Tag Archives: Proxy

关于 SOCKS 代理的远端 DNS 解析

经常使用 SOCKS 代理服务器的同志们会发现一种现象,即使 SOCKS 代理服务器设置正确,某些网站仍然无法访问,比如某著名微博网站。其一般原因都是 DNS 污染 (DNS cache poisoning)。

值得庆幸的是 SOCKS 5 协议增加了对 UDP 数据包的支持,DNS 查询是通过 UDP 传输的,所以我们可以使 DNS 查询数据包也走 SOCKS 5 代理来进行远端 DNS 解析(Remote DNS Lookup)。 SOCKS 5是通过将域名直接提交给 SOCKS 服务器来进行远端 DNS 解析的,即 Address Type 0x03,而非上述所说使用 UDP 通道解析。DNS 服务是 Internet 的基础服务,要求 DNS 解析应当尽量地快,所以浏览器默认不会使用远端 DNS 解析。在目前的常用浏览器中,貌似只有 Firefox 支持可选的远端 DNS 解析,方法见这里

我没有找到 IE 和 Chrome 支持远端 DNS 解析的方法,从讨论来看似乎是不支持的,Opera 则根本没有 SOCKS 代理支持。

即便是 Firefox,对远端 DNS 解析的支持也是有一些问题的。我的经验是:Firefox 只有在设置里面写死 SOCKS v5 的代理服务器设置时,才会支持远端 DNS 解析;当使用自动代理设置脚本(.pac )时,即使返回 SOCKS 代理,Firefox 也不会进行远端 DNS 解析。当使用自动代理设置脚本(.pac )时,以 SOCKS5 返回代理地址,可以支持远端 DNS 解析。

结论是,如果想要远端 DNS 解析,只能手动切换 SOCKS 代理,不能使用自动代理配置脚本。

网友 forkei 的重要评论

chrome 的 Proxy Switchy 1.4.2 版本插件可以很好的解决这个问题。Firefox 的 FoxyProxy 插件也可以很好的解决 DNS 污染。支持插件扩展功能的浏览器功能就是强大。IE 内核浏览器和 opera 只有通过 polipo 或者 privoxy 将 socks 代理转为 http 代理才行,麻烦。

Tohr - HTTP 层上的洋葱路由器

Tohr (The Onion HTTP Router) 是我上个星期写的一个小的研究项目,它的名字起源于 Tor (The Onion Router)。简单地来说,它就是试图在 HTTP 层上实现类似于 Tor 实现的功能—— HTTP 层上的 HTTP(S) 隧道。

这个 idea 不是我想出来的,而是受到 GAppProxy 的启发(GAppProxy 是一个 great work)。但是 GAppProxy 只是利用 Google 的平台,而且受到 GAE 的很多限制。那么我的贡献呢,就是把这个 idea 通用化,设计一个协议使其支持多平台,解决了 GAppProxy 的一些 bug,完善了 HTTPS 的支持。(哦,忘记了,我还给它起了一个很 fancy 的名字 ^_^)目前 Tohr 的路由器可以是 Google App Engine 上的 Python 网站,也可以是普通的 Apache+PHP 站点。

Tohr 是怎么工作的?

Tohr 的工作原理

Tohr 的工作原理见上图。首先您得拥有一个墙外的主机(免费或者收费的)作为 Tohr 路由器,Tohr目前支持 Google App Engine 和 Apache+PHP 服务器,您将对应的 tohr-router 文件上传到服务器上;然后您在本地运行一个 tohr-daemon 守护程序,设置 tohr-daemon 连接 tohr-router 的 url,tohr-daemon 默认会开启 9090 来提供一个 HTTP(S) 代理服务,您只需要将浏览器的 HTTP 代理设置为 localhost:9090,您的访问请求就会通过 tohr-daemon 转发到 Tohr 路由器上,这样就能通过它来访问被防火墙禁止访问的网站了。

Tohr 是给什么人用的?

目前来讲 Tohr 仍然不很完善,而且还需要加入对其它类型的主机,比如 asp.net、jsp 的支持,还有对多跳和匿名的支持,还没有一个针对普通用户易用性的优化。要求普通用户都有一个墙外主机也是件比较为难的事情(虽然申请一个国外免费 PHP 空间并不困难,比如这里),因此 Tohr 目前还仅适合爱折腾的人使用,尤其是懂 Python 或 PHP 的爱折腾的人,所以在这里是找不到一个一步步的图文教程教普通用户怎么配置的。当然,如果哪位用户愿意做一个,请发送到邮件列表或者提交补丁,我很乐意将它放在项目文档里。

浏览器自动选择 Proxy 配置案例

本文主要讨论的是浏览器代理服务器设置技术,文中出现的人名、公司名或者域名均为化名,如有雷同,纯属巧合。

在某些地方上网时,比如南京大学的校园网中,某些公司的局域网中,我们可能需要用到代理服务器。代理服务器的切换一直是一个让人头痛的话题,IE 浏览器有一个 ProxySwither Lite 软件可以用来切换代理,Firefox 有一批插件可以用来切换代理,但是,很难用它们来解决全局性的问题,使用前的配置也是比较麻烦的事情。那么,有没有一种方法可以一劳永逸地解决这个问题呢?答案是有的,那就是 PAC(Proxy Auto-Config) 文件。

使用 PAC 文件我们可以做到:1. IE、Firefox、Opera...浏览器使用同一个代理配置方案,Windows、Linux多系统使用同一个代理配置方案;2. 针对特定的域名,使用特定的代理;3. 针对特定的 IP 范围,使用特定的代理;4. 针对特定的 URL 模式,使用特定的代理。

