Dieser Commit ist enthalten in:
Lixfel 2022-10-01 12:06:13 +02:00
Ursprung 7080792d52
Commit 96e4d46eb5
6 geänderte Dateien mit 67 neuen und 19 gelöschten Zeilen

BIN
AltAuth.png Normale Datei

Binäre Datei nicht angezeigt.

Nachher

Breite:  |  Höhe:  |  Größe: 76 KiB

Datei anzeigen

@ -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")

Datei anzeigen

@ -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)

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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);

Datei anzeigen

@ -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):