我正在尝试使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支持将Soc​​ks 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/

10-16 12:46