Skip to content

Commit 82718ec

Browse files
RaphiMC1zun4
andcommitted
Use backend proxy for join server requests
Co-authored-by: Izuna <[email protected]> Closes #420
1 parent c769fae commit 82718ec

File tree

7 files changed

+154
-51
lines changed

7 files changed

+154
-51
lines changed

src/main/java/net/raphimc/viaproxy/protocoltranslator/viaproxy/ViaProxyConfig.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
import net.raphimc.viaproxy.protocoltranslator.ProtocolTranslator;
3939
import net.raphimc.viaproxy.saves.impl.accounts.Account;
4040
import net.raphimc.viaproxy.util.AddressUtil;
41+
import net.raphimc.viaproxy.util.Proxy;
4142
import net.raphimc.viaproxy.util.config.*;
4243
import net.raphimc.viaproxy.util.logging.Logger;
4344

4445
import java.io.File;
4546
import java.net.SocketAddress;
46-
import java.net.URI;
4747
import java.util.HashMap;
4848
import java.util.Map;
4949
import java.util.Stack;
@@ -107,8 +107,8 @@ public class ViaProxyConfig {
107107
"- type://address:port",
108108
"- type://username:password@address:port"
109109
})
110-
@TypeSerializer(ProxyUriTypeSerializer.class)
111-
private URI backendProxyUrl = null;
110+
@TypeSerializer(ProxyTypeSerializer.class)
111+
private Proxy backendProxy = null;
112112

113113
@Option("backend-haproxy")
114114
@Description("Send HAProxy protocol messages to the target server.")
@@ -383,12 +383,12 @@ public void setBetacraftAuth(final boolean betacraftAuth) {
383383
this.save();
384384
}
385385

