为了保证安全的同时,在外网也能便利访问家里的服务,同时又能减少转发带来流量,VPN绝对是最佳的选择。这里我就用StrongSwan
搭建一个基于证书认证的IPSec VPN
。
IPsec 是什么?StrongSwan又是什么?
IPsec
全称 Internet Protocol Security, 即互联网安全协议,是一个协议包,包含了AH、ESP、IKE/IKEv2
这些协议,其作用是通过加密和认证保证端到端的IP数据传输的安全。当前,IPsec
协议主要就是用于VPN
。
StrongSwan
是一个跨平台的开源项目,Linux
上实现了 IPsec
功能,所以我们这里用它来搭建。
想要详细了解其细节,推荐阅读:
- Wiki - IPsec
- Cloudflare - What is IPsec? | How IPsec VPNs work
- Wiki - StrongSwan
准备工作
1. Linux 系统
我的系统是 CentOS 7.
$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
$ uname -a
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
2. 域名 & 域名解析
如我的域名 vpn.razeencheng.com
, 解析已OK。
vpn.razeencheng.com. 600 IN A 192.168.100.53
3. 准备自签发证书
由于是搭建基于自签发证书认证的,我们需要提前准备好需要的自签发证书,这里我们需要:
- 自建根证书
- VPN 的服务证书(自建根签发的)
- VPN 的客户端证书(自建根签发的)
我这里推荐使用 KeyManager 生成,这是我司开发的一款离线证书管理软件,可以在这里下载。
软件安装好后,打开如下,设计一个密码就可以进入了(密码别忘了哦,除了用恢复密钥外没有办法恢复的)。
首先我们来生成一张根证书。进入软件后,点击“创建测试证书”, 然后将表单往下拉,我们可以看到有一个 “创建根证书” 按钮,点击。 然后我们需要为自己的更起个“霸气”的名字。点击“高级设置”,我们可以选择算法等,这里我就都用默认,只把有效期改长一点,给个480月吧,最后滚动到最下面,点击“创建根证书“即可完成根证书创建。
如下,成功后我们可以看到根证书的详细信息。
接下来,我们用这张根签发一张服务器证书。再次点击“创建测试证书”,如下图所示,证书类型选择“服务器证书”,写上自己将要使用的VPN 域名,有效期也可以改长点。最重要的是,“证书签发者” 选刚刚创建的这张证书,最后点击“创建证书”。
继续,我们再签发一张客户端证书,其他操作和上面一样,除了“证书类型”选择客户端证书外。
这样,我们在"所有证书"中,就能看到我们生成的客户端和服务器证书,点击对应证书的“更多”,选择“导出证书”, 客户端证书我们选择pfx格式(需要设置一个密码),服务端证书,选择“Nginx”,点击导出。 然后在“CA证书”栏中同样操作,选择Nginx,导出刚刚的根证书。
如下图所示,这样我们的证书全部准备就绪了,我们需要的就是:
- 根证书公钥(图中 Razeen Test Root 2021_chain.crt)
- 客户端证书公私钥(图中 razeencheng-s-vpn-iis-0910233719.pfx)
- 服务端的证书共私钥 (图中 vpn.razeencheng.com_chain.crt 和 vpn.razeencheng.com_key.key)
开始安装
1. 安装 EPEL 源,安装 strongswan。
$ yum -y install epel-release
$ yum -y install strongswan
安装好后,strongswan
的目录为/etc/strongswan/
。
2. 将证书放到对应的位置。
- 根证书放到
/etc/strongswan/ipsec.d/cacerts
下; - 服务器证书公钥放到
/etc/strongswan/ipsec.d/certs
下: - 服务器证书私钥放到
/etc/strongswan/ipsec.d/private
下。
放好后,目录结构如下:
3. 配置 Strongswan
我们到 /etc/strongswan
目录,把原来的默认配置文件备份下。
$ cd /etc/strongswan
$ mv ipsec.conf ipsec.conf.bak
我们创建一个新的ipsec.conf
。
$ vim ipsec.conf
粘贴下面的配置。
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
# strictcrlpolicy=yes
# uniqueids = no
conn %default
keyexchange=ikev2
ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024!
esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1!
dpdaction=clear
dpddelay=300s
rekey=no
left=%any
leftsubnet=0.0.0.0/0
leftcert=vpn.razeencheng.com_chain.crt
right=%any
rightdns=192.168.1.1,114.114.114.114
rightsourceip=192.168.252.0/24
rightca="C=CN, CN=Razeen Test Root 2021"
conn IPSec-IKEv2
keyexchange=ikev2
auto=add
conn IPSec-IKEv2-EAP
also="IPSec-IKEv2"
rightauth=eap-mschapv2
rightauthby2=pubkey
rightsendcert=never
eap_identity=%any
conn CiscoIPSec
keyexchange=ikev1
forceencaps=yes
authby=xauthrsasig
xauth=server
auto=add
这里你需要修改的是:
leftcert=vpn.razeencheng.com_chain.crt
这里 left 我们可以理解为VPN服务端这边,这里指定我们的服务端证书的名字(上面我们放到/etc/strongswan/ipsec.d/certs
文件夹下的)。rightdns=192.168.1.1,114.114.114.114
这里 right 可以理解为VPN的客户端那边,指定客户端连接后使用的DNS,可以逗号分隔指多个。rightsourceip=192.168.200.0/24
这里指VPN客户端端连接后分配的子网。rightca="C=CN, CN=Razeen Test Root 2021"
对客户端证书的CA Subject 限制,这里改成你的CA证书对应的。可用openssl
快速查看,Subject:
后面的内容复制上来即可。$ openssl x509 -in ipsec.d/cacerts/Razeen\ Test\ Root\ 2021_chain.crt -text | grep "Subject:" Subject: C=CN, CN=Razeen Test Root 2021
如果需要理解配置中其他参数的含义,可以看官方的 wiki - IpsecConf。
4. 配置私钥和账户密码
编辑ipsec.secrets
文件,例如:
: RSA vpn.razeencheng.com_key.key
testuser : EAP "test1234"
testuser2 : EAP "test5678"
这里:
: RSA vpn.razeencheng.com_key.key
指定我们的服务端的私钥文件名字(上面我们放到/etc/strongswan/ipsec.d/private
文件夹下的);testuser : EAP "test1234"
就是我们的账号密码了。这里我加了两个用户testuser
和testuser2
, 密码分别为test1234
和test5678
。
想了解更多配置含义,可以看 wiki - IpsecSecrets。
5. 启动 strongswan
# 启动
systemctl start strongswan
# 设置开启启动
systemctl enable strongswan
6. 设置防火墙
# 添加 AH ESP 协议
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 服务端口和服务
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"
# 允许 NET 地址伪装并重载
firewall-cmd --zone=public --permanent --add-masquerade
firewall-cmd --reload
7. 允许端口转发
编辑 /etc/sysctl.conf
文件,允许端口转发。
# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
目前我们只设置了ipv4的。允许下面命令重载。
$ sysctl -p
重启 strongswan。
$ systemctl restart strongswan
到这里我们的安装过程就结束了。
连接测试
当然,连接之前你还有域名别忘你解析到你的主机上。。
最后经过测试,连接正常。而客户端的配置过程,稍微有点复杂,而且在配置 macOS Big Sur
过程中还遇到一些坑,关于这些详细内容,请看我的下一篇文章。