From c30a7be849bee652cdf1c950d05afe34a82902cc Mon Sep 17 00:00:00 2001 From: Fallen_Breath Date: Fri, 23 Feb 2024 02:31:15 +0800 Subject: [PATCH] compat upstream changes --- README.md | 1 - .../velocitypowered/proxy/VelocityServer.java | 8 +-- .../client/InitialLoginSessionHandler.java | 28 ++++++++- .../proxy/network/ConnectionManager.java | 57 ++++++++++++++----- .../proxy/tablist/TabListUuidRewriter.java | 16 +++--- 5 files changed, 82 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 1b722f64e4..d99f20ee73 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ A list of small tweaks I made: - Added proxy setting for authenticating player with `sessionserver.mojang.com` - The proxy setting is in the `auth-proxy` section in `velocity.toml`, of course you know how to fill it - Supported proxy types: `socks4`, `socks5`, `http` - - Due to [an issue](https://github.com/AsyncHttpClient/async-http-client/issues/1913) in the http library velocity uses, you can only use `http` proxy for now - If enabled, velocity will firstly try authenticating with the given proxy, if failed it will try again without the proxy - Implement UUID rewrite for TabList packets, like what bungeecord does diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 85ca7e4214..3cac9eb8b0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -265,9 +265,6 @@ void start() { this.cm.queryBind(configuration.getBind().getHostString(), configuration.getQueryPort()); } - // [fallen's fork] mojang auth proxy: create the proxied http client - cm.createProxiedHttpClient(); - Metrics.VelocityMetrics.startMetrics(this, configuration.getMetrics()); } @@ -603,8 +600,9 @@ public HttpClient createHttpClient() { } // [fallen's fork] mojang auth proxy - public AsyncHttpClient getAsyncProxiedHttpClient() { - return cm.getProxiedHttpClient(); + @Nullable + public HttpClient createProxiedHttpClient() { + return cm.createProxiedHttpClient(); } public Ratelimiter getIpAttemptLimiter() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java index 5cc5371c02..65a6f1450e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java @@ -52,6 +52,7 @@ import java.util.Arrays; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.BiConsumer; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.apache.logging.log4j.LogManager; @@ -215,7 +216,11 @@ public boolean handle(EncryptionResponsePacket packet) { .uri(URI.create(url)) .build(); final HttpClient httpClient = server.createHttpClient(); - httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()) + + // [fallen's fork] mojang auth proxy: make the request progress reuseable + @SuppressWarnings("unchecked") final BiConsumer[] requester = new BiConsumer[1]; + requester[0] = (client, retryable) -> + client.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()) .whenCompleteAsync((response, throwable) -> { if (mcConnection.isClosed()) { // The player disconnected after we authenticated them. @@ -223,6 +228,13 @@ public boolean handle(EncryptionResponsePacket packet) { } if (throwable != null) { + // [fallen's fork] mojang auth proxy: fail-able with proxy mode + if (retryable) { + logger.error("Unable to authenticate player (proxied), try without", throwable); + requester[0].accept(httpClient, false); + return; + } + logger.error("Unable to authenticate player", throwable); inbound.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); return; @@ -259,6 +271,10 @@ public boolean handle(EncryptionResponsePacket packet) { // Apparently an offline-mode user logged onto this online-mode proxy. inbound.disconnect( Component.translatable("velocity.error.online-mode-only", NamedTextColor.RED)); + } else if (retryable) { + // [fallen's fork] mojang auth proxy: fail-able with proxy mode + logger.error("Error authenticating with proxy, http status code {}, try without", response.statusCode()); + requester[0].accept(httpClient, false); } else { // Something else went wrong logger.error( @@ -278,6 +294,16 @@ public boolean handle(EncryptionResponsePacket packet) { } } }); + + // [fallen's fork] mojang auth proxy starts + final HttpClient proxiedHttpClient = server.createProxiedHttpClient(); + if (proxiedHttpClient != null) { + requester[0].accept(proxiedHttpClient, true); + } else { + requester[0].accept(httpClient, false); + } + // [fallen's fork] mojang auth proxy ends + } catch (GeneralSecurityException e) { logger.error("Unable to enable encryption", e); mcConnection.close(true); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java index 26928dc211..0e2c3f2dd9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java @@ -33,11 +33,16 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.WriteBufferWaterMark; import io.netty.util.concurrent.GlobalEventExecutor; +import java.io.IOException; import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; import java.net.http.HttpClient; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -64,11 +69,6 @@ public final class ConnectionManager { private final SeparatePoolInetNameResolver resolver; - // [fallen's fork] mojang auth proxy starts - private AsyncHttpClient proxiedHttpClient; - private final Supplier proxiedHttpClientSupplier; - // [fallen's fork] mojang auth proxy ends - /** * Initializes the {@code ConnectionManager}. * @@ -247,15 +247,46 @@ public HttpClient createHttpClient() { .build(); } - // [fallen's fork] mojang auth proxy starts - public AsyncHttpClient getProxiedHttpClient() { - return proxiedHttpClient; - } + // [fallen's fork] mojang auth proxy + @SuppressWarnings("checkstyle:MissingJavadocMethod") + @Nullable + public HttpClient createProxiedHttpClient() { + if (server.getConfiguration().isAuthProxyEnabled()) { + Proxy.Type proxyType = null; + String type = server.getConfiguration().getAuthProxyType(); + switch (type) { + case "socks4": + case "socks5": + proxyType = Proxy.Type.SOCKS; + break; + case "http": + proxyType = Proxy.Type.HTTP; + break; + default: + LOGGER.error("Bad auth proxy type {}", type); + } + if (proxyType != null) { + var hostname = server.getConfiguration().getAuthProxyHostname(); + var port = server.getConfiguration().getAuthProxyPort(); + var finalProxyType = proxyType; + return HttpClient.newBuilder() + .proxy(new ProxySelector() { + @Override + public List select(URI uri) { + return List.of(new Proxy(finalProxyType, new InetSocketAddress(hostname, port))); + } - public void createProxiedHttpClient() { - proxiedHttpClient = proxiedHttpClientSupplier.get(); + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { + // do nothing as what java.net.ProxySelector.of does + } + }) + .executor(this.workerGroup) + .build(); + } + } + return null; } - // [fallen's fork] mojang auth proxy ends public BackendChannelInitializerHolder getBackendChannelInitializer() { return this.backendChannelInitializer; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/TabListUuidRewriter.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/TabListUuidRewriter.java index 423b3d1fe4..6cd8a8f835 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/TabListUuidRewriter.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/TabListUuidRewriter.java @@ -18,9 +18,9 @@ package com.velocitypowered.proxy.tablist; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem; -import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo; -import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo; +import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItemPacket; +import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfoPacket; +import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket; import java.util.stream.Collectors; /** @@ -30,10 +30,10 @@ public class TabListUuidRewriter { /** * Rewrite uuid for a LegacyPlayerListItem packet. */ - public static void rewrite(ConnectedPlayer player, LegacyPlayerListItem packet) { + public static void rewrite(ConnectedPlayer player, LegacyPlayerListItemPacket packet) { packet.getItems().replaceAll(item -> { if (player.getOfflineUuid().equals(item.getUuid())) { - var newItem = new LegacyPlayerListItem.Item(player.getUniqueId()); + var newItem = new LegacyPlayerListItemPacket.Item(player.getUniqueId()); newItem.setName(item.getName()); newItem.setProperties(item.getProperties()); @@ -52,10 +52,10 @@ public static void rewrite(ConnectedPlayer player, LegacyPlayerListItem packet) /** * Rewrite uuid for a UpsertPlayerInfo packet. */ - public static void rewrite(ConnectedPlayer player, UpsertPlayerInfo packet) { + public static void rewrite(ConnectedPlayer player, UpsertPlayerInfoPacket packet) { packet.getEntries().replaceAll(entry -> { if (player.getOfflineUuid().equals(entry.getProfileId())) { - var newEntry = new UpsertPlayerInfo.Entry(player.getUniqueId()); + var newEntry = new UpsertPlayerInfoPacket.Entry(player.getUniqueId()); newEntry.setProfile(player.getGameProfile()); newEntry.setListed(entry.isListed()); @@ -74,7 +74,7 @@ public static void rewrite(ConnectedPlayer player, UpsertPlayerInfo packet) { /** * Rewrite uuid for a RemovePlayerInfo packet. */ - public static void rewrite(ConnectedPlayer player, RemovePlayerInfo packet) { + public static void rewrite(ConnectedPlayer player, RemovePlayerInfoPacket packet) { var newProfiles = packet.getProfilesToRemove().stream() .map(uuid -> { if (player.getOfflineUuid().equals(uuid)) {