[date: 2018-03-04 11:52] [visits: 9]

Mac科学上网

因工作需要长期使用Google,所以必须科学上网,恰好自己服务器在香港,作为程序猿要实现科学上网,It's so easy~

但本文的主旨不是教大家如何科学上网,而是怎么玩的更有程序猿范,下面我们开始吧~

科学上网方法

科学上网具体怎么实现,百度、Google有很多教程,所知道的有三种,简要描述下:

借助SSH端口转发功能,与墙外服务器建立连接,然后再配置应用程序使用相应的SOCKS代理即可

    ssh -N -D 2048 user@host
    netstat -anp tcp |grep LISTEN |grep 2048

上述第一条命令建立隧道,第二条命令检查通道是否建立成功,接着通过设置->网络->高级->代理->SOCKS代理设置好相应信息,然后就可以访问Google了,以上命令和设置都是在Mac环境下。

VPN全称“Virtual Private Network”,虚拟专用网络,其核心功能是在共公网络基础上构建私有网络,简单理解为在公网上搭建局域网,在中大规模企业内应用广泛。科学上网算是与大环境的一种特色结合,有点大材小用

核心在于搭建VPN服务器,通过“墙外路由器”实现科学上网,搭建VPN服务器主要涉及技术关键词:pptp、ppp、pptpd、xl2tpd、iptables

SS是ShadowSocks的简写,原理简单,就是提供配套的SOCKS代理Server与Client,此方式简单易学,稳定好用

自己目前使用的就是SS,接下来描述自己的使用经验。

普通玩法

CentOS下安装SS-Server主要命令如下:

    curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
    python get-pip.py
    python get-pip.py
    pip install --upgrade pip
    pip install shadowsocks
    cat > /etc/shadowsocks.json << EOF
    > {
    >     "server": "0.0.0.0",
    >     "server_port": 10024,
    >     "password": "your pass",
    >     "method": "aes-256-cfb"
    > }
    > EOF
    ssserver -c /etc/shadowsocks.json &

接着下载SS-Client,设置好相应信息,就可以科学上网了。

升一级

非程序猿到这一步就已经OK了,但自己不想安装一个图形化的客户端,所以下载的是命令行工具,简称升一级。

    brew install shadowsocks-libev
    cat > /usr/local/etc/ss-local.conf << EOF
    > {
    >     "server": "host",
    >     "server_port": 10024,
    >     "local_port": 1080,
    >     "password": "your pass",
    >     "method": "aes-256-cfb"
    >     "timeout": 600
    > }
    > EOF
    ss-local -c /usr/local/etc/ss-local.conf 1>>/dev/null 2>>/dev/null &

接着通过设置->网络->高级->代理->SOCKS代理设置好相应信息,就可以访问Google了。

再升一级

通过上述方式虽然了实现科学上网,但也有好几个缺点:

  1. 支持SOCKS代理的应用,流量貌似都会通过代理,不需要的应用、网站都会使用代理,带宽严重不够,使用体验差
  2. 部分只支持HTTP代理的应用(skicka),不能实现科学上网
  3. 开机后需要重新通过命令行启动ss-local、后期还包括polipo
  4. 因为第一个缺点以及代理与Charles抓包冲突,导致经常要通过手动设置->网络->高级->代理->SOCKS代理,来切换代理的开关状态(操作不能自动化是不选择GUI客户端的原因之一)

这一级,我们实现局部科学上网,只针对必要的应用、必要的网站。经过Google搜索,了解到PAC文件可以实现浏览器局部科学上网。

由于不清楚PAC具体规则,以及网上PAC调试方法不生效,所以只能一点一点摸,费了蛮久时间,最终PAC文件内容:

var list = [
    /.*google\.com/,
    /.*gstatic\.com/,
    /.*googlevideo\.com/,
    /.*googleusercontent.com/,
    /.*youtube\.com/,
    /.*googleapis.com/,
    /.*stackoverflow\.com/,
    /.*stackexchange.com/,
    /.*github\.com/,
    /.*wikipedia\.org/,
    /.*leetcode\.com/,
    /.*ytimg.com/,
    /.*bitbucket.org/
];

var socksProxy = 'SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080';
var direct = 'DIRECT';

