Bugfixes
Dieser Commit ist enthalten in:
Ursprung
7080792d52
Commit
96e4d46eb5
BIN
AltAuth.png
Normale Datei
BIN
AltAuth.png
Normale Datei
Binäre Datei nicht angezeigt.
Nachher Breite: | Höhe: | Größe: 76 KiB |
22
README.md
22
README.md
|
@ -1,2 +1,24 @@
|
|||
# AltAuth
|
||||
|
||||
AltAuth is a solution to allow players with Mojang account, (untested) banned accounts and (untested) Multiplayer
|
||||
disabled accounts to join online mode Minecraft servers depending on client and server support.
|
||||
This works by redirecting the session server requests to a proxy specified by the server.
|
||||
|
||||
In comparison to the trustless authentication method proposed by Aizistral
|
||||
https://github.com/Aizistral-Studios/Trustless-Authentication this authentication method enables joining of Mojang
|
||||
account players, prevents man in the middle attacks (like vanilla authentication) and is compatible to clients without
|
||||
AltAuth, but requires a trusted third/second party.
|
||||
|
||||
## Usage
|
||||
|
||||
The build/libs/AltAuth-*-all.jar (produced by running `./gradlew build`) is a valid Fabric (client and server 1.19.2),
|
||||
Bukkit/Spigot/Paper (1.8 - 1.19.2) and BungeeCord/Waterfall mod/plugin. The server needs to be in online mode and
|
||||
specify the domain or ip address of an AltAuth web proxy.
|
||||
|
||||
Since https is a requirement and the example proxy `proxy.py` not yet supporting https the proxy has to run behind a
|
||||
https proxy currently. Configuration of the proxy can be done in the first lines of the proxy script.
|
||||
Banned and multiplayer disabled user support has not been tested yet and is therefore disabled by default.
|
||||
|
||||
## AltAuth Protocol and Proxy behaviour
|
||||
|
||||
![Sequence diagram describing protocol and principle](AltAuth.png "Sequence diagram describing protocol and principle")
|
|
@ -8,6 +8,7 @@ import io.netty.channel.Channel;
|
|||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
@ -29,7 +30,7 @@ public class ProtocolInjector implements Listener {
|
|||
private static final Class<?> dedicatedPlayerList = ReflectionUtil.getClass("net.minecraft.server.dedicated.DedicatedPlayerList");
|
||||
private static final FieldWrapper<?> getPlayerList = ReflectionUtil.getField(craftServer, dedicatedPlayerList, 0);
|
||||
private static final Class<?> playerList = ReflectionUtil.getClass("net.minecraft.server.players.PlayerList");
|
||||
private static final Class<?> minecraftServer = ReflectionUtil.getClass("net.minecraft.server.MinecraftServer");
|
||||
public static final Class<?> minecraftServer = ReflectionUtil.getClass("net.minecraft.server.MinecraftServer");
|
||||
private static final FieldWrapper<?> getMinecraftServer = ReflectionUtil.getField(playerList, minecraftServer, 0);
|
||||
private static final Class<?> serverConnection = ReflectionUtil.getClass("net.minecraft.server.network.ServerConnection");
|
||||
private static final FieldWrapper<?> getServerConnection = ReflectionUtil.getField(minecraftServer, serverConnection, 0);
|
||||
|
@ -44,6 +45,7 @@ public class ProtocolInjector implements Listener {
|
|||
|
||||
private final Plugin plugin;
|
||||
private final String handlerName;
|
||||
private final Object minecraftServerInstance;
|
||||
private final List<?> connections;
|
||||
private boolean closed;
|
||||
|
||||
|
@ -53,7 +55,8 @@ public class ProtocolInjector implements Listener {
|
|||
private ProtocolInjector(final Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.handlerName = "altauth";
|
||||
this.connections = getConnections.get(getServerConnection.get(getMinecraftServer.get(getPlayerList.get(plugin.getServer()))));
|
||||
this.minecraftServerInstance = getMinecraftServer.get(getPlayerList.get(plugin.getServer()));
|
||||
this.connections = getConnections.get(getServerConnection.get(minecraftServerInstance));
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
|
@ -62,6 +65,10 @@ public class ProtocolInjector implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
public Object minecraftServer() {
|
||||
return minecraftServerInstance;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
if(closed)
|
||||
|
|
|
@ -10,29 +10,47 @@ import java.util.logging.Level;
|
|||
|
||||
public class SessionServiceInjector {
|
||||
|
||||
private static final Class<?> SESSION_SERVICE = ReflectionUtil.getClass("com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService");
|
||||
private static final Class<?> MINECRAFT_SESSION_SERVICE = ReflectionUtil.getClass("com.mojang.authlib.minecraft.MinecraftSessionService");
|
||||
private static final Class<?> YGGDRASIL_SESSION_SERVICE = ReflectionUtil.getClass("com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService");
|
||||
|
||||
private static final ReflectionUtil.FieldWrapper<URL> JOIN_URL = ReflectionUtil.getField(SESSION_SERVICE, URL.class, "JOIN_URL");
|
||||
private static final ReflectionUtil.FieldWrapper<URL> CHECK_URL = ReflectionUtil.getField(SESSION_SERVICE, URL.class, "CHECK_URL");
|
||||
private static final ReflectionUtil.FieldWrapper<URL> JOIN_URL = ReflectionUtil.getField(YGGDRASIL_SESSION_SERVICE, URL.class, 0);
|
||||
private static final ReflectionUtil.FieldWrapper<URL> CHECK_URL = ReflectionUtil.getField(YGGDRASIL_SESSION_SERVICE, URL.class, 1);
|
||||
|
||||
private final Object sessionService;
|
||||
private final URL joinUrlBackup;
|
||||
private final URL checkUrlBackup;
|
||||
|
||||
public SessionServiceInjector(String altAuthServer) {
|
||||
joinUrlBackup = JOIN_URL.get(null);
|
||||
checkUrlBackup = CHECK_URL.get(null);
|
||||
|
||||
altAuthServer = "https://" + altAuthServer + "/session/minecraft/";
|
||||
|
||||
if(ReflectionUtil.MINECRAFT_VERSION < 17) { //TODO maybe 16 (untested)
|
||||
sessionService = null;
|
||||
} else if (ReflectionUtil.MINECRAFT_VERSION < 19) {
|
||||
sessionService = ReflectionUtil.getField(ProtocolInjector.minecraftServer, MINECRAFT_SESSION_SERVICE, 0).get(
|
||||
ProtocolInjector.instance.minecraftServer()
|
||||
);
|
||||
} else {
|
||||
Class<?> services = ReflectionUtil.getClass("net.minecraft.server.Services");
|
||||
sessionService = ReflectionUtil.getField(services, MINECRAFT_SESSION_SERVICE, 0).get(
|
||||
ReflectionUtil.getField(ProtocolInjector.minecraftServer, services, 0).get(
|
||||
ProtocolInjector.instance.minecraftServer()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
joinUrlBackup = JOIN_URL.get(sessionService);
|
||||
checkUrlBackup = CHECK_URL.get(sessionService);
|
||||
|
||||
try {
|
||||
JOIN_URL.set(null, new URL(altAuthServer + "join"));
|
||||
CHECK_URL.set(null, new URL(altAuthServer + "hasJoined"));
|
||||
JOIN_URL.set(sessionService, new URL(altAuthServer + "join"));
|
||||
CHECK_URL.set(sessionService, new URL(altAuthServer + "hasJoined"));
|
||||
} catch (MalformedURLException e) {
|
||||
AltAuthBukkit.getInstance().getLogger().log(Level.SEVERE, "Could not create AltAuth URLs", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void revert() {
|
||||
JOIN_URL.set(null, joinUrlBackup);
|
||||
CHECK_URL.set(null, checkUrlBackup);
|
||||
JOIN_URL.set(sessionService, joinUrlBackup);
|
||||
CHECK_URL.set(sessionService, checkUrlBackup);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,19 +12,19 @@ public final class ReflectionUtil {
|
|||
private ReflectionUtil() {}
|
||||
|
||||
private static final String ORG_BUKKIT_CRAFTBUKKIT;
|
||||
private static final boolean REPLACE_NET_MINECRAFT;
|
||||
public static final int MINECRAFT_VERSION;
|
||||
static {
|
||||
String craftbukkitPackage;
|
||||
boolean legacyNms;
|
||||
int minecraftVersion;
|
||||
try {
|
||||
craftbukkitPackage = Bukkit.getServer().getClass().getPackage().getName();
|
||||
legacyNms = Integer.parseInt(craftbukkitPackage.split("[.](?=[^.]*$)")[1].split("_")[1]) < 17;
|
||||
minecraftVersion = Integer.parseInt(craftbukkitPackage.split("[.](?=[^.]*$)")[1].split("_")[1]);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
craftbukkitPackage = "";
|
||||
legacyNms = false;
|
||||
minecraftVersion = 0;
|
||||
}
|
||||
ORG_BUKKIT_CRAFTBUKKIT = craftbukkitPackage;
|
||||
REPLACE_NET_MINECRAFT = legacyNms;
|
||||
MINECRAFT_VERSION = minecraftVersion;
|
||||
}
|
||||
|
||||
private static final String LEGACY_NET_MINECRAFT_SERVER = ORG_BUKKIT_CRAFTBUKKIT.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
@ -120,7 +120,7 @@ public final class ReflectionUtil {
|
|||
try {
|
||||
if(name.startsWith("org.bukkit.craftbukkit")) {
|
||||
return Class.forName(ORG_BUKKIT_CRAFTBUKKIT + name.substring(22));
|
||||
} else if(REPLACE_NET_MINECRAFT && name.startsWith("net.minecraft")) {
|
||||
} else if(MINECRAFT_VERSION < 17 && name.startsWith("net.minecraft")) {
|
||||
return Class.forName(LEGACY_NET_MINECRAFT_SERVER + "." + name.split("[.](?=[^.]*$)")[1]);
|
||||
} else {
|
||||
return Class.forName(name);
|
||||
|
|
3
proxy.py
3
proxy.py
|
@ -22,7 +22,8 @@ bind_to = ('127.0.0.1', 8080)
|
|||
allow_mojang_accounts = True
|
||||
# Should banned microsoft accounts ("UserBannedException") be allowed to join?
|
||||
# Should accounts with disabled multiplayer ("InsufficientPrivilegesException") be allowed to join?
|
||||
allowed_microsoft_accounts = ("InsufficientPrivilegesException", "UserBannedException")
|
||||
allowed_microsoft_accounts = ()
|
||||
#allowed_microsoft_accounts = ("InsufficientPrivilegesException", "UserBannedException")
|
||||
|
||||
|
||||
def moj_request(url, data=None):
|
||||
|
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren