6

支持Android、iOS 9内置IPSec客户端的strongSwan 5.3.5配置

 3 years ago
source link: http://maskray.me/blog/2015-12-31-strongswan
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

支持Android、iOS 9内置IPSec客户端的strongSwan 5.3.5配置

Arch Linux可以安装aur/strongswan,Debian可以安装unstable仓库的strongswanlibcharon-extra-plugins。Ubuntu等发行版,软件仓库中strongswan较旧,建议编译安装最新版本。

在服务器上执行:

# CA key & certificate
ipsec pki --gen > caKey.der
ipsec pki --self --in caKey.der --dn 'C=JP, O=mynet, CN=CA' --ca > caCert.der
openssl x509 -inform der -in caCert.der -out caCert.pem
# server key & certificate
ipsec pki --gen > serverKey.der
ipsec pki --pub --in serverKey.der | ipsec pki --issue --cacert caCert.der --cakey caKey.der --dn 'C=JP, O=mynet, CN=your.ip' --san 'your.domain' > serverCert.der
openssl x509 -inform der -in serverCert.der -out serverCert.pem
openssl rsa -inform der -in serverKey.der -out serverKey.pem
# 本文未用到(iOS 9公钥认证未试验成功,Linux strongSwan客户端公钥认证产生1580字节packet超过MTU,分片未试验成功)。若需生成client key & certificate
#ipsec pki --gen > clientKey.der
#ipsec pki --pub --in clientKey.der | ipsec pki --issue --cacert caCert.der --cakey caKey.der --dn "C=JP, O=azurejp, CN=client" --san '[email protected]' > clientCert.der
#openssl x509 -inform der -in clientCert.der -out clientCert.pem
#openssl rsa -inform der -in clientKey.der -out clientKey.pem
mkdir -p /etc/ipsec.d/{certs,cacerts,private}
cp caCert.pem /etc/ipsec.d/cacerts/
cp serverCert.pem /etc/ipsec.d/certs/
cp serverKey.pem /etc/ipsec.d/private/

编辑/etc/ipsec.conf

config setup
uniqueids = never
conn ikev2ios
keyexchange = ikev2
ike = aes256-sha256-modp1024,3des-sha1-modp1024,aes256-sha1-modp1024! # for iOS 9
esp = aes256-sha256,3des-sha1,aes256-sha1! # for iOS 9
left = %any
leftid = your.domain # iOS 9似乎要求此处为域名或IP
leftsendcert = always # iOS 9会验证证书
leftcert = serverCert.pem
leftsubnet = 0.0.0.0/0 # 给iOS 9推送的路由
right = %any
rightauth = eap-mschapv2
rightsourceip = 10.99.1.0/24
eap_identity = %any
auto = add
fragmentation = yes
conn ikev1android
keyexchange = ikev1
left = %any
leftid = your.ip
leftsendcert = always
leftcert = serverCert.pem
leftsubnet = 0.0.0.0/0
right = %any
rightauth = xauth
rightsourceip = 10.99.1.0/24
auto = add

注意修改your.ipyour.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

: RSA serverKey.pem
client : EAP "your.password" # iOS及Linux的EAP-MSCHAPv2
client : XAUTH "your.password" # Android IPSec hybrid RSA

注意修改用于EAP-MSCHAPv2的密码your.password

服务器需要允许外界访问500/udp和4500/udp。客户端连接后,可以把服务端作为路由的下一跳,服务端需要配置转发:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 10.99.1.0/24 -j MASQUERADE

某些使用环境可能会设定默认DROP、禁止FORWARD等,需要更复杂的配置,此处不赘述。

若要推送nameserver给客户端,可以编辑/etc/strongswan.conf

charon {
load_modular = yes
duplicheck.enable = no
compress = yes
dns1 = your.dns1
dns2 = your.dns2
plugins {
include strongswan.d/charon/*.conf

ipsec start启动服务端守护进程,如果使用systemd的话,可能是systecmtl start strongswan之类。

Linux strongSwan客户端

caCert.pem复制到本地,cp caCert.pem /etc/ipsec.d/cacerts/

编辑/etc/ipsec.conf,设定名为myikev2的连接:

config setup
niqueids = never
conn myikev2
keyexchange = ikev2
right = your.ip
rightca = caCert.pem
rightid = your.domain
rightsubnet = 0.0.0.0/0
left = %any
leftsourceip = %config
leftauth = eap-mschapv2
eap_identity = client
auto = start

注意修改your.domain

编辑/etc/ipsec.secrets,需要服务端中指定的EAP密码:

client : EAP "your.password"

rightsubnet会影响到myikev2连接建立后的新建的路由。ip ru可以看到多了一个ID为220的路由表,若把rightsubnet改为8.0.0.0/8,会看到ip r s t 220输出:

# 我本地无线网接口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

若要测试是否可以把服务端作为网关,可以用如下命令:

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,可以用如下命令创建:

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:

Aggressive Mode PSK disabled for security reasons.

journal -fb _SYSTEM_UNIT=strongswan.service看服务端日志,或者用ipsec start --nofork在前台开启。客户端修改后ipsec restart看日志,某些改动可以使用ipsec reloadipsec rereadsecrets等。

服务端找不到匹配的conn配置:

looking for peer configs matching 10.0.0.4[server]...1.2.3.4[client] # 未仔细研究,似乎对应配置文件中的:left[leftid]...right[rightid]
no matching peer config found

服务端strongswan不支持特定认证方式

journalctl -fb后重启ipsec服务,看到如下字样:

14[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。

12: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:

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

Share Comments


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK