上次更新:2019-12-27

项目地址:https://strongswan.org/

写这篇文章的时候,strongswan的最新版为strongswan 5.3.5,epel库中为strongswan 5.3.2

刚剁了太小内存vps,只是跑跑ss还是有点浪费,而且ios9.2(据我所知)不越狱连内建ss都用不了了,本想装个l2tp,但是发现ios9.2开始支持ikev2了,那就正好装个strongswan试试。

安装strongswan

安装环境:CentOS 6.x 32位

惯例,更新系统

yum -y update

先安装epel库

yum -y install epel-release

安装strongswan

yum -y install strongswan

OpenVZ必须再安装libipsec插件(注①)

yum -y install strongswan-plugin-libipsec

新建个密钥文件夹

mkdir cert && cd cert

生成CA证书的私钥(注②)

strongswan pki --gen --outform pem > ca.pem

使用私钥,签名CA证书

strongswan pki --self --in ca.pem --dn "C=CN, O=VPN, CN=VPN CA" --ca --lifetime 3650 --outform pem >ca.cert.pem

生成服务器证书的私钥

strongswan pki --gen --outform pem > server.pem  

用CA证书签发服务器证书

strongswan pki --pub --in server.pem | strongswan pki --issue --lifetime 1200 \
    --cacert ca.cert.pem --cakey ca.pem --dn "C=CN, O=VPN, CN=127.0.0.1" \
    --san="127.0.0.1" --flag serverAuth --flag ikeIntermediate --outform pem > server.cert.pem
    

生成客户端证书的私钥

strongswan pki --gen --outform pem > client.pem

用CA证书签发客户端证书

strongswan pki --pub --in client.pem | strongswan pki --issue \
   --cacert ca.cert.pem --cakey ca.pem --dn "C=CN, O=VPN, CN=VPN Client" \
   --outform pem > client.cert.pem

生成 pkcs12 证书

openssl pkcs12 -export -inkey client.pem -in client.cert.pem -name "VPN Client"\
         -certfile ca.cert.pem -caname "127.0.0.1"  -out client.cert.p12

把证书复制到strongswan目录下

\cp -r ca.cert.pem /etc/strongswan/ipsec.d/cacerts/
\cp -r server.cert.pem /etc/strongswan/ipsec.d/certs/
\cp -r server.pem /etc/strongswan/ipsec.d/private/
\cp -r client.cert.pem /etc/strongswan/ipsec.d/certs/
\cp -r client.pem  /etc/strongswan/ipsec.d/private/

编辑/etc/strongswan/ipsec.conf文件

mv /etc/strongswan/ipsec.conf /etc/strongswan/ipsec.conf.bak;
cat > /etc/strongswan/ipsec.conf<<-EOF
config setup
    uniqueids=never 

conn %default
    keyexchange=ike              #ikev1 或 ikev2 都用这个
    left=%any                    #服务器端标识,%any表示任意
    leftsubnet=0.0.0.0/0,::/0    #服务器端虚拟ip, 0.0.0.0/0表示通配.
    right=%any                   #客户端标识,%any表示任意

conn IKE-BASE
    leftca=ca.cert.pem           #服务器端 CA 证书
    leftcert=server.cert.pem     #服务器端证书
    rightsourceip=10.10.0.0/24,fec3::/120   #分配给客户端的虚拟 ip 段

conn IKEv2-EAP
    also=IKE-BASE
    keyexchange=ikev2
    ike=aes256-sha256-modp1024,3des-sha1-modp1024,aes256-sha1-modp1024!
    esp=aes256-sha256,3des-sha1,aes256-sha1!
    rekey=no                     #服务器对 Windows 发出 rekey 请求会断开连接
    leftid=127.0.0.1             #远程ID,也就是服务器IP
    leftauth=pubkey
    leftsendcert=always
    #leftfirewall=yes
    right=%any
    rightfirewall=yes
    rightsourceip=10.10.0.0/24
    rightsendcert=never
    rightauth=eap-mschapv2
    eap_identity=%any
    dpdaction=clear
    fragmentation=yes
    auto=add

#供 ios 9以下使用, 使用客户端证书
conn IPSec-IKEv1
    also=IKE-BASE
    keyexchange=ikev1
    fragmentation=yes            #开启对 iOS 拆包的重组支持
    ike=aes256-sha1-modp1024
    leftauth=pubkey
    rightauth=pubkey
    rightauth2=xauth
    rightcert=client.cert.pem
    auto=add

#供 ios 9以下使用, 使用 PSK 预设密钥
conn IPSec-IKEv1-PSK
    also=IKE-BASE
    keyexchange=ikev1
    fragmentation=yes
    leftauth=psk
    rightauth=psk
    rightauth2=xauth
    auto=add

#供 android, linux, os x 使用
conn IPSec-IKEv2
    also=IKE-BASE
    keyexchange=ikev2
    leftauth=pubkey
    rightauth=pubkey
    rightcert=client.cert.pem
    auto=add

#供 windows 7+ 使用, win7 以下版本需使用第三方 ipsec vpn 客户端连接
conn IPSec-IKEv2-EAP
    also=IKE-BASE
    keyexchange=ikev2
    ike=aes256-sha1-modp1024!    #第一阶段加密方式
    rekey=no                     #服务器对 Windows 发出 rekey 请求会断开连接
    leftauth=pubkey
    rightauth=eap-mschapv2
    rightsendcert=never          #服务器不要向客户端请求证书
    eap_identity=%any
    auto=add

EOF

密码认证文件(注③)

