使用 Pow 和 Privoxy 绕开 OS X 的沙盒限制和 SOCKS5 兼容问题

Apple 在 OS X 上推行沙盒之后,发现原来能用 PAC 代理配置不能用于所有程序了,原因是因为启用沙盒的程序无法访问 PAC 文件。除此之外,也发现了 SOCKS5 的兼容问题(如 Safari、Tweetbot),也就意味着在日益严峻的天朝网络环境里某些提高生产力的工具,如 shadowsocks ,就半残废了,只能走全局的 SOCKS 代理,而想要访问大陆站点的时候,比如优酷,这明显不科学,只能想办法解决。

沙盒的权限问题

虽然沙盒政策不让程序访问未授权的文件,不过对于「远程」文件倒没限制,所以我们可以把 PAC 文件部署在本地的服务器上。

安装 Pow 或 Anvil参考,使用 Apache/nginx 也可以,总之可以通过类似 http://localhost/proxy.pac 的方式访问本地的 PAC 文件即可。

以 Anvil 为例,安装并启动后,将 PAC 文件所在目录拖曳到状态栏的图标即可,得到如 http://pac.dev/ 的地址。将加上文件名后的完整地址,如 http://pac.dev/proxy.pac,复制到 Network Proxies 设置里 Automatic Proxy Configuration 的文本框里:

Automatic Proxy Conguration with Anvil

SOCKS5 的问题

虽然绕过了沙盒的限制,但是 Safari 和 Tweetbot 是不支持 SOCKS5 的,而 Chrome/Firefox 却只支持 SOCKS5,这里就有两种方法。

第一种,PAC 里这样写:

    'SOCKS5 127.0.0.1:8080;SOCKS 127.0.0.1:8080'

第二种,把 SOCSK5 转换成都支持的 HTTP 代理,这就需要使用 Privoxy。Privoxy 非常强大,但是比 PAC 复杂,如非需要,建议还是用第一种方法处理。

注意:本文是通过 homebrew 来安装 Privoxy,配置方式和通过官方安装指南安装的有所区别。

打开命令行依次执行以下命令:

brew install privoxy
cd /usr/local/etc/privoxy/
echo 'listen-address 0.0.0.0:8118\nforward-socks5 / localhost:8080 .' >> config

0.0.0.0 可以让别的设备用,如果不需要,可以用 127.0.0.18118 是默认端口;localhost:8080 是我的 SOCKS5 地址,根据需要自行修改。

需要注意的是,Privoxy 读取配置文件只会在当前目录读取,所以运行时建议用这个命令:privoxy /usr/local/etc/privoxy/config,没看到任何信息就代表成功了。

把 PAC 文件里的 SOCKS5 地址改成 HTTP 地址:

function FindProxyForURL(url, host) {
  proxy = 'PROXY 127.0.0.1:8118'
  if (shExpMatch(url, "*.twitter.com/*")) {
    return proxy;
  }
  return 'DIRECT'
}

好了,配合之前解决的沙盒问题,PAC 又可以正常工作了。

如果需要自启动,在命令行执行如下命令:

cd ~
touch org.privoxy.plist | echo '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>org.privoxy.launchd.privoxy</string><key>ProgramArguments</key><array><string>/usr/local/sbin/privoxy</string><string>/usr/local/etc/privoxy/config</string></array><key>RunAtLoad</key><true/></dict></plist>' >> org.privoxy.plist
sudo chown root:wheel org.privoxy.plist
sudo cp org.privoxy.plist /Library/LaunchDaemons/org.privoxy.plist
launchctl load /Library/LaunchDaemons/org.privoxy.plist
launchctl start org.privoxy.launchd.privoxy

Privoxy 的进阶内容

其实 Privoxy 并不只是把 SOCKS5 转换成 HTTP 代理,她本身还有很强大的功能,比如 actionfilter,在这仅仅简单介绍一下,具体用途看官方文档

Action 可以起到 PAC 文件的作用,也可以当成 AdBlock、user script 和 Stylebot 来使用。

默认的文件分别是 /usr/local/etc/privoxy/user.action/usr/local/etc/privoxy/user.filter

大概的语法如下:

direct      = +forward-override{forward .}
ssh         = +forward-override{forward-socks5 127.0.0.1:8080 .}
default     = direct
{default}
/
{direct} 
.youku.com
.twitter.com
{ssh}
.twitter.com
# 后面的规则优先级比前面的高
{+block}
.weibo.com # 屏蔽微博
{-block}
.weibo.com/chrisyipw # 但是不屏蔽自己
{+block-as-image}
.weibo.com # 屏蔽微博下所有合法图片,即使扩展名不是图片扩展名也会被屏蔽

可以通过不同的 alias 配置不同的代理程序,如果是用 SSH 而不是 shadowsocks,可以考虑链接多个服务器进行分流,毕竟 SSH 并发性能不高。

还有更高级的,比如结合 filter 修改页面内容,比如重定向 URL 什么的:

{+filter{filter_name}}
.weibo.com
{+fast-redirects{check-decoded-url}}
news.google.com/news/url.*&url=http.*&

具体看 user.action 里的注释吧,而 filter 是需要结合 user.filter 来用的,如果想要使用多个 action 文件,在 config 加入 actionsfile name.action 就行。