本文介绍使用 StrongSwan 搭建 VPN 的过程,适合有一定 linux 基础的用户。
本文使用的服务器
- 1CPU,1G, 优惠码
- CentOS 8.3
- StrongSwan 5.8.2
StrongSwan 简介
StrongSwan 是基于 OpenSource IPsec 的 VPN 解决方案,官方网站:https://www.strongswan.org/ ,如果无法访问请使用科学上网,原因你懂的。
本文介绍使用 StrongSwan 搭建 VPN 的过程,适合有一定 linux 基础的用户。
StrongSwan 是基于 OpenSource IPsec 的 VPN 解决方案,官方网站:https://www.strongswan.org/ ,如果无法访问请使用科学上网,原因你懂的。
CentOS 8 安装请移步 《CentOS 8 使用 Strongswan IPsec IKEv2 搭梯》
本文介绍使用 StrongSwan 搭建 VPN 的过程,适合有一定 linux 基础的用户。
本文使用的服务器
StrongSwan 是基于 OpenSource IPsec 的 VPN 解决方案,官方网站:https://www.strongswan.org/ ,如果无法访问请使用科学上网,原因你懂的。
StrongSwan 运行于 Linux 系统上,本文使用 CentOS 7 系统。
由于基于源码自行编译安装过于繁琐,这里只介绍使用 yum 的安装方式。
首先,配置 StrongSwan 的源,此软件已包含在 EPEL 源中,关于配置 yum 源,请参考 《CentOS 7 配置 LNMP + FTP 环境》文中的 “添加常用软件源” 部分。
安装 StrongSwan
1 | yum install strongswan |
启用开机启动
1 | systemctl enable strongswan |
StrongSwan IPsec IKEv2 连接需要用到服务器证书,用于验证服务器身份。由于自签发证书不受操作系统信任,我们需要申请 Let’s Encrypt 免费证书。
申请方式参考《CentOS 7 Nginx Let’ s Encrypt SSL 证书安装配置》, 申请的域名必须是明确的,不能用通配符证书代替。例如,vpn.xxx.com, 申请证书时,必须带上 -d vpn.xxx.com 参数。
安装证书
假设上一步我们申请的证书保存在 /etc/letsencrypt/live/xxx.com 中,xxx.com 是你申请证书使用的域名。
我们使用创建软连接的方式使用证书
1 2 3 4 5 6 | cd /etc/strongswan/ipsec.d ln -s /etc/letsencrypt/live/xxx.com/fullchain.pem ./certs/fullchain.pem ln -s /etc/letsencrypt/live/xxx.com/privkey.pem ./private/privkey.pem #下载 letsencrype 中间证书, 此步对于 windows 客户端连接至关重要。 wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem -O /etc/strongswan/ipsec.d/cacerts/lets-encrypt-x3-cross-signed.pem |
证书安装完成
修改 ipsec.conf 主配置文件
1 | nano /etc/strongswan/ipsec.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 | conn setup uniqueids = no conn %default compress = yes keyexchange=ike ike=aes256-sha256-sha1-modp2048-modp1024,3des-sha256-sha1-modp2048-modp1024! esp=aes256-sha256-sha1,3des-sha256-sha1! leftdns=8.8.8.8,8.8.4.4 rightdns=8.8.8.8,8.8.4.4 conn ikev2 dpdaction=clear dpddelay=60s rekey=no fragmentation=yes eap_identity=%identity left=%any leftid=这里用你申请证书时使用的域名,如“xxx.com” leftsubnet=0.0.0.0/0 leftauth=pubkey leftcert=fullchain.pem leftsendcert=always leftfirewall=yes right=%any rightid=%any rightsourceip=10.1.0.0/24 rightauth=eap-mschapv2 rightsendcert=never auto=add |
修改 charon.conf, 配置日志输出文件。
1 | nano /etc/strongswan/strongswan.d/charon.conf |
日志不是必要项,建议只用在调试配置时使用,配置正常后注释掉 filelog 节部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | charon { filelog { charon-debug-log { path = /var/log/charon_debug.log time_format = %b %e %T default = 2 mgr = 0 net = 1 enc = 1 asn = 1 job = 1 ike_name = yes append = no flush_line = yes } } #这里是其它设置...... } |
修改 ipsec.secrets , 增加 vpn 账户。
1 | nano /etc/strongswan/ipsec.secrets |
添加服务端证书私钥,新建用户账号。
1 2 3 4 5 | #这是申请的证书的私钥 : RSA privkey.pem #这是用户账号,每行一个账号,格式为 [账号 %any : EAP "密码"] user1 %any : EAP "password1" user2 %any : EAP "password2" |
1 | nano /etc/sysctl.conf |
增加下面的内容
1 2 3 4 5 | # VPN 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 |
重新加载规则
1 | sysctl -p |
CentOS 7 默认使用 firewalld 防火墙, 有关 firewalld 的介绍请看这里。
允许 ‘AH’ 和 ‘ESP’ 身份验证协议和加密协议通过防火墙
1 2 | firewall-cmd --zone=public --permanent --add-rich-rule='rule protocol value="esp" accept' firewall-cmd --zone=public --permanent --add-rich-rule='rule protocol value="ah" accept' |
开放 ipsec 和相关端口
1 2 3 | firewall-cmd --zone=public --permanent --add-port=500/udp firewall-cmd --zone=public --permanent --add-port=4500/udp firewall-cmd --zone=public --permanent --add-service="ipsec" |
允许 ip 伪装
1 | firewall-cmd --zone=public --permanent --add-masquerade |
然后重新加载防火墙
1 | firewall-cmd --reload |
首先禁用 firewalld
1 2 | systemctl stop firewalld systemctl disable firewalld |
然后安装 iptables
1 2 | yum install iptables-services systemctl enable iptables |
配置 iptables
1 | nano /etc/sysconfig/iptables |
在默认内容基础上,添加几条规则(下面高亮的部分)。
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 | *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A POSTROUTING -m policy --pol ipsec --dir out -j ACCEPT -A POSTROUTING -s 10.1.0.0/24 -o eth0 -j MASQUERADE COMMIT *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -i eth0 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p ah -j ACCEPT -A INPUT -p esp -j ACCEPT -A INPUT -p udp -m udp --dport 500 -j ACCEPT -A INPUT -p udp -m udp --dport 4500 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -i eth0 -m policy --pol ipsec --dir in -j ACCEPT -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT |
重新加载 iptables 规则
1 | systemctl restart iptables |
1 | systemctl restart strongswan |
开始->设置->网络和Internet->vpn->添加vpn连接
添加完成后点击“更改适配器选项”
在vpn连接项点右键,属性->网络
双击 ipv4 ,点击“高级”
勾选“在远程网络上使用默认网关”, 取消“自动跃点”,手动填写跃点数为“10”(当自动跃点无法上网时才设置手动跃点)。如何确定跃点数,请看下面内容。
确定后连接 vpn 即可。
确定跃点数
因为 win10 系统的问题,经常会出现vpn连接能连上,就是打不开网页的情况,这是因为“本地连接”的优先级高于“vpn”的优先级,导致所有的请求优先使用“本地连接”的dns去解析域名,由于我们国家坚持推行使用社会主义特色的dns,所以某些域名解析会返回无效或错误的ip地址,这就导致我们无法正常访问网站!跃点数就是设定优先级用的。
我们需要做的就是让 “vpn 连接” 的跃点数小于 “本地连接” 的跃点数。
断开vpn, 打开 PowerShell 窗口,输入下面命令。
1 2 | #查看接口 Get-NetIPInterface -AddressFamily ipv4 |
第一列表示当前接口的索引号,第二列是名称,InterfaceMetric 列即接口的跃点,我的本地连接名是 WLAN, 跃点是35。
查看“本地连接”网卡的跃点数为 35,因此上一步中设置的跃点数只要小于35即可(跃点数越小优先级越高),所以我们设置为10。
“设置->VPN->添加配置”, 选 IKEv2
描述: 随便填
服务器: 填url或ip
远程ID: ipsec.conf 中的 leftid, 如 “xxx.com”
用户鉴定: 用户名
用户名: EAP 项用户名, 如 “user1”
密码: EAP 项密码, 如 “password1”
原理同 ios, 我没有 mac 做验证。
需下载安装客户端程序,前往官网下载
最新版 apk 程序
新写了一篇简单一点的文章,移步《CentOS 7 使用 Strongswan 配置 IKEv2 VPN》查看。
最近感觉我国”建筑行业龙头企业”的施工水平又有提升, ipsec + l2tp 方式也难逃厄运. so, 放弃, 改用 IKEv2.
google 到一款名为 strongSwan 的开源服务端. 官网为 https://www.strongswan.org.
本文只介绍 IKEv2 方式的 VPN 配置, 如果需要 PPTP 方式, 请参考 <<CentOS VPS 建立 PPTP VPN 服务>>
这里使用的 VPS 服务器配置:
strongSwan 的发行版已包含在 EPEL 源中, 如果没有添加 EPEL 源, 请看 <<CentOS 7 配置 LNMP + FTP 环境>> 添加 EPEL 源.
添加完 EPEL 源后输入如下命令
当前为 5.4.0 版本, 官网上最新为 5.5.0, 但是需要编译安装.
1 2 3 | yum install strongswan systemctl enable strongswan systemctl start strongswan |
1. 生成一个私钥:
1 | strongswan pki --gen --outform pem > ca.key.pem |
2. 基于这个私钥自己签一个 CA 根证书:
1 | strongswan pki --self --in ca.key.pem --dn "C=CN, O=ITnmg, CN=ITnmg StrongSwan CA" --ca --lifetime 3650 --outform pem > ca.cert.pem |
–self 表示自签证书
–in 是输入的私钥
–dn 是判别名
–ca 表示生成 CA 根证书
–lifetime 为有效期, 单位是天
1. 同样先生成一个私钥
1 | strongswan pki --gen --outform pem > server.key.pem |
2. 用我们刚才自签的 CA 证书给自己发一个服务器证书:
1 2 3 4 5 | #从私钥生成公钥 strongswan pki --pub --in server.key.pem --outform pem > server.pub.pem #用刚生成的公钥生成服务器证书 strongswan pki --issue --lifetime 3600 --cacert ca.cert.pem --cakey ca.key.pem --in server.pub.pem --dn "C=CN, O=ITnmg, CN=vpn.itnmg.net" --san="vpn.itnmg.net" --flag serverAuth --flag ikeIntermediate --outform pem > server.cert.pem |
–issue, –cacert 和 –cakey 就是表明要用刚才自签的 CA 证书来签这个服务器证书。
–dn, –san,–flag 是一些客户端方面的特殊要求:
客户端证书是在启用客户端证书验证的时候, 用于验证客户端用户身份的. 每个用户一个证书. 如果需要很高的安全性, 可以用客户端证书, 一般情况下, 不需要使用.
1. 依然是生成私钥:
1 | strongswan pki --gen --outform pem > client.key.pem |
2. 然后用刚才自签的 CA 证书来签客户端证书:
1 2 3 4 5 | #从私钥生成公钥 strongswan pki --pub --in client.key.pem --outform pem > client.pub.pem #这里就不需要上面那一堆特殊参数了 strongswan pki --issue --lifetime 1200 --cacert ca.cert.pem --cakey ca.key.pem --in client.pub.pem --dn "C=CN, O=ITnmg, CN=vpn.itnmg.net" --outform pem > client.cert.pem |
1 | openssl pkcs12 -export -inkey client.key.pem -in client.cert.pem -name "ITnmg StrongSwan Client Cert" -certfile ca.cert.pem -caname "ITnmg StrongSwan CA" -out client.cert.p12 |
此时会提示输入两次密码, 这个密码是在导入证书到其他系统时需要验证的. 没有这个密码即使别人拿到了证书也没法使用.
1 2 3 4 5 6 7 | cp -r ca.key.pem /etc/strongswan/ipsec.d/private/ cp -r ca.cert.pem /etc/strongswan/ipsec.d/cacerts/ cp -r server.cert.pem /etc/strongswan/ipsec.d/certs/ cp -r server.pub.pem /etc/strongswan/ipsec.d/certs/ cp -r server.key.pem /etc/strongswan/ipsec.d/private/ cp -r client.cert.pem /etc/strongswan/ipsec.d/certs/ cp -r client.key.pem /etc/strongswan/ipsec.d/private/ |
把 CA 证书(ca.cert.pem)、客户端证书(client.cert.pem)和 .p12 证书(client.cert.p12)用 FTP 复制出来给客户端用
先修改主配置
1 | nano /etc/strongswan/ipsec.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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | config setup #是否缓存证书吊销列表 #<em>cachecrls = yes</em> #是否严格执行证书吊销规则 # strictcrlpolicy=yes #如果同一个用户在不同的设备上重复登录,yes 断开旧连接,创建新连接;no 保持旧连接,并发送通知; never 同 no, 但不发送通知. uniqueids=no #配置根证书, 如果不使用证书吊销列表, 可以不用这段. 命名为 %default 所有配置节都会继承它 #ca %default #证书吊销列表url,可以是 LDAP, http, 或文件路径 #crluri = <uri> #定义连接项, 命名为 %default 所有连接都会继承它 conn %default #是否启用压缩, yes 表示如果支持压缩会启用. compress = yes #当意外断开后尝试的操作, hold, 保持并重连直到超时. dpdaction = hold #意外断开后尝试重连时长 dpddelay = 30s #意外断开后超时时长, 只对 IKEv1 起作用 dpdtimeout = 60s #闲置时长,超过后断开连接. inactivity = 300s #数据传输协议加密算法列表 esp = aes256-sha256,aes256-sha1,3des-sha1! #密钥交换协议加密算法列表 ike = aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024! #默认的密钥交换算法, ike 为自动, 优先使用 IKEv2 keyexchange = ike #服务端公网ip, 可以是魔术字 %any,表示从本地ip地址表中取. left = %any #客户端ip, 同上 right = %any #指定服务端与客户端的dns, 多个用","分隔 leftdns = 8.8.8.8,8.8.4.4 rightdns = 8.8.8.8,8.8.4.4 #服务端用于ike认证时使用的端口, 默认为500,如果使用了nat 转发, 则使用4500 #leftikeport = <port> #服务器端虚拟ip地址 #leftsourceip = %config #客户端虚拟ip段 rightsourceip = 10.0.0.0/24 #服务器端子网, 魔术字 0.0.0.0/0. 如果为客户端分配虚拟 IP 地址的话,那表示之后要做 iptables 转发,那么服务器端就必须是用魔术字 leftsubnet = 0.0.0.0/0 #rightsubnet = <ip subnet>[[<proto/port>]][,...] conn IKEv2-BASE #服务器端根证书DN名称 leftca = "C=CN, O=ITnmg, CN=ITnmg StrongSwan CA" #服务器证书, 可以是 PEM 或 DER 格式 leftcert = server.cert.pem #不指定客户端证书路径 #rightcert = <path> #指定服务器证书的公钥 leftsigkey = server.pub.pem #rightsigkey = <raw public key> | <path to public key> #是否发送服务器证书到客户端 leftsendcert = always #客户端不发送证书 rightsendcert = never #服务端认证方法,使用证书 leftauth = pubkey #客户端认证使用 EAP 扩展认证 , 貌似 eap-mschapv2 比较通用 rightauth = eap-mschapv2 #服务端id, 可以任意指定, 默认为服务器证书的 subject, 还可以是魔术字 %any,表示什么都行. leftid = vpn.itnmg.net #客户端id, 任意 rightid = %any #ios, mac os, win7+, linux conn IKEv2-EAP also=IKEv2-BASE #指定客户端eap id eap_identity = %any #不自动重置密钥 rekey = no #开启IKE 消息分片 fragmentation = yes #当服务启动时, 应该如何处理这个连接项. add 添加到连接表中. auto = add |
我的设置项
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 | config setup uniqueids=no conn %default compress = yes esp = aes256-sha256,aes256-sha1,3des-sha1! ike = aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha1-modp2048,3des-sha1-modp2048,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024! keyexchange = ike keyingtries = 1 leftdns = 8.8.8.8,8.8.4.4 rightdns = 8.8.8.8,8.8.4.4 conn ikev2-eap leftca = "C=CN, O=ITnmg, CN=ITnmg StrongSwan CA" leftcert = server.cert.pem leftsendcert = always rightsendcert = never leftid = vpn.itnmg.net left = %any right = %any leftauth = pubkey rightauth = eap-mschapv2 leftfirewall = yes leftsubnet = 0.0.0.0/0 rightsourceip = 10.1.0.0/16 fragmentation = yes rekey = no eap_identity=%any auto = add |
v5.1.2 之后, 所有插件配置都分散在 /etc/strongswan/strongswan.d/ 目录中.
1 | nano /etc/strongswan/strongswan.d/charon.conf |
修改如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | charon { duplicheck.enable = no #同时连接多个设备,把冗余检查关闭. # windows 公用 dns dns1 = 8.8.8.8 dns2 = 8.8.4.4 #以下是日志输出, 生产环境请关闭. filelog { /var/log/charon.log { # add a timestamp prefix time_format = %b %e %T # prepend connection name, simplifies grepping ike_name = yes # overwrite existing files append = no # increase default loglevel for all daemon subsystems default = 1 # flush each line to disk flush_line = yes } } } |
1 | nano /etc/strongswan/ipsec.secrets |
下面添加用户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #使用证书验证时的服务器端私钥 #格式 : RSA <private key file> [ <passphrase> | %prompt ] : RSA server.key.pem #使用预设加密密钥, 越长越好 #格式 [ <id selectors> ] : PSK <secret> %any : PSK "预设加密密钥" #EAP 方式, 格式同 psk 相同 用户名 : EAP "密码" #XAUTH 方式, 只适用于 IKEv1 #格式 [ <servername> ] <username> : XAUTH "<password>" 用户名 : XAUTH "密码" |
1 | nano /etc/sysctl.conf |
写入以下配置
1 2 3 | # VPN net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding=1 |
保存退出, 执行下面命令.
1 | sysctl -p |
将下面几条规则加入 iptables 规则中, 适当使用 -I 参数替换 -A 参数, 确保所有的项目位置都在拒绝项前面.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #开放端口 iptables -A INPUT -p udp --dport 500 -j ACCEPT iptables -A INPUT -p udp --dport 4500 -j ACCEPT #启用ip伪装 iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -o eth0 -m policy --dir out --pol ipsec -j ACCEPT iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE #添加转发 iptables -A FORWARD -s 10.1.0.0/16 -j ACCEPT #保存规则 service iptables save #重启服务 systemctl restart iptables |
如果嫌上面的操作麻烦, 可以直接编辑 iptables 规则文件.
1 | nano /etc/sysconfig/iptables |
将下面的规则部分贴进去, 不要整个复制粘贴, 根据原有规则适当调整每条规则的位置, 确保规则在拒绝项前, 使之能生效.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 10.1.0.0/16 -o eth0 -m policy --dir out --pol ipsec -j ACCEPT -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE COMMIT *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p udp -m udp --dport 500 -j ACCEPT -A INPUT -p udp -m udp --dport 4500 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -s 10.1.0.0/16 -j ACCEPT -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT |
保存退出, 重启 iptables 使之生效.
1 | systemctl restart iptables |
firewalld 介绍请看
<<CentOS 7 firewalld 动态防火墙介绍>>