8

我编写了一个应用程序,它(除其他外)在 Windows 中运行本地服务,充当 Firefox 的 SOCKS v5 代理。

我现在处于调试阶段,发现某些网站无法正常工作。例如,Facebook.com 上用于图片上传的 Java 小程序失败,因为无法查找域。

我的应用程序覆盖了隐藏的 FF 配置设置network.proxy.socks__remote__dns将其设置为true。该应用程序的全部目的是允许在防火墙后访问网站(例如,如果用户在中国),因此此设置对于确保域也被远程解析(而不仅仅是 HTTP 请求)至关重要。

在 JRE6 设置(在此处记录)中没有等效设置,并且由于远程 DNS 解析是 SOCKS v5 而不是 v4 的功能,因为文档似乎暗示我担心这是不可能的。

如何以编程方式确保 JRE 对所有请求(包括 DNS)使用 SOCKS v5 代理?


更新:重现此问题的步骤:

  1. 确保您位于阻止(或重定向)互联网访问(包括 DNS )的防火墙后面
  2. 安装 PuTTY 并在您选择的某个端口号(例如 9870)上添加动态 SSH 隧道。然后登录到可以完全访问互联网的远程服务器
  3. 启动 Firefox,您将无法浏览网页
  4. 在 FF 网络设置中,将 SOCKS v5 代理设置为 localhost:9870
  5. 在 FF 中转到 about:config,将network.proxy.socks__remote__dns更改为 true
  6. 您现在可以浏览网页了。
  7. 转到 facebook.com,登录,转到您的个人资料并尝试使用图片上传器 java 小程序添加一些图片
  8. 它将失败,并出现一系列类似于以下的类未找到错误:

    加载:类 com.facebook.facebookphotouploader5.FacebookPhotoUploader5.class not found

我相信这是失败的,因为 JRE 无法解析该类所在的域。我的这种信念基于以下事实:文档(http://java.sun.com/javase/6/docs/technotes/guides/deployment/deployment-guide/properties.html)仅讨论 SOCKS v4(其中据我所知不支持远程DNS)。我的 deployment.properties 文件位于 %APPDATA%\Sun\Java\Deployment。我可以确认我在 Java 控制面板中所做的修改已写入该文件。如果我覆盖 Java 的网络设置而不是“使用浏览器设置”并尝试手动使用 SOCKS 代理设置,我仍然有问题。似乎没有一种简单的方法可以强制 JRE 通过代理远程执行 DNS。


更新 2:

没有 SOCKS 代理,来自我的本地客户端

  • www.facebook.com 解析为 203.161.230.171
  • upload.facebook.com 解析为 64.33.88.161

两个主机都无法访问(因为防火墙)

如果我登录到远程服务器,我会得到:

  • www.facebook.com 69.63.187.17
  • 上传.facebook.com 69.63.178.32

几分钟后,这两个 IP 都会发生变化,因为 Facebook 似乎使用了循环 DNS 和其他负载平衡。

在 Firefox 中设置代理设置后,我可以毫无困难地导航到 www.facebook.com(因为 DNS 正在代理上远程解析)。当我使用 Java 小程序访问页面时,它会因我已经报告的堆栈跟踪消息而失败。

但是,如果我编辑 Windows\System32\drivers\etc\hosts,为 upload.facebook.com 添加正确的 IP,我可以让小程序加载并正常工作(有时需要重新启动 FF)。

这个证据似乎支持我的理论,即 Java 运行时没有解析代理上的 DNS,而只是通过它路由流量。

我的应用程序用于大规模部署,需要与其他站点(不仅仅是 facebook)上的 java 小程序一起使用。我真的需要解决这个问题。


更新 3 Stacktrace 转储 ZZ Coder 请求的文件:

load: class com.facebook.facebookphotouploader5.FacebookPhotoUploader5.class not found.
java.lang.ClassNotFoundException: com.facebook.facebookphotouploader5.FacebookPhotoUploader5.class
    at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
    at sun.plugin2.applet.Plugin2Manager.createApplet(Unknown Source)
    at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
    at sun.plugin2.applet.Applet2ClassLoader.access$000(Unknown Source)
    at sun.plugin2.applet.Applet2ClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    ... 7 more
Exception: java.lang.ClassNotFoundException: com.facebook.facebookphotouploader5.FacebookPhotoUploader5.class

Dumping class loader cache...
 Live entry: key=http://upload.facebook.com/controls/2008.10.10_v5.5.8/,FacebookPhotoUploader5.jar,FacebookPhotoUploader5.jar, refCount=1, threadGroup=sun.plugin2.applet.Applet2ThreadGroup[name=http://upload.facebook.com/controls/2008.10.10_v5.5.8/-threadGroup,maxpri=4]
Done.
4

2 回答 2

5

new InetSocketAddress(hosta, port) 默认解析 IP,SocksSocketImpl 如果目标地址被解析,则首先使用 IP。如果你想要 RemoteDNS,你可以新建一个 Socket 你一个代理,然后连接到一个由 InetSocketAddress.createUnresolved(host, port) 构造的 InetSocketAddress。

你的 Socks Server 必须是 SOCKS5,java SocksSocketImpl 自动检测是版本。

Proxy p = new Proxy(Proxy.Type.SOCKS, paddr);
Socket s = new Socket(p);
InetSocketAddress addr = InetSocketAddress.createUnresolved("host.blocked.by.gfw", port);
s.connect(addr);
于 2011-12-16T03:54:19.500 回答
1

JRE 当然支持 Socks V5。我从 Java 1.4 开始就一直在使用它。如果您的 SOCKS 服务器是 V4,JRE 仅使用 V4。服务器响应的第一个字节必须是 5。

V4 支持是错误的。它仅适用于 IP 地址,不适用于域名,因为它事先不知道如何解析域名。因此,如果 Socks 可以正常工作,您必须使用 V5。

我怀疑您的代理设置不正确,因此袜子根本不起作用。这应该很容易用 Wireshark 追踪。只需检查小程序正在使用哪个端口。

堆栈跟踪也将非常有帮助。它会告诉你是否使用了袜子。例如,

load: class test.MyApplet.class not found.
java.lang.ClassNotFoundException: <name>.class
at sun.applet.AppletClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.applet.AppletClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.applet.AppletClassLoader.loadCode(Unknown Source)
at sun.applet.AppletPanel.createApplet(Unknown Source)
at sun.plugin.AppletViewer.createApplet(Unknown Source)
at sun.applet.AppletPanel.runLoader(Unknown Source)
at sun.applet.AppletPanel.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Caused by: java.net.SocketException: Malformed reply from SOCKS server
at java.net.SocksSocketImpl.readSocksReply(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)

我将 SOCKS 代理指向我的 HTTP 服务器,因此预计会出现此错误。

于 2009-09-23T03:13:51.773 回答