From 352fc9b8904d0e99eca1d307490e91c64ca88ce5 Mon Sep 17 00:00:00 2001 From: cowwen Date: Sat, 9 Mar 2019 14:54:14 +0800 Subject: [PATCH 1/3] socks5 proxy resolve destination domain --- .../netty/channel/ChannelManager.java | 7 +++++ .../netty/request/NettyRequestSender.java | 12 ++++++++- .../asynchttpclient/proxy/ProxyServer.java | 26 ++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java index 6a5ed05972..4ca3a8039b 100755 --- a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java +++ b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java @@ -33,6 +33,8 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedWriteHandler; +import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.NameResolver; import io.netty.util.Timer; import io.netty.util.concurrent.*; @@ -56,6 +58,7 @@ import javax.net.ssl.SSLException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ThreadFactory; @@ -430,6 +433,10 @@ protected void initChannel(Channel channel) throws Exception { channel.pipeline().addFirst(SOCKS_HANDLER, socksProxyHandler); } }); + AddressResolver addressResolver = proxy.getAddressResolver(); + if (addressResolver != null) { + socksBootstrap.resolver((AddressResolverGroup) addressResolver); + } promise.setSuccess(socksBootstrap); } else { diff --git a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java index 03255731f7..8563773d12 100755 --- a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java +++ b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java @@ -37,6 +37,7 @@ import org.asynchttpclient.netty.channel.*; import org.asynchttpclient.netty.timeout.TimeoutsHolder; import org.asynchttpclient.proxy.ProxyServer; +import org.asynchttpclient.proxy.ProxyType; import org.asynchttpclient.resolver.RequestHostnameResolver; import org.asynchttpclient.uri.Uri; import org.asynchttpclient.ws.WebSocketUpgradeHandler; @@ -46,6 +47,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.util.ArrayList; import java.util.List; import static io.netty.handler.codec.http.HttpHeaderNames.EXPECT; @@ -342,7 +344,15 @@ private Future> resolveAddresses(Request request, InetSocketAddress unresolvedRemoteAddress = InetSocketAddress.createUnresolved(proxy.getHost(), port); scheduleRequestTimeout(future, unresolvedRemoteAddress); return RequestHostnameResolver.INSTANCE.resolve(request.getNameResolver(), unresolvedRemoteAddress, asyncHandler); - + } else if (proxy != null && proxy.isResolveDomain() && ProxyType.SOCKS_V5 == proxy.getProxyType()) { + // resolve domain in socks 5 server + int port = uri.getExplicitPort(); + InetSocketAddress unresolvedRemoteAddress = InetSocketAddress.createUnresolved(uri.getHost(), port); + final Promise> unResolvedPromise = ImmediateEventExecutor.INSTANCE.newPromise(); + List unresolvedLiWrapper = new ArrayList<>(1); + unresolvedLiWrapper.add(unresolvedRemoteAddress); + unResolvedPromise.trySuccess(unresolvedLiWrapper); + return unResolvedPromise; } else { int port = uri.getExplicitPort(); diff --git a/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java b/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java index 13c33590be..42793b821c 100644 --- a/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java +++ b/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java @@ -16,8 +16,10 @@ */ package org.asynchttpclient.proxy; +import io.netty.resolver.AddressResolver; import org.asynchttpclient.Realm; +import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -36,6 +38,8 @@ public class ProxyServer { private final Realm realm; private final List nonProxyHosts; private final ProxyType proxyType; + private AddressResolver addressResolver; + // server can resolve domain in socks 5 public ProxyServer(String host, int port, int securedPort, Realm realm, List nonProxyHosts, ProxyType proxyType) { @@ -47,6 +51,12 @@ public ProxyServer(String host, int port, int securedPort, Realm realm, List nonProxyHosts, + ProxyType proxyType, AddressResolver addressResolver) { + this(host, port, securedPort, realm, nonProxyHosts, proxyType); + this.addressResolver = addressResolver; + } + public String getHost() { return host; } @@ -71,6 +81,14 @@ public ProxyType getProxyType() { return proxyType; } + public AddressResolver getAddressResolver() { + return addressResolver; + } + + public boolean isResolveDomain() { + return addressResolver != null; + } + /** * Checks whether proxy should be used according to nonProxyHosts settings of * it, or we want to go directly to target host. If null proxy is @@ -118,6 +136,7 @@ public static class Builder { private Realm realm; private List nonProxyHosts; private ProxyType proxyType; + private AddressResolver addressResolver; public Builder(String host, int port) { this.host = host; @@ -157,11 +176,16 @@ public Builder setProxyType(ProxyType proxyType) { return this; } + public Builder setAddressResolver(AddressResolver addressResolver) { + this.addressResolver = addressResolver; + return this; + } + public ProxyServer build() { List nonProxyHosts = this.nonProxyHosts != null ? Collections.unmodifiableList(this.nonProxyHosts) : Collections.emptyList(); ProxyType proxyType = this.proxyType != null ? this.proxyType : ProxyType.HTTP; - return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType); + return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType, this.addressResolver); } } } From 129b9e6914e0688b3ca8790eb63a49b0fe46535d Mon Sep 17 00:00:00 2001 From: cowwen Date: Mon, 11 Mar 2019 11:36:47 +0800 Subject: [PATCH 2/3] websocket proxy in http is need... --- .../netty/channel/ChannelManager.java | 118 ++++++++++-------- .../netty/request/NettyRequestSender.java | 1 + .../asynchttpclient/proxy/ProxyServer.java | 23 ++-- 3 files changed, 80 insertions(+), 62 deletions(-) diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java index 4ca3a8039b..c1c6a883d1 100755 --- a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java +++ b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java @@ -33,7 +33,6 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedWriteHandler; -import io.netty.resolver.AddressResolver; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.NameResolver; import io.netty.util.Timer; @@ -58,7 +57,6 @@ import javax.net.ssl.SSLException; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.SocketAddress; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ThreadFactory; @@ -395,59 +393,79 @@ public Future getBootstrap(Uri uri, NameResolver nameRes final Promise promise = ImmediateEventExecutor.INSTANCE.newPromise(); - if (uri.isWebSocket() && proxy == null) { - return promise.setSuccess(wsBootstrap); - - } else if (proxy != null && proxy.getProxyType().isSocks()) { - Bootstrap socksBootstrap = httpBootstrap.clone(); - ChannelHandler httpBootstrapHandler = socksBootstrap.config().handler(); - - nameResolver.resolve(proxy.getHost()).addListener((Future whenProxyAddress) -> { - if (whenProxyAddress.isSuccess()) { - socksBootstrap.handler(new ChannelInitializer() { - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - httpBootstrapHandler.handlerAdded(ctx); - super.handlerAdded(ctx); - } - - @Override - protected void initChannel(Channel channel) throws Exception { - InetSocketAddress proxyAddress = new InetSocketAddress(whenProxyAddress.get(), proxy.getPort()); - Realm realm = proxy.getRealm(); - String username = realm != null ? realm.getPrincipal() : null; - String password = realm != null ? realm.getPassword() : null; - ProxyHandler socksProxyHandler; - switch (proxy.getProxyType()) { - case SOCKS_V4: - socksProxyHandler = new Socks4ProxyHandler(proxyAddress, username); - break; - - case SOCKS_V5: - socksProxyHandler = new Socks5ProxyHandler(proxyAddress, username, password); - break; - - default: - throw new IllegalArgumentException("Only SOCKS4 and SOCKS5 supported at the moment."); - } - channel.pipeline().addFirst(SOCKS_HANDLER, socksProxyHandler); - } - }); - AddressResolver addressResolver = proxy.getAddressResolver(); - if (addressResolver != null) { - socksBootstrap.resolver((AddressResolverGroup) addressResolver); - } - promise.setSuccess(socksBootstrap); + // direct connect + if (proxy == null) { + if (uri.isWebSocket()) { + promise.setSuccess(wsBootstrap); + } else { + promise.setSuccess(httpBootstrap); + } + return promise; + } - } else { - promise.setFailure(whenProxyAddress.cause()); - } - }); + // http proxy + if (proxy.getProxyType().isHttp()) { + promise.setSuccess(httpBootstrap); + return promise; + } + // socks proxy + Bootstrap bs; + ChannelHandler handler; + if (uri.isWebSocket()) { + bs = wsBootstrap; + handler = wsBootstrap.config().handler(); } else { - promise.setSuccess(httpBootstrap); + bs = httpBootstrap; + handler = httpBootstrap.config().handler(); } + final Bootstrap wrapFinalBs = bs; + final ChannelHandler wrapFinalHandler = handler; + + nameResolver.resolve(proxy.getHost()).addListener((Future whenProxyAddress) -> { + if (!whenProxyAddress.isSuccess()) { + promise.setFailure(whenProxyAddress.cause()); + return; + } + wrapFinalBs.handler(new ChannelInitializer() { + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + wrapFinalHandler.handlerAdded(ctx); + super.handlerAdded(ctx); + } + + @Override + protected void initChannel(Channel channel) throws Exception { + InetSocketAddress proxyAddress = new InetSocketAddress(whenProxyAddress.get(), proxy.getPort()); + Realm realm = proxy.getRealm(); + String username = realm != null ? realm.getPrincipal() : null; + String password = realm != null ? realm.getPassword() : null; + ProxyHandler socksProxyHandler; + switch (proxy.getProxyType()) { + case SOCKS_V4: + socksProxyHandler = new Socks4ProxyHandler(proxyAddress, username); + break; + + case SOCKS_V5: + socksProxyHandler = new Socks5ProxyHandler(proxyAddress, username, password); + break; + + default: + throw new IllegalArgumentException("Only SOCKS4 and SOCKS5 supported at the moment."); + } + channel.pipeline().addFirst(SOCKS_HANDLER, socksProxyHandler); + } + }); + if (proxy.getProxyType().isSocks()) { + AddressResolverGroup addressResolverGroup = proxy.getAddressResolverGroup(); + if (addressResolverGroup != null) { + wrapFinalBs.resolver(addressResolverGroup); + } + } + promise.setSuccess(wrapFinalBs); + }); + return promise; } diff --git a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java index 8563773d12..ba851f2d56 100755 --- a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java +++ b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java @@ -351,6 +351,7 @@ private Future> resolveAddresses(Request request, final Promise> unResolvedPromise = ImmediateEventExecutor.INSTANCE.newPromise(); List unresolvedLiWrapper = new ArrayList<>(1); unresolvedLiWrapper.add(unresolvedRemoteAddress); + scheduleRequestTimeout(future, unresolvedRemoteAddress); unResolvedPromise.trySuccess(unresolvedLiWrapper); return unResolvedPromise; } else { diff --git a/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java b/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java index 42793b821c..3fc38096f7 100644 --- a/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java +++ b/client/src/main/java/org/asynchttpclient/proxy/ProxyServer.java @@ -16,10 +16,9 @@ */ package org.asynchttpclient.proxy; -import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; import org.asynchttpclient.Realm; -import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -38,7 +37,7 @@ public class ProxyServer { private final Realm realm; private final List nonProxyHosts; private final ProxyType proxyType; - private AddressResolver addressResolver; + private AddressResolverGroup addressResolverGroup; // server can resolve domain in socks 5 public ProxyServer(String host, int port, int securedPort, Realm realm, List nonProxyHosts, @@ -52,9 +51,9 @@ public ProxyServer(String host, int port, int securedPort, Realm realm, List nonProxyHosts, - ProxyType proxyType, AddressResolver addressResolver) { + ProxyType proxyType, AddressResolverGroup addressResolverGroup) { this(host, port, securedPort, realm, nonProxyHosts, proxyType); - this.addressResolver = addressResolver; + this.addressResolverGroup = addressResolverGroup; } public String getHost() { @@ -81,12 +80,12 @@ public ProxyType getProxyType() { return proxyType; } - public AddressResolver getAddressResolver() { - return addressResolver; + public AddressResolverGroup getAddressResolverGroup() { + return addressResolverGroup; } public boolean isResolveDomain() { - return addressResolver != null; + return addressResolverGroup != null; } /** @@ -136,7 +135,7 @@ public static class Builder { private Realm realm; private List nonProxyHosts; private ProxyType proxyType; - private AddressResolver addressResolver; + private AddressResolverGroup addressResolverGroup; public Builder(String host, int port) { this.host = host; @@ -176,8 +175,8 @@ public Builder setProxyType(ProxyType proxyType) { return this; } - public Builder setAddressResolver(AddressResolver addressResolver) { - this.addressResolver = addressResolver; + public Builder setAddressResolverGroup(AddressResolverGroup addressResolverGroup) { + this.addressResolverGroup = addressResolverGroup; return this; } @@ -185,7 +184,7 @@ public ProxyServer build() { List nonProxyHosts = this.nonProxyHosts != null ? Collections.unmodifiableList(this.nonProxyHosts) : Collections.emptyList(); ProxyType proxyType = this.proxyType != null ? this.proxyType : ProxyType.HTTP; - return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType, this.addressResolver); + return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType, this.addressResolverGroup); } } } From 4a6affc6bef945d6dc3f0f975cbcfbc95f889aa0 Mon Sep 17 00:00:00 2001 From: cowwen Date: Fri, 15 Mar 2019 16:57:24 +0800 Subject: [PATCH 3/3] resolve domain based on proxy type is socks and setting a addressResolverGroup --- .../org/asynchttpclient/netty/request/NettyRequestSender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java index ba851f2d56..5e2bf8495a 100755 --- a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java +++ b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java @@ -344,7 +344,7 @@ private Future> resolveAddresses(Request request, InetSocketAddress unresolvedRemoteAddress = InetSocketAddress.createUnresolved(proxy.getHost(), port); scheduleRequestTimeout(future, unresolvedRemoteAddress); return RequestHostnameResolver.INSTANCE.resolve(request.getNameResolver(), unresolvedRemoteAddress, asyncHandler); - } else if (proxy != null && proxy.isResolveDomain() && ProxyType.SOCKS_V5 == proxy.getProxyType()) { + } else if (proxy != null && proxy.isResolveDomain() && proxy.getProxyType().isSocks()) { // resolve domain in socks 5 server int port = uri.getExplicitPort(); InetSocketAddress unresolvedRemoteAddress = InetSocketAddress.createUnresolved(uri.getHost(), port);