使用Alfred切换网络代理

目前网络状态

公司连WiFi,需要设置一个pac代理,不需要额外的代理,公司的代理能访问Google。回到家需要连上家里的WiFi,需要用SS做代理翻墙。

痛点

SS的代理和公司的代理互相冲突。从家的网络环境切到公司的网络环境中需要做:切换WiFi,关闭SS,记下来公司的pac地址,然后打开网络设置来手动设置代理;从公司的网络环境切到家中的网络环境需要:切换WiFi,打开SS。
公司网络配置:


家中网络配置:

主要就是这个自动代理配置的URL冲突了。

需求

每次切换网络环境,Alfred执行一个命令即可完成自动切换,SS可以一直在后台运行无需关闭。

解决方案

  • bash中切换网络环境的命令是networksetup,可以完成命令行更换网络设置,具体使用方法可以查询man networksetup。我们这次主要用到的几条:
networksetup -setautoproxystate Wi-Fi off
networksetup -setautoproxyurl Wi-Fi http://txp-01.tencent.com/proxy.pac
  • 我们的主要思路就是根据WiFi的ssid来区分目前是处于哪个网络环境中,比如只要WiFi名称是Tencent-OfficeWiFi就认为我是处于公司网络环境中,其他的都是认为是在家的网络环境中。这个是使用networksetup -getairportnetwork en0来实现的;


然后使用awk将WiFi名称输出出来判断:

if [ "$(networksetup -getairportnetwork en0 | awk -F ": " '{print $2}')" = "Tencent-OfficeWiFi" ]; then # at Company
networksetup -setwebproxystate Wi-Fi off 
networksetup -setsocksfirewallproxystate Wi-Fi off 
networksetup -setautoproxystate Wi-Fi off

networksetup -setautoproxystate Wi-Fi on 
networksetup -setautoproxyurl Wi-Fi http://txp-01.tencent.com/proxy.pac
else # at home
networksetup -setwebproxystate Wi-Fi off 
networksetup -setsocksfirewallproxystate Wi-Fi off 
networksetup -setautoproxystate Wi-Fi off 

networksetup -setautoproxystate Wi-Fi on 
networksetup -setautoproxyurl Wi-Fi http://127.0.0.1:8090/proxy.pac
fi
  • 把代码做成Alfred的Workflow,这个很容易就知道大致的流程是什么样的,我简单做了一个,流程就是keyword -> bash -> notification,非常简单。中间的bash脚本就是上面贴出来的。

  • 但是诸位以为这样就结束了么,前三步都是网络上面有的,一搜就能够搜到解决方案,那我写这个有什么用。最重要的是第四步,networksetup更改设置是需要root权限的,如果仅仅是这样的代码,放在命令行中去跑,需要sudo pathname,这样还好。但是我们的目的是放在Alfred上面跑。这样的后果是什么呢,会弹出无数次

简直令人崩溃。
这样怎么办呢,有人说用sudo -A,但是这个命令需要调用另外一个bash脚本,在Alfred里面搞不了,卒。还有人说使用sudo -S,利用管道把密码传进去,把其中执行networksetup的都写成这样$password | networksetup -xxx,这样可以么,是可以的。但是你把密码这么明文放着,不知道你怎么想的,我反正是一百个不放心。
好了,左不行右不行,那能不能搞呢。答案当然是能搞的。可以使用钥匙串(Keychain Access)。做法如下:
1 打开Keychain Access,左下角有个小加号,点击可以手动添加钥匙串。

添加完之后可以找到:


2 然后可以利用security来读取这个钥匙串。

security find-generic-password -l alfred_sudo_plugin -w

其中-l参数就是名字,-w是获取明文密码。这个时候会提示是否允许security应用程序获取钥匙串中test的明文密码,可以点击Always Allow,你就会发现以后再用security读取密码的时候不会弹出确认框了。


此时,在Keychain Access就会看到的Access Control这里增加了一个security

上面这个就能够读取到你设置的明文密码。

  • 拿到这个明文密码了之后,大家都知道怎么做了吧,用sudo -S这个就可以了。最后代码是这样的:
password="$(security find-generic-password -l alfred_sudo_plugin -w)"

if [ "$(networksetup -getairportnetwork en0 | awk -F ": " '{print $2}')" = "Tencent-OfficeWiFi" ]; then # at Company

echo $password | sudo -S networksetup -setwebproxystate Wi-Fi off 
echo $password | sudo -S networksetup -setsocksfirewallproxystate Wi-Fi off 
echo $password | sudo -S networksetup -setautoproxystate Wi-Fi off

echo $password | sudo -S networksetup -setautoproxystate Wi-Fi on 
echo $password | sudo -S networksetup -setautoproxyurl Wi-Fi http://txp-01.tencent.com/proxy.pac

else # at home
echo $password | sudo -S networksetup -setwebproxystate Wi-Fi off 
echo $password | sudo -S networksetup -setsocksfirewallproxystate Wi-Fi off 
echo $password | sudo -S networksetup -setautoproxystate Wi-Fi off 

echo $password | sudo -S networksetup -setautoproxystate Wi-Fi on 
echo $password | sudo -S networksetup -setautoproxyurl Wi-Fi http://127.0.0.1:8090/proxy.pac

fi 

Done!祝大家折腾愉快。