Anyconnect VPN使用PAC来智能分流

简述

这篇文章会讨论使用AnyConnect VPN的智能分流方案,包括广为人知的路由表和更加合理和科学的PAC代理方案。本文承接上文的使用场景借助openwrt路由器实现移动网络下的智能翻墙,即移动网络下的智能分流方案,OpenConnect Server(ocserv)可以部署在openwrt路由器或者像我这样部署在路由器后面的cubieboard上面,对于国外的ocserv是无法直接使用这里的PAC代理方案的。

本文涉及的场景和前提

还是有不少人有疑问啊,这里声明一下。

本文使用场景为上篇 借助openwrt路由器实现移动网络下的智能翻墙 的后续。讨论的是非越狱的iOS在移动网络下的翻墙方案,当然也排除使用surge的情况。

该场景假设你已经在国外部署好shadowsocks服务端或者各种VPN服务端,并且通过家里的路由器或者服务器作为国内节点部署http/socks5代理+翻墙客户端(shadowsocks client或者各种VPN client),该国内节点为移动网络下的移动设备提供翻墙方案,实现方案是通过VPN技术让iOS设备连接国内节点,并通过PAC代理来分流,实现的效果是: 需要翻墙的网站通过国内节点的shadowsocks tunnel或者VPN去访问,不需要翻墙的网站通过国内节点访问。

这样的实现方案主要是由于以下前提或者约束:

  • 未越狱iOS在移动网络下(非Wi-Fi环境)
    • 无法安装shadowsocks
    • surge 99$肉痛
    • 最简单易实施的方案是VPN
    • 如何在VPN下取得较好的分流体验
      • 这正是本文讨论的

具体请参见前文 借助openwrt路由器实现移动网络下的智能翻墙

为什么要使用Anyconnect VPN

Anyconnect VPN是cisco公司推出的企业级VPN解决方案,和我们熟知的众多VPN技术相比,特点在于其稳定,因为AnyConnect的VPN协议默认使用UDP DTLS作为数据传输,但如果有什么网络问题导致UDP传输出现问题,它会利用最初建立的TCP TLS通道作为备份通道,降低VPN断开的概率。之前用过pptp,l2tp,ikev2等VPN,现在则想折腾一下Anyconnect VPN。

本文不涉及具体的部署和配置,部署请参见折腾笔记:架设OpenConnect Server给iPhone提供更顺畅的网络生活

还在用路由表分流?来用PAC吧!

当我浏览了不少网上的Anyconnect VPN搭建方案时,发现所有的作者都提到了AnyConnect VPN支持向客户端推送路由表的特性,故所有的分流方案也都是采用了这样的方法,经常可以在配置文件中看到这样的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Facebook
route = 58.26.0.0/255.255.0.0
route = 210.149.0.0/255.255.0.0
route = 31.13.0.0/255.255.0.0
route = 66.220.0.0/255.255.0.0
# Google
route = 8.6.0.0/255.255.0.0
route = 8.8.0.0/255.255.0.0
route = 8.15.0.0/255.255.0.0
route = 8.34.0.0/255.255.0.0
route = 8.35.0.0/255.255.0.0
...

甚至还有这样的项目ocserv-cn-no-route

不说Anyconnect VPN客户端对路由表大小有限制,要改源码编译且最大也只有两百多条这个固有的缺点,但是路由表不精确、覆盖面太小这都是我所不能忍受的。难道cisco推出的Anyconnect都不能支持proxy吗?难道不能用PAC来分流吗?

答案无疑是否定的。在cisco的官网上我们可以看到:

Proxy Auto-Configuration File Generation for Clientless Support
Some versions of the ASA require AnyConnect configuration to support clientless portal access through a proxy server after establishing an AnyConnect session. AnyConnect uses a proxy auto-configuration (PAC) file to modify the client-side proxy settings to let this occur. AnyConnect generates this file only if the ASA does not specify private-side proxy settings.

所以Anyconnect不仅支持proxy,还直接支持proxy auto-configuration,也就是我们的PAC。既然Anyconnect VPN支持,那么接下来作为开源Anyconnect VPN的实现,就要看OpenConnect Server(ocserv)支不支持了。答案是,ocserv没有让我们失望。

配置

这个配置是如此简单。我们只需要打开ocserv的配置文件,添加一条:

1
proxy-url = http://tyr.gift/anyconnect.pac

上述配置的含义是:客户端默认还是会把所有的流量推给服务器,Anyconnect VPN 服务器使用pac文件中指定的规则进行代理。实现的场景是:iPhone将所有流量就近路由到家里的openwrt上,openwrt根据pac规则选择本地连接还是远程代理。所以PAC的规则是服务器端的行为。目前该方案已废弃,原因是大家在iOS上可以使用Shadowrocket获得更好的体验。

甚至,我们可以使用关键字%{U}%{G}来为不同的用户名和组名定义不同的PAC文件,只需要这样:

1
proxy-url = http://tyr.gift/%{U}/anyconnect.pac

或者

1
proxy-url = http://tyr.gift/%{G}/anyconnect.pac

只需要将链接中的pac换成你自己的pac文件一切就大功告成了,就是这么简单!关于如何制作PAC文件和搭建http/socks代理,请参考我之前的文章关于PAC自动代理和ios翻墙

其它一些注意事项

在cubieboard上编译ocserv

在cubieboard上面编译ocserv的时候要注意configure的时候需要configure --disable-seccomp,否则会出现

1
Error: worker-privs.c:41:46: error: ‘__NR_time’ undeclared (first use in this function)

同样,在ocserv的配置文件中,我们需要isolate-workers = false

iptables

我们可以通过修改ocserv.conf

1
2
ipv4-network = 192.168.10.0
ipv4-netmask = 255.255.255.0

来配置VPN所使用的网段。iptables 这样配置:

1
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE

使用可信的SSL服务器证书

一般我们都是通过自建的CA证书来签发自己的服务器端证书,这会导致该服务器会被客户端认为是不可信的,需要我们关闭阻止不信任的服务器这个选项,或者手动导入服务器证书。

但如果我们已经拥有了自己的可信的SSL证书,则可以直接在ocserv.conf中用我们的服务器证书和私钥,就可以让客户端信任Anyconnect VPN服务器。
这是因为,客户端通过系统自带的证书链去验证服务器,服务器通过CA证书去验证客户端。CA证书和客户端证书还是通过certool或者openssl工具去产生。

推荐Let’s Encrypt这个项目来签发SSL证书,通过命令行简单而且免费。本站SSL证书已经更换为Let’s Encrypt签发的证书。

按需连接

cisco的AnyConnect Secure Mobility Client支持按需连接

在客户端的VPN配置中,只要我们打开了按需连接这个功能,并且添加一部分域名,那么当客户端访问这部分域名时,iOS会自动打开Anyconnect VPN,而不需要手动去打开VPN,对于临时的网络访问比如去搜索Google的时候还是挺方便的。

不过由于这里底层实现需要等待系统dns解析这部分域名超时之后,iOS才会去开启Anyconnect VPN,所以使用下来存在3-5s的等待时间。

配置见下图。

Anyconnect Ondemand

如果您觉得这篇文章对您有帮助,不妨支持我一下!