386-
public URI getBackendProxyUrl() {
387-
return this.backendProxyUrl;
386+
public Proxy getBackendProxy() {
387+
return this.backendProxy;
388388
}
389389

390-
public void setBackendProxyUrl(final URI backendProxyUrl) {
391-
this.backendProxyUrl = backendProxyUrl;
390+
public void setBackendProxy(final Proxy backendProxy) {
391+
this.backendProxy = backendProxy;
392392
this.save();
393393
}
394394

src/main/java/net/raphimc/viaproxy/proxy/external_interface/ExternalInterface.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
package net.raphimc.viaproxy.proxy.external_interface;
1919

2020
import com.google.common.primitives.Longs;
21+
import com.mojang.authlib.minecraft.MinecraftSessionService;
22+
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
2123
import com.viaversion.viaversion.api.connection.UserConnection;
2224
import com.viaversion.viaversion.api.minecraft.ProfileKey;
2325
import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_0;
2426
import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_1;
2527
import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_3;
2628
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
29+
import net.lenni0451.commons.httpclient.proxy.SingleProxyAuthenticator;
2730
import net.raphimc.minecraftauth.step.bedrock.StepMCChain;
2831
import net.raphimc.minecraftauth.step.java.StepPlayerCertificates;
2932
import net.raphimc.netminecraft.packet.impl.login.C2SLoginHelloPacket;
@@ -38,8 +41,10 @@
3841
import net.raphimc.viaproxy.saves.impl.accounts.Account;
3942
import net.raphimc.viaproxy.saves.impl.accounts.BedrockAccount;
4043
import net.raphimc.viaproxy.saves.impl.accounts.MicrosoftAccount;
44+
import net.raphimc.viaproxy.util.Proxy;
4145
import net.raphimc.viaproxy.util.logging.Logger;
4246

47+
import java.net.Authenticator;
4348
import java.security.PrivateKey;
4449
import java.security.PublicKey;
4550
import java.security.SignatureException;
@@ -104,7 +109,21 @@ public static void joinServer(final String serverIdHash, final ProxyConnection p
104109
try {
105110
if (proxyConnection.getUserOptions().account() instanceof MicrosoftAccount microsoftAccount) {
106111
try {
107-
AuthLibServices.SESSION_SERVICE.joinServer(microsoftAccount.getGameProfile().getId(), microsoftAccount.getMcProfile().getMcToken().getAccessToken(), serverIdHash);
112+
if (ViaProxy.getConfig().getBackendProxy() == null) {
113+
AuthLibServices.SESSION_SERVICE.joinServer(microsoftAccount.getGameProfile().getId(), microsoftAccount.getMcProfile().getMcToken().getAccessToken(), serverIdHash);
114+
} else {
115+
final Proxy proxy = ViaProxy.getConfig().getBackendProxy();
116+
final MinecraftSessionService sessionService = new YggdrasilAuthenticationService(proxy.toJavaProxy()).createMinecraftSessionService();
117+
Authenticator prevAuthenticator = Authenticator.getDefault();
118+
try {
119+
if (proxy.getUsername() != null && proxy.getPassword() != null) {
120+
Authenticator.setDefault(new SingleProxyAuthenticator(proxy.getUsername(), proxy.getPassword()));
121+
}
122+
sessionService.joinServer(microsoftAccount.getGameProfile().getId(), microsoftAccount.getMcProfile().getMcToken().getAccessToken(), serverIdHash);
123+
} finally {
124+
Authenticator.setDefault(prevAuthenticator);
125+
}
126+
}
108127
} catch (Throwable e) {
109128
proxyConnection.kickClient("§cFailed to authenticate with Mojang servers! Please try again in a couple of seconds.");
110129
}

src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerChannelInitializer.java

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424
import io.netty.channel.Channel;
2525
import io.netty.channel.ChannelHandler;
2626
import io.netty.handler.codec.haproxy.HAProxyMessageEncoder;
27-
import io.netty.handler.proxy.HttpProxyHandler;
28-
import io.netty.handler.proxy.ProxyHandler;
29-
import io.netty.handler.proxy.Socks4ProxyHandler;
30-
import io.netty.handler.proxy.Socks5ProxyHandler;
3127
import net.raphimc.netminecraft.constants.MCPipeline;
3228
import net.raphimc.netminecraft.netty.codec.NoReadFlowControlHandler;
3329
import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer;
@@ -39,9 +35,6 @@
3935
import net.raphimc.viaproxy.protocoltranslator.impl.ViaProxyVLPipeline;
4036
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
4137

42-
import java.net.InetSocketAddress;
43-
import java.net.URI;
44-
import java.util.Locale;
4538
import java.util.function.Supplier;
4639

4740
public class Proxy2ServerChannelInitializer extends MinecraftChannelInitializer {
@@ -62,8 +55,8 @@ protected void initChannel(Channel channel) {
6255

6356
final ProxyConnection proxyConnection = ProxyConnection.fromChannel(channel);
6457

65-
if (ViaProxy.getConfig().getBackendProxyUrl() != null && !proxyConnection.getServerVersion().equals(BedrockProtocolVersion.bedrockLatest)) {
66-
channel.pipeline().addLast(VIAPROXY_PROXY_HANDLER_NAME, this.getProxyHandler());
58+
if (ViaProxy.getConfig().getBackendProxy() != null && !proxyConnection.getServerVersion().equals(BedrockProtocolVersion.bedrockLatest)) {
59+
channel.pipeline().addLast(VIAPROXY_PROXY_HANDLER_NAME, ViaProxy.getConfig().getBackendProxy().createNettyProxyHandler());
6760
}
6861
if (ViaProxy.getConfig().useBackendHaProxy()) {
6962
channel.pipeline().addLast(VIAPROXY_HAPROXY_ENCODER_NAME, HAProxyMessageEncoder.INSTANCE);
@@ -87,28 +80,4 @@ protected void initChannel(Channel channel) {
8780
}
8881
}
8982

90-
protected ProxyHandler getProxyHandler() {
91-
final URI proxyUrl = ViaProxy.getConfig().getBackendProxyUrl();
92-
final InetSocketAddress proxyAddress = new InetSocketAddress(proxyUrl.getHost(), proxyUrl.getPort());
93-
final String username = proxyUrl.getUserInfo() != null ? proxyUrl.getUserInfo().split(":")[0] : null;
94-
final String password = proxyUrl.getUserInfo() != null && proxyUrl.getUserInfo().contains(":") ? proxyUrl.getUserInfo().split(":")[1] : null;
95-
96-
switch (proxyUrl.getScheme().toUpperCase(Locale.ROOT)) {
97-
case "HTTP", "HTTPS" -> {
98-
if (username != null && password != null) return new HttpProxyHandler(proxyAddress, username, password);
99-
else return new HttpProxyHandler(proxyAddress);
100-
}
101-
case "SOCKS4" -> {
102-
if (username != null) return new Socks4ProxyHandler(proxyAddress, username);
103-
else return new Socks4ProxyHandler(proxyAddress);
104-
}
105-
case "SOCKS5" -> {
106-
if (username != null && password != null) return new Socks5ProxyHandler(proxyAddress, username, password);
107-
else return new Socks5ProxyHandler(proxyAddress);
108-
}
109-
}
110-
111-
throw new IllegalArgumentException("Unknown proxy type: " + proxyUrl.getScheme());
112-
}
113-
11483
}

src/main/java/net/raphimc/viaproxy/proxy/proxy2server/passthrough/PassthroughProxy2ServerChannelInitializer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ protected void initChannel(Channel channel) {
4141
return;
4242
}
4343

44-
if (ViaProxy.getConfig().getBackendProxyUrl() != null) {
45-
channel.pipeline().addLast(VIAPROXY_PROXY_HANDLER_NAME, this.getProxyHandler());
44+
if (ViaProxy.getConfig().getBackendProxy() != null) {
45+
channel.pipeline().addLast(VIAPROXY_PROXY_HANDLER_NAME, ViaProxy.getConfig().getBackendProxy().createNettyProxyHandler());
4646
}
4747
if (ViaProxy.getConfig().useBackendHaProxy()) {
4848
channel.pipeline().addLast(VIAPROXY_HAPROXY_ENCODER_NAME, HAProxyMessageEncoder.INSTANCE);

src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import net.raphimc.viaproxy.ui.elements.LinkLabel;
3434
import net.raphimc.viaproxy.ui.events.UICloseEvent;
3535
import net.raphimc.viaproxy.util.AddressUtil;
36+
import net.raphimc.viaproxy.util.Proxy;
3637
import net.raphimc.viaproxy.util.logging.Logger;
3738

3839
import javax.swing.*;
@@ -287,12 +288,12 @@ private void start() {
287288
}
288289
if (!proxyUrl.isBlank()) {
289290
try {
290-
ViaProxy.getConfig().setBackendProxyUrl(new URI(proxyUrl));
291+
ViaProxy.getConfig().setBackendProxy(new Proxy(new URI(proxyUrl)));
291292
} catch (URISyntaxException e) {
292293
throw new IllegalArgumentException(I18n.get("tab.general.error.invalid_proxy_url"));
293294
}
294295
} else {
295-
ViaProxy.getConfig().setBackendProxyUrl(null);
296+
ViaProxy.getConfig().setBackendProxy(null);
296297
}
297298
this.applyGuiState();
298299
this.viaProxyWindow.advancedTab.applyGuiState();
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.util;
19+
20+
import io.netty.handler.proxy.HttpProxyHandler;
21+
import io.netty.handler.proxy.ProxyHandler;
22+
import io.netty.handler.proxy.Socks4ProxyHandler;
23+
import io.netty.handler.proxy.Socks5ProxyHandler;
24+
import net.lenni0451.commons.httpclient.proxy.ProxyType;
25+
import net.lenni0451.commons.httpclient.utils.URLWrapper;
26+
27+
import java.net.InetSocketAddress;
28+
import java.net.SocketAddress;
29+
import java.net.URI;
30+
import java.util.Locale;
31+
32+
public class Proxy {
33+
34+
private final String protocol;
35+
private final SocketAddress address;
36+
private final String username;
37+
private final String password;
38+
39+
public Proxy(final URI uri) {
40+
this(uri.getScheme(), new InetSocketAddress(uri.getHost(), uri.getPort()), uri.getUserInfo());
41+
}
42+
43+
public Proxy(final String protocol, final SocketAddress address) {
44+
this(protocol, address, null, null);
45+
}
46+
47+
public Proxy(final String protocol, final SocketAddress address, final String userInfo) {
48+
this(protocol, address, userInfo != null ? userInfo.split(":", 2)[0] : null, userInfo != null ? (userInfo.split(":", 2).length > 1 ? userInfo.split(":", 2)[1] : null) : null);
49+
}
50+
51+
public Proxy(final String protocol, final SocketAddress address, final String username, final String password) {
52+
this.protocol = protocol.toUpperCase(Locale.ROOT);
53+
this.address = address;
54+
this.username = username;
55+
this.password = password;
56+
}
57+
58+
public ProxyHandler createNettyProxyHandler() {
59+
switch (this.protocol) {
60+
case "HTTP", "HTTPS" -> {
61+
if (this.username != null && this.password != null) return new HttpProxyHandler(this.address, this.username, this.password);
62+
else return new HttpProxyHandler(this.address);
63+
}
64+
case "SOCKS4" -> {
65+
if (this.username != null) return new Socks4ProxyHandler(this.address, this.username);
66+
else return new Socks4ProxyHandler(this.address);
67+
}
68+
case "SOCKS5" -> {
69+
if (this.username != null && this.password != null) return new Socks5ProxyHandler(this.address, this.username, this.password);
70+
else return new Socks5ProxyHandler(this.address);
71+
}
72+
default -> throw new IllegalArgumentException("Unsupported proxy protocol: " + this.protocol);
73+
}
74+
}
75+
76+
public java.net.Proxy toJavaProxy() {
77+
final ProxyType proxyType = switch (this.protocol) {
78+
case "HTTP", "HTTPS" -> ProxyType.HTTP;
79+
case "SOCKS4" -> ProxyType.SOCKS4;
80+
case "SOCKS5" -> ProxyType.SOCKS5;
81+
default -> throw new IllegalArgumentException("Unsupported proxy protocol: " + this.protocol);
82+
};
83+
return new net.lenni0451.commons.httpclient.proxy.ProxyHandler(proxyType, this.address, this.username, this.password).toJavaProxy();
84+
}
85+
86+
public URI toURI() {
87+
String userInfo = null;
88+
if (this.username != null) {
89+
userInfo = this.username;
90+
if (this.password != null) {
91+
userInfo += ":" + this.password;
92+
}
93+
}
94+
return URLWrapper.empty().setProtocol(this.protocol.toLowerCase(Locale.ROOT)).setHost(AddressUtil.toString(this.address)).setUserInfo(userInfo).toURI();
95+
}
96+
97+
public String getProtocol() {
98+
return this.protocol;
99+
}
100+
101+
public SocketAddress getAddress() {
102+
return this.address;
103+
}
104+
105+
public String getUsername() {
106+
return this.username;
107+
}
108+
109+
public String getPassword() {
110+
return this.password;
111+
}
112+
113+
}

src/main/java/net/raphimc/viaproxy/util/config/ProxyUriTypeSerializer.java renamed to src/main/java/net/raphimc/viaproxy/util/config/ProxyTypeSerializer.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,23 @@
1919

2020
import net.lenni0451.optconfig.serializer.ConfigTypeSerializer;
2121
import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig;
22+
import net.raphimc.viaproxy.util.Proxy;
2223

2324
import java.net.URI;
2425
import java.net.URISyntaxException;
2526

26-
public class ProxyUriTypeSerializer extends ConfigTypeSerializer<ViaProxyConfig, URI> {
27+
public class ProxyTypeSerializer extends ConfigTypeSerializer<ViaProxyConfig, Proxy> {
2728

28-
public ProxyUriTypeSerializer(final ViaProxyConfig config) {
29+
public ProxyTypeSerializer(final ViaProxyConfig config) {
2930
super(config);
3031
}
3132

3233
@Override
33-
public URI deserialize(final Class<URI> typeClass, final Object serializedObject) {
34+
public Proxy deserialize(final Class<Proxy> typeClass, final Object serializedObject) {
3435
final String proxyUrl = (String) serializedObject;
3536
if (!proxyUrl.isBlank()) {
3637
try {
37-
return new URI(proxyUrl);
38+
return new Proxy(new URI(proxyUrl));
3839
} catch (URISyntaxException e) {
3940
throw new IllegalArgumentException("Invalid proxy url: " + proxyUrl + ". Proxy url format: type://address:port or type://username:password@address:port");
4041
}
@@ -43,9 +44,9 @@ public URI deserialize(final Class<URI> typeClass, final Object serializedObject
4344
}
4445

4546
@Override
46-
public Object serialize(final URI object) {
47+
public Object serialize(final Proxy object) {
4748
if (object != null) {
48-
return object.toString();
49+
return object.toURI().toString();
4950
} else {
5051
return "";
5152
}

0 commit comments

Comments
 (0)