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

Mac科学上网

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

但本文的主旨不是教大家如何科学上网,而是怎么玩的更有程序猿范。

科学上网方法

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

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

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

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

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

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

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

自己目前使用的就是SS,接下来讲讲自己的玩法。

LEVLE-1

LEVLE-1主要是安装SS-Server配合一个客户端使用,CentOS下安装SS-Server主要命令如下:

    curl https://bootstrap.pypa.io/get-pip.py -o 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,设置好相应信息,就可以科学上网了。

LEVLE-2

正常来说是下载GUI的client,但自己不想安装一个图形化的客户端,所以下载的是命令行工具,称为LEVEL-2。

    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了。

LEVLE-3

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

  1. 在网络设置中设置的SOCKS代理是全局生效,导致支持SOCKS代理的应用流量都会通过代理,这其中大部分应用与站点我们不希望走代理,且代理带宽严重不足,使用体验差
  2. 部分只支持HTTP代理的应用(skicka),不能实现科学上网
  3. 开机后需要重新通过命令行启动ss-local
  4. 因为代理与Charles抓包冲突,导致经常要通过手动设置->网络->高级->代理->SOCKS代理,来切换代理的开关状态

在LEVEL-3中,我们实现局部科学上网,只针对必要的应用与站点。经过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;
}

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

自己在写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 &

LEVEL-4

在LEVEL-2中选择命令行客户端的重要原因是因为GUI客户端操作难做自动化,这个选择恰好可以帮助我们在LEVEL-4中使用自动化方式解决前文的第3、4条缺点。

开机需要手动启动服务,这个根据Linux经验,觉得在Mac下应该有开机自启动服务可以解决,但实施的时候还是遇到了一个问题,在后面简单描述。

Mac下开机服务自启动是通过launchd这个系统程序实现,在LaunchAgents目录下新建plist文件,命令操作流程如下:

    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文件与ss的基本一样,就不贴相关命令和配置了。但前文提到的问题就出在polipo上,同样的配置,polipo就是无法启动,开机后使用launchctl命令查看状态,如下:

    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的plist中这两行内容删除掉。但问题的根本原因由于没有精力和知识储备去折腾,也就不了了之了,这里欢迎知道原因的朋友邮件告诉我。

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

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

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

上述两条命令可以替代设置->网络->高级->代理->自动代理的GUI操作,嫌弃命令长,可以在~/.bash_profile文件中配置两个alias:

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

至此,我的科学上网之旅告一段落,最终使用方式总结:

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