mirror of
https://github.com/ViaVersion/ViaProxy.git
synced 2024-11-02 08:50:26 +01:00
Implemented HAProxy protocol for backend connections
This commit is contained in:
parent
af3ab5f6eb
commit
038782a60d
@ -44,6 +44,7 @@ public class Options {
|
|||||||
public static boolean ONLINE_MODE;
|
public static boolean ONLINE_MODE;
|
||||||
public static boolean OPENAUTHMOD_AUTH;
|
public static boolean OPENAUTHMOD_AUTH;
|
||||||
public static boolean BETACRAFT_AUTH;
|
public static boolean BETACRAFT_AUTH;
|
||||||
|
public static URI PROXY_URL; // Example: type://address:port or type://username:password@address:port
|
||||||
|
|
||||||
// GUI only config options
|
// GUI only config options
|
||||||
public static Account MC_ACCOUNT;
|
public static Account MC_ACCOUNT;
|
||||||
@ -56,7 +57,7 @@ public class Options {
|
|||||||
public static boolean INTERNAL_SRV_MODE; // Example: ip\7port\7version\7mppass
|
public static boolean INTERNAL_SRV_MODE; // Example: ip\7port\7version\7mppass
|
||||||
public static boolean LOCAL_SOCKET_AUTH;
|
public static boolean LOCAL_SOCKET_AUTH;
|
||||||
public static String RESOURCE_PACK_URL; // Example: http://example.com/resourcepack.zip
|
public static String RESOURCE_PACK_URL; // Example: http://example.com/resourcepack.zip
|
||||||
public static URI PROXY_URL; // Example: type://address:port or type://username:password@address:port
|
public static boolean HAPROXY_PROTOCOL;
|
||||||
|
|
||||||
public static void parse(final String[] args) throws IOException {
|
public static void parse(final String[] args) throws IOException {
|
||||||
final OptionParser parser = new OptionParser();
|
final OptionParser parser = new OptionParser();
|
||||||
@ -76,6 +77,7 @@ public class Options {
|
|||||||
final OptionSpec<Void> betaCraftAuth = parser.accepts("betacraft_auth", "Use BetaCraft authentication servers for classic");
|
final OptionSpec<Void> betaCraftAuth = parser.accepts("betacraft_auth", "Use BetaCraft authentication servers for classic");
|
||||||
final OptionSpec<String> resourcePackUrl = parser.acceptsAll(asList("resource_pack_url", "resource_pack", "rpu", "rp"), "URL of a resource pack which all connecting clients can optionally download").withRequiredArg().ofType(String.class);
|
final OptionSpec<String> resourcePackUrl = parser.acceptsAll(asList("resource_pack_url", "resource_pack", "rpu", "rp"), "URL of a resource pack which all connecting clients can optionally download").withRequiredArg().ofType(String.class);
|
||||||
final OptionSpec<String> proxyUrl = parser.acceptsAll(asList("proxy_url", "proxy"), "URL of a SOCKS(4/5)/HTTP(S) proxy which will be used for TCP connections").withRequiredArg().ofType(String.class);
|
final OptionSpec<String> proxyUrl = parser.acceptsAll(asList("proxy_url", "proxy"), "URL of a SOCKS(4/5)/HTTP(S) proxy which will be used for TCP connections").withRequiredArg().ofType(String.class);
|
||||||
|
final OptionSpec<Void> haProxyProtocol = parser.acceptsAll(asList("haproxy-protocol", "haproxy"), "Send HAProxy protocol messages to the backend server");
|
||||||
PluginManager.EVENT_MANAGER.call(new PreOptionsParseEvent(parser));
|
PluginManager.EVENT_MANAGER.call(new PreOptionsParseEvent(parser));
|
||||||
|
|
||||||
final OptionSet options = parser.parse(args);
|
final OptionSet options = parser.parse(args);
|
||||||
@ -113,6 +115,7 @@ public class Options {
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HAPROXY_PROTOCOL = options.has(haProxyProtocol);
|
||||||
PluginManager.EVENT_MANAGER.call(new PostOptionsParseEvent(options));
|
PluginManager.EVENT_MANAGER.call(new PostOptionsParseEvent(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import io.netty.channel.ChannelFutureListener;
|
|||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import io.netty.handler.codec.haproxy.*;
|
||||||
import net.raphimc.netminecraft.constants.ConnectionState;
|
import net.raphimc.netminecraft.constants.ConnectionState;
|
||||||
import net.raphimc.netminecraft.constants.MCPackets;
|
import net.raphimc.netminecraft.constants.MCPackets;
|
||||||
import net.raphimc.netminecraft.constants.MCPipeline;
|
import net.raphimc.netminecraft.constants.MCPipeline;
|
||||||
@ -61,6 +62,8 @@ import net.raphimc.viaproxy.util.logging.Logger;
|
|||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.channels.UnresolvedAddressException;
|
import java.nio.channels.UnresolvedAddressException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@ -69,6 +72,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -239,8 +243,6 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||||||
Logger.u_info("connect", this.proxyConnection.getC2P().remoteAddress(), this.proxyConnection.getGameProfile(), "[" + clientVersion.getName() + " <-> " + serverVersion.getName() + "] Connecting to " + serverAddress.getAddress() + ":" + serverAddress.getPort());
|
Logger.u_info("connect", this.proxyConnection.getC2P().remoteAddress(), this.proxyConnection.getGameProfile(), "[" + clientVersion.getName() + " <-> " + serverVersion.getName() + "] Connecting to " + serverAddress.getAddress() + ":" + serverAddress.getPort());
|
||||||
try {
|
try {
|
||||||
this.proxyConnection.connectToServer(serverAddress, serverVersion);
|
this.proxyConnection.connectToServer(serverAddress, serverVersion);
|
||||||
this.proxyConnection.getChannel().writeAndFlush(new C2SHandshakePacket(clientVersion.getOriginalVersion(), serverAddress.getAddress(), serverAddress.getPort(), packet.intendedState)).await().addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
this.proxyConnection.setConnectionState(packet.intendedState);
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (e instanceof ConnectException || e instanceof UnresolvedAddressException) { // Trust me, this is not always false
|
if (e instanceof ConnectException || e instanceof UnresolvedAddressException) { // Trust me, this is not always false
|
||||||
this.proxyConnection.kickClient("§cCould not connect to the backend server!\n§cTry again in a few seconds.");
|
this.proxyConnection.kickClient("§cCould not connect to the backend server!\n§cTry again in a few seconds.");
|
||||||
@ -249,6 +251,19 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
|
|||||||
this.proxyConnection.kickClient("§cAn error occurred while connecting to the backend server: " + e.getMessage() + "\n§cCheck the console for more information.");
|
this.proxyConnection.kickClient("§cAn error occurred while connecting to the backend server: " + e.getMessage() + "\n§cCheck the console for more information.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Options.HAPROXY_PROTOCOL) {
|
||||||
|
final InetSocketAddress sourceAddress = (InetSocketAddress) this.proxyConnection.getC2P().remoteAddress();
|
||||||
|
final InetSocketAddress targetAddress = (InetSocketAddress) this.proxyConnection.getChannel().remoteAddress();
|
||||||
|
final HAProxyProxiedProtocol protocol = sourceAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6;
|
||||||
|
final HAProxyTLV tlv = new HAProxyTLV((byte) 0xE0, Unpooled.buffer().writeInt(clientVersion.getOriginalVersion()));
|
||||||
|
|
||||||
|
final HAProxyMessage haProxyMessage = new HAProxyMessage(HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, protocol, sourceAddress.getAddress().getHostAddress(), targetAddress.getAddress().getHostAddress(), sourceAddress.getPort(), targetAddress.getPort(), Collections.singletonList(tlv));
|
||||||
|
this.proxyConnection.getChannel().writeAndFlush(haProxyMessage).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.proxyConnection.getChannel().writeAndFlush(new C2SHandshakePacket(clientVersion.getOriginalVersion(), serverAddress.getAddress(), serverAddress.getPort(), packet.intendedState)).await().addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||||
|
this.proxyConnection.setConnectionState(packet.intendedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLoginHello(C2SLoginHelloPacket1_7 packet) throws NoSuchAlgorithmException, InvalidKeySpecException, AuthenticationException {
|
private void handleLoginHello(C2SLoginHelloPacket1_7 packet) throws NoSuchAlgorithmException, InvalidKeySpecException, AuthenticationException {
|
||||||
|
@ -22,6 +22,7 @@ import com.viaversion.viaversion.connection.UserConnectionImpl;
|
|||||||
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
|
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.handler.codec.haproxy.HAProxyMessageEncoder;
|
||||||
import io.netty.handler.proxy.HttpProxyHandler;
|
import io.netty.handler.proxy.HttpProxyHandler;
|
||||||
import io.netty.handler.proxy.ProxyHandler;
|
import io.netty.handler.proxy.ProxyHandler;
|
||||||
import io.netty.handler.proxy.Socks4ProxyHandler;
|
import io.netty.handler.proxy.Socks4ProxyHandler;
|
||||||
@ -29,11 +30,11 @@ import io.netty.handler.proxy.Socks5ProxyHandler;
|
|||||||
import net.raphimc.netminecraft.constants.MCPipeline;
|
import net.raphimc.netminecraft.constants.MCPipeline;
|
||||||
import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer;
|
import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer;
|
||||||
import net.raphimc.netminecraft.packet.registry.PacketRegistryUtil;
|
import net.raphimc.netminecraft.packet.registry.PacketRegistryUtil;
|
||||||
|
import net.raphimc.viaprotocolhack.util.VersionEnum;
|
||||||
import net.raphimc.viaproxy.cli.options.Options;
|
import net.raphimc.viaproxy.cli.options.Options;
|
||||||
import net.raphimc.viaproxy.plugins.PluginManager;
|
import net.raphimc.viaproxy.plugins.PluginManager;
|
||||||
import net.raphimc.viaproxy.plugins.events.Proxy2ServerChannelInitializeEvent;
|
import net.raphimc.viaproxy.plugins.events.Proxy2ServerChannelInitializeEvent;
|
||||||
import net.raphimc.viaproxy.plugins.events.types.ITyped;
|
import net.raphimc.viaproxy.plugins.events.types.ITyped;
|
||||||
import net.raphimc.viaproxy.protocolhack.impl.ViaProxyVPHPipeline;
|
|
||||||
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
|
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
@ -53,14 +54,18 @@ public class Proxy2ServerChannelInitializer extends MinecraftChannelInitializer
|
|||||||
channel.close();
|
channel.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final ProxyConnection proxyConnection = ProxyConnection.fromChannel(channel);
|
||||||
|
|
||||||
final UserConnection user = new UserConnectionImpl(channel, true);
|
final UserConnection user = new UserConnectionImpl(channel, true);
|
||||||
new ProtocolPipelineImpl(user);
|
new ProtocolPipelineImpl(user);
|
||||||
ProxyConnection.fromChannel(channel).setUserConnection(user);
|
proxyConnection.setUserConnection(user);
|
||||||
|
|
||||||
if (Options.PROXY_URL != null) {
|
if (Options.PROXY_URL != null && !proxyConnection.getServerVersion().equals(VersionEnum.bedrockLatest)) {
|
||||||
channel.pipeline().addLast("viaproxy-proxy-handler", this.getProxyHandler());
|
channel.pipeline().addLast("viaproxy-proxy-handler", this.getProxyHandler());
|
||||||
}
|
}
|
||||||
|
if (Options.HAPROXY_PROTOCOL) {
|
||||||
|
channel.pipeline().addLast("viaproxy-haproxy-encoder", HAProxyMessageEncoder.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
super.initChannel(channel);
|
super.initChannel(channel);
|
||||||
channel.attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY).set(PacketRegistryUtil.getHandshakeRegistry(true));
|
channel.attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY).set(PacketRegistryUtil.getHandshakeRegistry(true));
|
||||||
|
Loading…
Reference in New Issue
Block a user