function FindProxyForURL(url, host) {
    for (var i = 0; i < list.length; i++) {
        if (list[i].test(host)) {
            return socksProxy;
        }
    }    

    return direct;
}

接着通过设置->网络->高级->代理->自动代理配置,填写代理文件URL: file:///usr/local/etc/pac,然后就可以局部科学上网了。

这里还绕了一段弯路,由于不知道PAC可以直接使用SOCKS代理,所以一开始弄了个HTTP代理,代理到SS上,PAC中再代理到HTTP代理实现科学上网。由于这个弯路,解决了上文第二个缺点,支持配置HTTP代理科学上网。

HTTP代理选择的是polipo,安装与使用,简单贴一下命令:

    brew install polipo
    cat > /usr/local/etc/polipo.conf << EOF
    > # config file for polipo
    > proxyAddress = 127.0.0.1
    > proxyPort = 1024
    > allowedClients = 127.0.0.1
    > allowedPorts = 1-65535
    > tunnelAllowedPorts = 1-65535
    > proxyName = localhost
    > cacheIsShared = false
    > socksParentProxy = 127.0.0.1:1080
    > socksProxyType = socks5
    > disableLocalInterface = true
    > disableConfiguration = true
    > dnsUseGethostbyname = yes
    > disableVia = true
    > censoredHeaders = from,accept-language,x-pad,link
    > censorReferer = maybe
    > logFile=/usr/local/var/log/polipo.log
    > logLevel=0xFF
    > EOF
    polipo -c /usr/local/etc/polipo.conf 1>>/dev/null 2>>/dev/null &

最终状态

经过上一个阶段,已经解决了两个缺点,剩下两个缺点,跟自动化相关,在最终Part解决。

开机需要手动启动服务,这个根据Linux经验,觉得通过开机自启动服务比较好解决,但在Mac下实施的时候还是遇到了一个问题,稍后简单描述下。

通过launchd,在Mac下实现开机服务自启动,命令操作流程如下:

    cd ~/Library/LaunchAgents/
    cat > com.amsimple.ss.plist << EOF
    > <?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>KeepAlive</key>
    >   <true/>
    >   <key>Label</key>
    >   <string>com.amsimple.ss</string>
    >   <key>ProgramArguments</key>
    >   <array>
    >     <string>/usr/local/bin/ss-local</string>
    >     <string>-c</string>
    >     <string>/usr/local/etc/ss-local.conf</string>
    >     <string>1>>/dev/null</string>
    >     <string>2>>/dev/null</string>
    >   </array>
    >   <key>RunAtLoad</key>
    >   <true/>
    > </dict>
    > </plist>
    > EOF
    launchctl load com.amsimple.ss.plist

polipo的plist文件基本一样,就不贴相关命令和配置了。但问题就出在polipo上,同样的配置,polipo就是无法启动,状态如下:

    launchctl list |grep com.amsimple
    1024    0   com.amsimple.ss
    1025    1   com.amsimple.polipo

百思不得及其解,而且有没有相关日志查看,哪怕最后得到了错误日志,也没有丝毫头绪,最终经过排除法慢慢试,找到了问题的表层原因:

    <string>1>>/dev/null</string>
    <string>2>>/dev/null</string>

polipo的plist文件中由于这两行,导致服务不能启动,干脆把ss和polipo中的这两行删除掉。实际原因由于没有精力和知识储备去折腾,也就不了了之了,欢迎知道原因的朋友邮件我。

开机自启动搞定后,还剩下最后一个缺点,就是使用代理的开关还是很麻烦,需要好几步操作,而且每次开关还需要重新输入PAC文件路径。

经过一番搜索,找到了解决办法:

sudo networksetup -setautoproxystate 'Wi-Fi' on
sudo networksetup -setautoproxystate 'Wi-Fi' off

上述两条命令可以实现设置->网络->高级->代理->自动代理的命令式操作,命令太长,在~/.bash_profile文件中配置两个alias就OK啦~

alias pon="sudo networksetup -setautoproxystate 'Wi-Fi' on"
alias poff="sudo networksetup -setautoproxystate 'Wi-Fi' off"

至此,科学上网之程序猿折腾告一段落,最终使用方式总结:

// 设置全局SOCKS代理应该也有命令行方式,留给大家探索