cat > /etc/strongswan/ipsec.secrets<<-EOF
: RSA server.pem     #使用证书验证时的服务器端私钥
: PSK "123456"       #使用预设密钥时, 8-63位ASCII字符
: XAUTH "123456"     #这里是使用XAUTH验证时的用户名和密码
VPN %any : EAP "123456"  #这里是使用EAP验证时的用户名和密码
EOF

编辑/etc/strongswan/strongswan.conf文件

mv /etc/strongswan/strongswan.conf /etc/strongswan/strongswan.conf.bak
cat > /etc/strongswan/strongswan.conf<<-EOF
charon {
    load_modular = yes
    duplicheck.enable = no
    compress = yes
    plugins {
        include strongswan.d/charon/*.conf
    }
    dns1 = 8.8.8.8
    dns2 = 8.8.4.4
    nbns1 = 8.8.8.8
    nbns2 = 8.8.4.4
    filelog {
        # 设置日志文件,生产环境请关闭(删除就行)
        /var/log/charon.log {
            # 添加时间戳前缀
            time_format = %b %e %T
            # 附加连接名称,简化
            ike_name = yes
            # 覆盖现有文件
            append = no
            # 增加所有守护程序子系统的默认日志级别
            default = 1
            # 将每一行刷新到磁盘
            flush_line = yes
        }
    }
}
        
include strongswan.d/*.conf
        
EOF

更新(2019-12-27):
  注意:该配置在新版本(5.7.0即以上)会报syntax error, unexpected ., expecting : or '{' or '=' [.],需要修改配置文件为:

# 替换第三行的duplicheck.enable = no
duplicheck {
    enable = no
}

# 替换filelog{}的日志文件配置为
filelog {
    charon {
        # 日志文件的路径,在5.7.0之前的版本中将此名称指定为节名称
        path = /var/log/charon.log
        # 添加时间戳前缀
        time_format = %b %e %T
        # 附加连接名称,简化
        ike_name = yes
        # 覆盖现有文件
        append = no
        # 增加所有守护程序子系统的默认日志级别
        default = 2
        # 将每一行刷新到磁盘
        flush_line = yes
    }
    stderr {
        # 特定子系统的更详细的日志级别,将覆盖默认日志级别。
        ike = 2
        knl = 3
    }
}

启动strongswan

strongswan start

添加开机启动

echo 'strongswan start' >> /etc/rc.local

修改系统配置,允许转发

net.ipv4.tcp_syncookies = 1
net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.forwarding=1

保存

sysctl -p

修改防火墙规则,添加iptables规则

iptables -A INPUT -p esp -j ACCEPT
#允许 ISAMKP 数据包
iptables -A INPUT -p udp -m udp --dport 500 -j ACCEPT
#允许 IPSec NAT Traversal 数据包
iptables -A INPUT -p udp -m udp --dport 4500 -j ACCEPT
iptables -A FORWARD -s 10.10.0.0/24  -j ACCEPT

添加转发(注意修改自己的网卡,我的是venet0 )

iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o venet0 -j MASQUERADE

保存并重启iptables

service iptables save
service iptables restart

先下载安装一开始生成的密钥ca.cert.pem

IOS 9.x:

类型 IKEv2
服务器是 IP 或是 URL
远程ID是 IP 或是 URL
账户和密码填 ipsec.secrets 里 EAP 前后的那两个

IOS 9 以下:

类型 IPSec

查看调试信息

tail -f /var/log/charon.log

错误信息

"allocating SPI failed: Invalid argument (22)"
  libipsec插件未安装。见注①。

"opening '/etc/strongswan/ipsec.d/private/myKey.der' failed: No such file or directory"
  密钥文件配置错误。见注③。

"no virtual IP found for %any6 requested"
  未分配IPv6地址,把ipsec.conf里所有填IP的地方后面添加相应的IPv6地址段。例如:

leftsubnet=0.0.0.0/0,::/0

"no private key found for IP地址 generating IKE_AUTH response 1 [ N(AUTH_FAILED) ]"
  若IP地址为客户端,请检查客户端配置;若IP地址为服务器,请检查私钥文件配置。见注③。

"generating IKE_AUTH response 1 [ N(AUTH_FAILED) ]"
  注意和上条的区别。有可能是服务器端未配置leftid。

连上VPN但无法上网
  看看iptables的FORWARD中有没有REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited一条,删除就行。例如:

#查看iptables规则
iptables -nL
#删除FORWARD表中第一行
iptables -D FORWARD 1

已知问题

"id '%any' not confirmed by certificate"

"unable to set IPSEC_POLICY on socket"

"opening configuration file '/etc/tnc_config' failed: No such file or directory"

未找到解决办法,但不影响使用。


注①:
  libipsec插件OpenVZ必须安装,否则会出现"allocating SPI failed: Invalid argument (22)"错误。kvm可能不用安装(未测)。

注②:
  yum安装的strongswan,命令已经变成"strongswan --help"了,而手动编译的还是"ipsec --help",不要弄混,否则就是命令不存在了。

注③:
  yum安装的strongswan,默认位置是这里"/etc/strongswan/ipsec.secrets",而手动编译的则是这里"/etc/ipsec.secrets",要区分开,否则无法正确读取私钥。


参考链接:
  https://www.strongswan.org/documentation.html
  https://wiki.strongswan.org/issues/
  http://linsir.org/post/how_to_install_IPSec_IKEV2_base_on_strongswan_with_CentOS7
  http://blog.miffyliye.org/2014/04/18/%E4%B8%BAwindows-phone%E6%9E%B6%E8%AE%BEikev2-vpn%E6%9C%8D%E5%8A%A1%E5%99%A8/
  https://github.com/quericy/one-key-ikev2-vpn