当有 SOCKS 代理时,为啥我的脚本遵循 /etc/hosts 而浏览器不遵循?

Posted

技术标签:

【中文标题】当有 SOCKS 代理时,为啥我的脚本遵循 /etc/hosts 而浏览器不遵循?【英文标题】:Why my script follows /etc/hosts but the browsers do not, when there is a SOCKS proxy?当有 SOCKS 代理时,为什么我的脚本遵循 /etc/hosts 而浏览器不遵循? 【发布时间】:2013-06-19 07:43:24 【问题描述】:

我在办公室的 MacBook 无法访问互联网。所以我通过 SSH 设置了一个即时 SOCKS 代理来访问 ***。我主要使用我的 MacBook 进行开发,所以我依靠 /etc/hosts 和虚拟主机在本地测试一些站点。

但是,当我尝试向/etc/hosts 添加条目时,浏览器无法访问我预期的站点...

我的 MacBook 的 WIFI 已关闭并已连接到公司 LAN:

 IP address:  192.168.8.250
 Subnet mask: 255.255.255.0
 Router:      192.168.8.1
 DNS server:  8.8.8.8

默认情况下,没有互联网访问。

有一个 Linux 开发盒 (192.168.12.128) 可以访问互联网,所以我设置了一个即时 SOCKS 代理来为我的 MacBook 获得互联网访问权限:

 ssh -fND localhost:30000 ohho@192.168.12.128

然后在我的 MacBook 的“系统偏好设置”>“网络”>“代理”中

 (Enable) SOCKS Proxy
 SOCKS Proxy sever: 127.0.0.1:30000
 Bypass proxy settings for these Hosts & Domains:
   *.local, 169.254/16, 127.0.0.1

现在我可以上网了,到目前为止一切顺利。

为了开发,我在/etc/hosts 中设置了一些条目用于虚拟主机:

 127.0.0.1 air.company.com

bash:

 $ ping air.company.com
 PING air.ohho.es (127.0.0.1): 56 data bytes
 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.046 ms

 $ curl air.company.com
 <html>OK</html>

看起来不错,curl 很好地返回了index.html 的内容。

但是,如果我尝试在浏览器(Safari/Chrome/Firefox)中打开站点:http://air.company.com,它们都不会像curl 那样返回结果。 Chrome 报错:

此网页不可用该网页http://air.company.com/ 可能暂时关闭,或者它可能已永久移动到新的 网址。错误 120 (net::ERR_SOCKS_CONNECTION_FAILED):未知 错误。

如果我在/etc/hosts 中添加另一个条目:

 127.0.0.1 www.microsoft.com

bash 中,看起来还可以:

 $ ping www.microsoft.com
 PING www.microsoft.com (127.0.0.1): 56 data bytes
 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.047 ms
 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.128 ms
 ^C
 --- www.microsoft.com ping statistics ---
 2 packets transmitted, 2 packets received, 0.0% packet loss
 round-trip min/avg/max/stddev = 0.047/0.087/0.128/0.041 ms

 $ curl www.microsoft.com
 <html>OK</html>

我也尝试使用 ruby​​ 脚本:

 require 'socket'
 require 'curl'

 ip = IPSocket.getaddress('www.microsoft.com')
 puts ip

 puts

 http = Curl.get("http://www.microsoft.com/")
 puts http.body_str

输出看起来不错:

 $ bundle exec ruby openweb.rb 
 127.0.0.1

 <html>OK</html>

但是,当我使用浏览器时,浏览器会返回来自 real Microsoft 网站的 Web 服务器的内容,而不是来自我的 MacBook (127.0.01) 的内容。为什么?

附言:

如果我禁用 SOCKS 代理,浏览器会正确返回来自 127.0.0.1 的内容。

如果我断开网线,浏览器会正确返回来自 127.0.0.1 的内容。

【问题讨论】:

【参考方案1】:

SOCKS5 将远程进行 DNS 查找;这对安全来说是件好事。

我认为您想要的是指示您的浏览器不要将代理用于内部或您的自定义开发地址。

为此,请设置“绕过这些主机和域的代理设置:”以包括 *.company.com。如果您有特别复杂的设置,您可以设置一个proxy access control(又名.pac)文件,该文件允许非常精细地控制通过代理的内容和直接访问的内容。

【讨论】:

【参考方案2】:

我会尽量回答,因为我已经遇到了这个问题。

当您使用 Socks5 连接时,您的 ip 解析被转发到 socks 服务器。

在版本 5 中,SOCKS 实现可以接收完整的域名作为目标和源地址[1](第 4 页)。

在 Mac OS 上,默认值为 SOCKS 5,如 (NSStreamSOCKSProxyVersionKey) 处的 [2] 所示。

因此默认情况下,mac 客户端将使用 SOCKS5 并会转发 DNS 请求。

我希望这能回答您的问题: “当有 SOCKS 代理时,为什么我的脚本遵循 /etc/hosts 而浏览器不遵循?” --> 因为 SOCKS5 实现转发 dns 请求:)

问候

1 - http://www.ietf.org/rfc/rfc1928.txt

2 - https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSStream_Class/Reference/Reference.html#//apple_ref/doc/c_ref/NSStreamSOCKSProxyConfigurationKey

【讨论】:

【参考方案3】:

使用 SOCKSv4a 和 SOCKSv5 客户端实际上能够让服务器连接到域 name,而不仅仅是地址 (http://en.wikipedia.org/wiki/SOCKS#SOCKS4a)。

                                                      ----------
                                                      -   DNS  -
                                                      ┐---------
                                                     .
                                                    .
----------------                   ----------------.-
-              ====================-                -
- Browser      = CON microsoft.com - SOCKS Server   -
-              ====================-                -
----------------                   ------------------

而且由于 SOCKS 服务器具有 Internet 访问权限,您可以看到 Microsoft 的站点,而不是您的本地版本。


想法:

如果您能够将 SOCKS 协议的版本更改为版本 4,它应该可以工作。 从长远来看可能更好:在浏览器中禁用远程 DNS,至少 Firefox 支持此设置:Network.proxy.socks.remote_dns。

【讨论】:

【参考方案4】:

这是一个 DNS 问题。尝试在本地解析名称。

【讨论】:

【参考方案5】:

我也遇到这个问题,只改/etc/host入口就解决了

只需删除:

127.0.0.1 www.microsoft.com

并添加:

192.168.8.250 www.microsoft.com

简而言之,添加您的服务器ip 地址而不是loopback ip

【讨论】:

以上是关于当有 SOCKS 代理时,为啥我的脚本遵循 /etc/hosts 而浏览器不遵循?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 SOCKS5 UDP 实现不起作用?

为啥 HTTP/HTTPS 代理和 Socks 代理可以在一个端口上工作?

为啥 Windows 上的 IE/Chrome 不支持端口 27977 上的 SOCKS5 代理? [关闭]

Socks代理的原理

如何通过 socks 代理使 python 请求工作

在Centos7下搭建Socks5代理服务器