服务器
Arch
Linux可以安装aur/strongswan
,Debian可以安装unstable仓库的strongswan
和libcharon-extra-plugins
。Ubuntu等发行版,软件仓库中strongswan较旧,建议编译安装最新版本。
在服务器上执行:
1 | # CA key & certificate |
编辑/etc/ipsec.conf
:
1 | config setup |
注意修改your.ip
和your.domain
。
iOS 9内置的IKEv2
VPN客户端会验证服务端证书是否为本地某信任CA签署的,且“远程ID”匹配证书的CN(生成serverCert.der
时的--dn
选项中)或subject
alternative name
(生成serverCert.der
时的--san
选项)。CN、subject
alternative
name可以填域名或IP地址,域名可以乱写,不会检查域名是否和服务器IP对应。填写服务器的域名或IP地址可行,其他可能项如邮箱地址等不知是否可行。
编辑/etc/ipsec.secrets
:
1 | : RSA serverKey.pem |
注意修改用于EAP-MSCHAPv2的密码your.password
。
服务器需要允许外界访问500/udp和4500/udp。客户端连接后,可以把服务端作为路由的下一跳,服务端需要配置转发:
1 | sysctl -w net.ipv4.ip_forward=1 |
某些使用环境可能会设定默认DROP、禁止FORWARD等,需要更复杂的配置,此处不赘述。
若要推送nameserver给客户端,可以编辑/etc/strongswan.conf
:
1 | charon { |
ipsec start
启动服务端守护进程,如果使用systemd的话,可能是systecmtl start strongswan
之类。
Linux strongSwan客户端
把caCert.pem
复制到本地,cp caCert.pem /etc/ipsec.d/cacerts/
。
编辑/etc/ipsec.conf
,设定名为myikev2
的连接:
1 | config setup |
注意修改your.domain
。
编辑/etc/ipsec.secrets
,需要服务端中指定的EAP密码:
1 | client : EAP "your.password" |
rightsubnet
会影响到myikev2
连接建立后的新建的路由。ip ru
可以看到多了一个ID为220的路由表,若把rightsubnet
改为8.0.0.0/8
,会看到ip r s t 220
输出:
1
2# 我本地无线网接口wlp3s0 IP 192.168.0.3,网关为192.168.0.1。wlp3s0上多出了一个10.99.1.1/32的由服务端推送的[virtual IP
8.0.0.0/8 via 192.168.0.1 dev wlp3s0 table 220 proto static src 10.99.1.1
若要测试是否可以把服务端作为网关,可以用如下命令: 1
2
3
4
5# 添加
ip r a 180.149.132.47 dev enp4s0f2 src 10.99.1.1
ping 180.149.132.47
# 删除
ip r d 180.149.132.47 dev enp4s0f2 src 10.99.1.1
Virtual IP。待补充。
iOS 9内置IKEv2客户端
在iOS
9中打开caCert.pem
,会提示导入“描述文件”,之后可以在“设置->通用->描述文件”看到该证书。
iOS
9中亦可导入用于客户端认证的私钥及证书,但必须是PKCS12格式,且有四位passphrase,可以用如下命令创建:
1
openssl pkcs12 -export -inkey clientKey.pem -in clientCert.pem -name 'client' -certfile caCert.pem -caname 'CA' -passout 'pass:1234' -out client.p12
尚未弄明如何使用iOS 9内置客户端的公钥认证,但可以使用EAP-MSCHAPv2方式认证。“设置->通用->VPN->添加VPN配置”,填写如下字段:
- 类型:
IKEv2
- 服务器:
your.ip
- 远程ID:服务端
/etc/ipsec.conf
中指定的leftid
- 用户鉴定:
用户名
- 用户名:
client
(服务端/etc/ipsec.secrets
中配置了名为client
的EAP identity) - 密码:
your.password
iOS调试还是挺麻烦的,VPN连接失败什么错误消息都没有,只能看服务端的日志……对iOS认识太少。
Android
- 类型:IPSec Hybrid RSA
- 服务器地址:
your.ip
- IPSec CA证书:
caCert.pem
- IPSec服务器证书:
serverCert.pem
。“设置->安全->从存储设备安装”中可以安装。
测试时,“IPSec CA证书”、“IPSec服务器证书”可留空。长按新建的VPN条目可以修改配置。
较新的strongSwan似乎关闭Aggressive Mode PSK,默认无法使用IPSec Xauth
PSK: 1
Aggressive Mode PSK disabled for security reasons.
调试
journal -fb _SYSTEM_UNIT=strongswan.service
看服务端日志,或者用ipsec start --nofork
在前台开启。客户端修改后ipsec restart
看日志,某些改动可以使用ipsec reload
、ipsec rereadsecrets
等。
常见错误
服务端找不到匹配的conn
配置:
1 | looking for peer configs matching 10.0.0.4[server]...1.2.3.4[client] # 未仔细研究,似乎对应配置文件中的:left[leftid]...right[rightid] |
服务端strongswan不支持特定认证方式
journalctl -fb
后重启ipsec服务,看到如下字样:
1
214[IKE] EAP-Identity request configured, but not supported
14[IKE] loading EAP_MSCHAPV2 method failed
服务端未推送nameserver给客户端
Android、iOS难以看到IPSec客户端错误信息,可以尝试用IP访问网页。
Path MTU discovery
假设服务器上外网接口为eth0
,根据该接口的MTU与网站协商了一个MSS,但该MSS加上IP
header很可能会大于IPSec客户端到服务器的MTU。服务器向网站发送ICMP
Unreachable,但网站很可能屏蔽了该消息。
在服务器上使用命令tcpdump -ni eth0 'port 80 and tcp[13] & 2 == 2'
观察80/tcp带有SYN的TCP
packets发现协商的MSS。tcpdump -ni eth0 'net 180.97.33.0/24'
发现网站发送的TCP
packet与服务器发送的不被理会的ICMP Unreachable。 1
2
3
4
5
6
7
8
9
10
11
1212:31:51.778576 IP (tos 0x0, ttl 44, id 42813, offset 0, flags [DF], proto TCP (6), length 1480)
180.97.33.107.80 > 10.0.0.4.49016: Flags [.], cksum 0xba48 (correct), seq 1026:2466, ack 78, win 193, length 1440
12:31:51.778633 IP (tos 0xc0, ttl 64, id 59986, offset 0, flags [none], proto ICMP (1), length 576)
10.0.0.4 > 180.97.33.107: ICMP 10.0.0.4 unreachable - need to frag (mtu 1438), length 556
IP (tos 0x0, ttl 43, id 42813, offset 0, flags [DF], proto TCP (6), length 1480)
180.97.33.107.80 > 10.0.0.4.49016: Flags [.], seq 1026:2466, ack 78, win 193, length 1440
12:31:52.194666 IP (tos 0x0, ttl 44, id 42814, offset 0, flags [DF], proto TCP (6), length 1480)
180.97.33.107.80 > 10.0.0.4.49016: Flags [.], cksum 0xba48 (correct), seq 1026:2466, ack 78, win 193, length 1440
12:31:52.194740 IP (tos 0xc0, ttl 64, id 59995, offset 0, flags [none], proto ICMP (1), length 576)
10.0.0.4 > 180.97.33.107: ICMP 10.0.0.4 unreachable - need to frag (mtu 1438), length 556
IP (tos 0x0, ttl 43, id 42814, offset 0, flags [DF], proto TCP (6), length 1480)
180.97.33.107.80 > 10.0.0.4.49016: Flags [.], seq 1026:2466, ack 78, win 193, length 1440
iOS客户端初始协商的MSS为1360,一般不会出问题。Linux
strongswan客户端/Android客户端初始协商的MSS可能和MTU有关,对于MTU
1500,协商了MSS
1460,无法访问网页。解决办法是调低服务器向IPSec客户端通报的MSS:
1
iptables -t mangle -A FORWARD -s 10.99.1.0/24 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360