因为最近的干扰力度变大,考虑到 AnyConnect 是思科的安全远程接入解决方案,隐蔽性要好一些,所以决定在服务器上搭建 AnyConnect 以提供给 iOS 设备使用,原来的 Cisco IPSec VPN 废弃,Shadowsocks 保留用于安卓和PC的连接。

AnyConnect 有以下优势:

  1. 待机不会断开
  2. 能够下发路由表给客户端(未测试)
  3. 稳定
  4. 耗电量较低

2015-11-26 更新:添加证书登录方式

2015-12-02 更新:更新转发规则

1. 安装 ocserv (OpenConnect server)

ocserv 是一个 OpenConnect SSL VPN 协议服务端,0.3.0 版后兼容使用 AnyConnect SSL VPN 协议的终端。
官方主页:http://www.infradead.org/ocserv/

ocserv 已经在 epel 仓库中提供了,所以可以直接通过 yum 安装

1
2
$ yum install epel-release
$ yum install ocserv

2. 生成证书

这里你需要先仔细阅读官方文档,简单的来说,如下几步

1. 创建工作文件夹
1
2
$ mkdir anyconnect
$ cd anyconnect
2. 生成 CA 证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ certtool --generate-privkey --outfile ca-key.pem
$ cat >ca.tmpl <<EOF
cn = "VPN CA"
organization = "Big Corp"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
EOF
$ certtool --generate-self-signed --load-privkey ca-key.pem \
--template ca.tmpl --outfile ca-cert.pem

把生成的 ca-cert.pem 放到 /etc/ocserv/

3. 生成本地服务器证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ certtool --generate-privkey --outfile server-key.pem
$ cat >server.tmpl <<EOF
cn = "www.example.com"
organization = "MyCompany"
serial = 2
expiration_days = 3650
encryption_key
signing_key
tls_www_server
EOF
$ certtool --generate-certificate --load-privkey server-key.pem \
--load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem \
--template server.tmpl --outfile server-cert.pem

把生成的 server-cert.pemserver-key.pem 放到 /etc/ocserv/

4. 生成客户端证书

创建 gen-client-cert.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cat >gen-client-cert.sh <<EOF
#!/bin/bash
USER=$1
CA_DIR=$2
SERIAL=`date +%s`
certtool --generate-privkey --outfile $USER-key.pem
cat << _EOF_ >user.tmpl
cn = "$USER"
unit = "users"
serial = "$SERIAL"
expiration_days = 9999
signing_key
tls_www_client
_EOF_
certtool --generate-certificate --load-privkey $USER-key.pem --load-ca-certificate $CA_DIR/ca-cert.pem --load-ca-privkey $CA_DIR/ca-key.pem --template user.tmpl --outfile $USER-cert.pem
openssl pkcs12 -export -inkey $USER-key.pem -in $USER-cert.pem -name "$USER VPN Client Cert" -certfile $CA_DIR/ca-cert.pem -out $USER.p12
EOF

创建用户文件夹并调用 gen-client-cert.sh 生成证书

1
2
3
4
5
$ mkdir user
$ cd user
# user 指的是用户名,.. 指的是 ca 证书所在的目录
$ ../gen-client-cert.sh user ..
# 按提示设置证书使用密码,或直接回车不设密码

最后,通过 http 服务器或其他方式将 user.p12 传输给客户端导入即可

3. 配置 ocserv

1
$ sudo vim /etc/ocserv/ocserv.conf

主要修改以下部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#ocserv支持多种认证方式,这是自带的密码认证,使用ocpasswd创建密码文件
#ocserv还支持证书认证,可以通过Pluggable Authentication Modules (PAM)使用radius等认证方式
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
#指定替代的登录方式,这里使用证书登录作为第二种登录方式
enable-auth = "certificate"
#证书路径
server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem
#ca路径
ca-cert = /etc/ocserv/ca-cert.pem
#从证书中提取用户名的方式,这里提取的是证书中的 CN 字段作为用户名
cert-user-oid = 2.5.4.3
#最大用户数量
max-clients = 16
#同一个用户最多同时登陆数
max-same-clients = 10
#tcp和udp端口
tcp-port = 4433
udp-port = 4433
#运行用户和组
run-as-user = ocserv
run-as-group = ocserv
#虚拟设备名称
device = vpns
#分配给VPN客户端的IP段
ipv4-network = 10.12.0.0
ipv4-netmask = 255.255.255.0
#DNS
dns = 8.8.8.8
dns = 8.8.4.4
#注释掉route的字段,这样表示所有流量都通过 VPN 发送
#route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0

4. 创建用户

1
2
#username为你要添加的用户名
$ sudo ocpasswd -c /etc/ocserv/ocpasswd username

5. 配置系统设置

  1. 开启内核转发
1
2
$ sudo sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' /etc/sysctl.conf
$ sudo sysctl -p
  1. 配置 iptables 规则

你可以参考Linode 的文章来配置 iptables

1
2
3
4
5
#IP段和eth0接口和vpns类接口要根据自己的情况修改
$ sudo iptables -t nat -A POSTROUTING -s 10.12.0.0/24 -o eth0 -j MASQUERADE
$ sudo iptables -A FORWARD -i vpns+ -j ACCEPT
$ sudo iptables -A FORWARD -o vpns+ -j ACCEPT
$ sudo iptables-save > /etc/sysconfig/iptables

6. 测试

现在我们可以开启服务器试试了

1
$ sudo ocserv -c /etc/ocserv/ocserv.conf -f -d 1

拿起你的 iOS 设备,下载思科的 AnyConnect 客户端,连接你的服务器。

出现问题可以看debug的返回信息,如果信息不详细,可以把 1 改成 10。

如果没有问题,那么就可以配置成开机运行了。

1
2
$ sudo systemctl enable ocserv
$ sudo systemctl start ocserv

a. 下发路由

我想这个功能是最激动人心的,因为我们手机如果长期连接,那么肯定是某些服务走 VPN,而国内的网站可以走手机自己的网络体验最好。

但是这里的一个问题是,AnyConnect 有下发路由表的 64 条数限制。

所以我们只能保证下某几个常用的服务是可用的,比如 Google Facebook 以及 Twitter

编辑配置文件

1
$ sudo vim /etc/ocserv/ocserv.conf

添加 route = 的字段即可

#. 参考

AnyConnect 带来 iPhone 上的新生活
在CentOS 6.5上配置Cisco AnyConnect VPN

2015-12-02 更新

不知道为什么,原有的转发规则在启用防火墙后有问题,配置 iptables 后查询 dmesg 输出发现从设备发来的包正常,但是发回设备的包全部被 reject 了,最后干脆放过了所有 ocserv 创建的虚拟网络设备的浏览。