下面我们来看一个案例:

假设小明的电脑位于 C 公司的局域网中,C 公司为了某些需要禁止员工访问某些站点,例如: alogspot.com 和 bwitter.com ,但是小明的工作和学习需要经常访问这些站点,公司的网管给小明带来了很大不便。不过小明很聪明,他找到了一个可以访问被禁那些站点的一个代理 127.0.0.1:8000。虽然通过该代理小明可以访问这些站点,但是切换代理和浏览器设置始终是麻烦;特别是在用 doogle.com 搜索到的某些文章位于 alogspot.com 时,一不小心点了搜索结果,到搜索引擎 doogle.com 的连接就会有很大一会儿被重置。因为小明的代理速度比较慢,总不能用代理上所有网站吧?这真是件麻烦事,小明该怎么办呢?

虽然很头痛,但是互联网的开拓者们给我们留下了那么多遗产,怎么能不好好利用呢?小明翻出了一个尘封已久的 Wiki 页面,缓缓回忆起那古老的 Javascript 语言,顿时有了主意,于是他写出了下面这个 PAC 脚本:

// 看看域名是不是本地站点
function isLocalHost(host)
{
  if( dnsDomainIs(host, "localhost") )
    return true;
  return false;
}
// 看看域名是不是禁止访问的站点
function isBlockedHost(host)
{
  if( dnsDomainIs(host, "alogspot.com") ||
      dnsDomainIs(host, "bwitter.com") )
    return true;
  return false;
}
// 看看搜索结果 URL 中是不是包含被禁止访问的关键字
function isBlockedURL(url, host)
{
  if( dnsDomainIs(host, "doogle.com") ) {
    if ( shExpMatch(url, "*alogspot.com*") ||
         shExpMatch(url, "*bwitter.com*") )
      return true;
  }
  return false;
}
// 看看 IP 在不在本地 IP 范围内
function isLocalIP(addr)
{
  if( isInNet(addr,"127.0.0.0","255.0.0.0") ||
      isInNet(addr,"10.0.0.0","255.0.0.0") ||
      isInNet(addr,"192.168.0.0","255.255.0.0") ||
      isInNet(addr,"172.16.0.0","255.255.0.0") )
    return true;
  return false;
}
// 看看 IP 在不在被禁止访问的 IP 范围内
function isBlockedIP(addr)
{
  return false;
}
// 看看 IP 地址是不是 IPv6 地址
function isIPV6(addr)
{
  if( shExpMatch(addr, "*:*") )
    return true;
  return false;
}
// 这是浏览器默认调用的函数接口
function FindProxyForURL(url, host)
{
  var direct      = "DIRECT";
  var httpProxy   = "PROXY localhost:8000";
  var socksProxy  = "SOCKS localhost:9050"// 留着做个参考
 
  if(isLocalHost(host)) {
    // 如果是本地域名,那就直连
    return direct;
  } else if(isBlockedURL(url, host) || isBlockedHost(host)) {
    // 如果是被禁止访问的域名,或者搜索结果 URL 中含有被禁止访问的关键词,那就走代理
    return httpProxy;
  }

  if(!isResolvable(host)) {
    // 如果域名不能解析,那就直连
    return direct;
  }
  // 解析域名到 IP 地址
  var IpAddr = dnsResolve(host);

  if(isLocalIP(IpAddr) || isIPV6(IpAddr)) {
    // 如果是本地 IP 或者 IPv6 地址,那就直连
    return direct;
  } else if(isBlockedIP(IpAddr)) {
    // 如果是被禁止访问的地址,那就走代理
    return httpProxy;
  } else {
    // 剩下的,唉,就直连吧
    return direct;
  }
}

小明将以上内容保存为 C:proxy.pac(~/proxy.pac),然后到

Firefox 中,选择 工具->选项->高级->网络->设置(Edit->Preferences->Advanced->Network->Settings),将 file:///c:/proxy.pac(file:///home/username/proxy.pac)填入“自动代理配置 URL”(Automatic proxy configuration URL)文本框中;

再到

IE 中,选择 工具->Internet 选项->连接->局域网设置,勾选使用自动配置脚本,填入 file://c:/proxy.pac;

再到

Opera 中,选择 Tools->Preferences->Advanced->Network->Proxy Servers,勾选上 Use automatic proxy configuration,填入 file://c:/proxy.pac。

从此,小明就开始了自己幸福的互联网冲浪生活,再也没有看到那曾经熟悉的“到该网站的连接已被重置”消息了。

PS:若要 Firefox 和 Chrome 支持远端 DNS 解析,需使用 SOCKS5 作为代理的前缀。

解决 GAppProxy Set-Cookie 和 HTTPS Cert Bugs

我自己写了一个类似 GAppProxy 的工具,支持 Python 和 PHP,有兴趣可以看这里。 研究 GAppProxy … Continue reading

内网穿透反向隧道代理技术

本文的主要目的是利用使 ssh 服务器(外网)通过客户端(内网)代理上网以及反向控制客户端(内网),不需要网络管理员权限,不需要 NAT。即可上网主机 A 位于内网,不可上网主机 B 位于外网,A … Continue reading

Tor - Anonymity on Line

其实以前就见过 Baosheng 在博客里推荐 Tor 这个工具,据说可以访问 Wikipedia,只是当时潜意识里觉得太麻烦,就懒得搞。昨天晚上 Baosheng bg,请 … Continue reading