我正在尝试使java.net中的Socks v4开箱即用,而我似乎已经成功了!
大概我正在使用的代码是这样的:
class SocketImplFactorySocks4 implements SocketImplFactory {
@Override
public SocketImpl createSocketImpl() {
System.out.println("Socket implementation triggered");
try {
return socketSocks4Factory();
} catch (Exception e) {
e.printStackTrace();
throw new Error("Can't go further");
}
}
private SocketImpl socketSocks4Factory() throws
[...] {
Class<?> aClass = Class.forName("java.net.SocksSocketImpl");
Constructor<?> cons = aClass.getDeclaredConstructor();
if (!cons.isAccessible())
cons.setAccessible(true);
Object socket = cons.newInstance();
Method method = socket.getClass().getDeclaredMethod("setV4");
if (!method.isAccessible())
method.setAccessible(true);
method.invoke(socket);
Field field = socket.getClass().getDeclaredField("useV4");
field.setAccessible(true);
Object value = field.get(socket);
return (SocketImpl) socket;
}
}
长话短说,当我创建一个套接字并传递-DsocksProxyHost和-DsocksProxyPort时,它可以工作。
我的问题是,当我在junit测试中使用相同的代码时,我可以通过Reflections检查将Socket.impl.useV4设置为true,在系统范围内设置socksProxy *设置,但是当我使用套接字时,它避免了完全使用代理(我可以在Wireshark中看到它)。
它是JUnit或Gradle,但是我已经达到了极限。请建议我下一步该去哪里。 build.gradle.kts供引用:
tasks{
test{
systemProperty("socksProxyHost", "localhost")
systemProperty("socksProxyPort", "8080")
}
}
提前致谢!
最佳答案
好吧,我花了太多时间弄清楚了,但是我做到了。我最初的目标是测试我的Socks v4服务器代码,但途中有两个问题:
1)即使Java Socket支持将Socks v4作为客户端,默认情况下也不启用。而且没有办法翻转拨动开关。
2)解决了#1问题后,我尝试编写E2E测试以吸烟整个过程,但是由于某种原因,即使切换(useV4)是正确的,避免进入Socks代理是。这就是我在此附带的内容。
为了解决第一个问题,我实现了SocketImplFactory(请参阅上面的问题)。
解决这个问题的原因是我的管理员背景,即使直到最近才开始。 :)我分离了原始的可疑对象(JUnit和Gradle),并在一个独立的psvm文件中进行了测试。该测试无效,但仍避免通过代理。这就是我的命:本地主机异常!
基本上,Java核心库中存在localhost(127.0.0.1,::等)的硬编码异常。经过一些搜索后,我遇到了DsocksNonProxyHosts选项。正如您可能已经猜到的那样,这没有帮助:)
最终,我得到了this答案,其中提到我可能需要实现ProxySelector。我做了: static class myProxySelector extends ProxySelector {
@Override
public List<Proxy> select(URI uri) {
List<Proxy> proxyl = new ArrayList<Proxy>(1);
InetSocketAddress saddr = InetSocketAddress.createUnresolved("localhost", 1080);
Proxy proxy = SocksProxy.create(saddr, 4);
proxyl.add(proxy);
System.out.println("Selecting Proxy for " + uri.toASCIIString());
return proxyl;
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
if (uri == null || sa == null || ioe == null) {
throw new IllegalArgumentException("Arguments can't be null.");
}
}
}
整个套接字设置如下所示: private void setupSocket() throws IOException {
Socket.setSocketImplFactory(new SocketImplFactorySocks4());
ProxySelector proxySelector = new myProxySelector();
ProxySelector.setDefault(proxySelector);
proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1080));
}
现在,我想要的所有东西都可以工作:我都可以E2E测试我的socks4代码,并且可以在localhost进行。
关于java - SocketImpl和JUnit/Gradle,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61160871/