还是老方法,依旧使用 chnroutes 生成路由表。并且非常不优雅,但是在找不到解决方案的时候可以暂时解决问题。
在使用 PPTP 方式连接 VPN 的时代,只要将生成的 ip-up
和 ip-down
拷贝到 /etc/ppp
目录下并且 sudo chmod +x ip-up ip-down
赋予执行权限,在连接 VPN 时会自动调用 ip-up
添加静态路由,在断开 VPN 时会自动调用 ip-down
删除静态路由。
现在 macOS 取消了 PPTP 方式的 VPN,那要怎么样来做分流呢,根据 PPTP 时代的经验,原理无非就是写静态路由,所以还是使用 chnroutes 生成 ip-up
和 ip-down
放在你喜欢的目录下,现在就到了最脏的时候,没有找到合适的自动运行的方式,所以我们手动运行。在每次进入到一个新的网络环境时 sudo ./ip-up
添加静态路由,在使用过后 sudo ./ip-down
删除静态路由。
那么问题来了,既然是静态路由,可不可以添加一次就好了?如果你这辈子都不会变更网络环境,理论上是的。为什么这么说,我们来看代码。
# ip-up 文件
#!/bin/sh
export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
OLDGW=`netstat -nr | grep '^default' | grep -v 'ppp' | sed 's/default *\([0-9\.]*\) .*/\1/' | awk '{if($1){print $1}}'`
if [ ! -e /tmp/pptp_oldgw ]; then
echo "${OLDGW}" > /tmp/pptp_oldgw
fi
dscacheutil -flushcache
route add 10.0.0.0/8 "${OLDGW}"
route add 172.16.0.0/12 "${OLDGW}"
route add 192.168.0.0/16 "${OLDGW}"
ip-up
的工作是获取当前网络的网关,添加静态路由,在静态路由里面将白名单 IP 转发到当前网络的网关上,这样流量就不会通过 VPN 了。所以说如果你确定这辈子都不会变更网络环境可以只执行一次 ip-up
就可以愉快的上网了。如果不是,老老实实在每次使用前执行 ip-up
添加静态路由,使用后执行 ip-down
删除静态路由,否则上不了网可别怨天尤人。
知道了原理后,我们还可以定制静态路由,将 chnroutes 生成的静态路由里缺少的部分自己手动添加进去。
# ip-up 文件
#!/bin/sh
export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
OLDGW=`netstat -nr | grep '^default' | grep -v 'ppp' | sed 's/default *\([0-9\.]*\) .*/\1/' | awk '{if($1){print $1}}'`
if [ ! -e /tmp/pptp_oldgw ]; then
echo "${OLDGW}" > /tmp/pptp_oldgw
fi
dscacheutil -flushcache
route add 10.0.0.0/8 "${OLDGW}"
route add 172.16.0.0/12 "${OLDGW}"
route add 192.168.0.0/16 "${OLDGW}"
# 自定义
route add 103.235.46.0/22 "${OLDGW}" # 百度
# ip-down 文件
#!/bin/sh
export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
if [ ! -e /tmp/pptp_oldgw ]; then
exit 0
fi
ODLGW=`cat /tmp/pptp_oldgw`
route delete 10.0.0.0/8 "${OLDGW}"
route delete 172.16.0.0/12 "${OLDGW}"
route delete 192.168.0.0/16 "${OLDGW}"
# 自定义
route delete 103.235.46.0/22 "${OLDGW}" # 百度
注意:一定要在 ip-up
和 ip-down
中成对添加自定义 IP。
以上就是以非常脏的方式实现手动分流的全过程,下一步就是要像 PPTP 时代一样在使用 VPN 能自动执行上述过程。由于我对 macOS 仅限于使用,也不是 *nix 大神,暂时没有想到什么特别好的解决方案,准备试试使用 AppleScript 能不能监听到 VPN 连接与断开事件来实现自动化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。