使用IPsec搭建vpn系统

多机房情况下,有时候需要将跨机房内网打通,现在还是使用ipsec的多。而且相对也比较成熟。IPsec全称ip Security,由两类协议组成,分别为AH协议(Authentication Header)和ESP协议(Encapsulated Security Payload),由于AH协议无法提供数据加密,所有数据在传输时以明文传输,且AH由于提供数据来源确认,所以无法穿越NAT,所以这两种协议中ESP协议应用更广泛一些。VPN只是IPSec的一种应用方式。刚好有空余的机器就简单实验一下。

协议 数据来源确认 数据加密 数据完整性确认 其他
AH AH常用摘要算法(单向Hash函数)MD5和SHA1
ESP ESP通常使用DES、3DES、AES等加密算法实现数据加密,使用MD5或SHA1来实现数据完整性

搭建

实验环境

Region Public IP Private IP Gateway
CD-Host-A 118.24.48.193 172.27.0.12 172.27.0.1
CD-Host-B 118.24.49.251 172.27.0.4 172.27.0.1
GZ-Host-A 193.112.154.165 172.16.0.10 172.16.0.1
GZ-Host-B 193.112.143.226 172.16.0.16 172.16.0.1

版本信息:
规划:其中CD-A和GZ-A这两台机器作为vpn服务器。
版本:Linux Libreswan 3.20 (netkey) on 3.10.0-514.26.2.el7.x86_64
OS:CentOS Linux release 7.2.1511 (Core)

安装初始化(主机CD-A)

1
yum install -y openswan

系统参数调整

1
2
3
4
5
6
7
8
cat /etc/sysctl.conf #修改参数如下
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
sysctl -p #执行命令让参数生效
setenforce 0 #关闭selinux
iptables -nvL #确认端口开放UDP 500 4500
#关闭ipmp重定向(是否需要)
#sysctl -a | egrep "ipv4.*(accept|send)_redirects" | awk -F "=" '{print$1"= 0"}' >> /etc/sysctl.conf

主配置如下

1
2
3
4
5
6
7
8
#cat /etc/ipsec.conf
#version 2
config setup
protostack=netkey
dumpdir=/var/run/pluto/
nat_traversal=yes
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
include /etc/ipsec.d/*.conf

配置key认证

1
echo 0.0.0.0 0.0.0.0 : PSK "arvon.top" > /etc/ipsec.d/cn.secrets#引号内为key字段

关于配置:可以通过命令man ipsec.conf获得帮助
填写连接的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#cat /etc/ipsec.d/cn.conf
conn cn-test
ike=3des-sha1
authby=secret
phase2=esp
phase2alg=3des-sha1
compress=no
pfs=yes
type=tunnel
left=172.27.0.12
leftid=118.24.48.193
leftsubnet=172.27.0.0/24
leftnexthop=%defaultroute
right=193.112.154.165
rightid=193.112.154.165
rightsubnet=172.16.0.0/24
rightnexthop=%defaultroute
auto=add

启动ipsec
Tips:修改连接配置auto=start,这样就不用每次重启ipsec后手动起连接了

1
2
systemctl start ipsec
ipsec auto --up cn-test

安装初始化(主机GZ-A)

注意:配置基本可以从CD-A照搬过来,不过由于我这里的环境是云端不同子网,所以连接的配置还需要做一些修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#cat /etc/ipsec.d/cn.conf
conn cn-test
ike=3des-sha1
authby=secret
phase2=esp
phase2alg=3des-sha1
compress=no
pfs=yes
type=tunnel
left=118.24.48.193
leftid=118.24.48.193
leftsubnet=172.27.0.0/24
leftnexthop=%defaultroute
right=172.16.0.10
rightid=193.112.154.165
rightsubnet=172.16.0.0/24
rightnexthop=%defaultroute
auto=add

此时,两台IPsec server已经联通了,不过是CD-B和GZ-B无法和对端网络联通,并没有达到实验目的,很明显现在主要问题是路由

问题

Step0: 方便排错

1
2
3
4
5
6
7
8
9
10
route -n #查看路由
ip rule ls #查看路由优先级
ip route get 172.27.0.4 #获取IP地址使用的路由
route add -net 10.0.60.0 netmask 255.255.255.0 gw 10.0.50.1 #添加路由
route del -net 172.16.0.0 netmask 255.255.255.0 eth0 #删除路由需要写完整
#systemctl start firewalld
iptables -t nat -F #清除防火墙nat规则
iptables -t nat -nvL #查看防火墙nat规则
tcpdump -n -i eth0 dst 172.27.0.12 #抓取eth0网卡上目标IP为12的包
tcpdump -n -i eth0 src 172.27.0.12 #抓取eth0网卡上源IP为12的包

Step1:以CD-A为例,当前路由如下

1
2
3
4
5
6
[root@VM_0_12_centos ipsec.d]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.27.0.1 0.0.0.0 UG 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
172.27.0.0 0.0.0.0 255.255.240.0 U 0 0 0 eth0

Step2: 在内网其他机器添加到VPN的路由

1
2
3
4
#在CD-B添加到CD-A的路由
route add -net 172.16.0.0 netmask 255.255.255.0 gw 172.27.0.12
#在GZ-B添加到GZ-A的路由
route add -net 172.27.0.0 netmask 255.255.255.0 gw 172.16.0.10

Step3:在vpn网关机器上进行SNAT

1
2
3
iptables -t nat -A POSTROUTING -s 172.27.0.0/24 -d 172.16.0.0/24 -j SNAT --to 118.24.48.193
#iptables -t nat -A POSTROUTING -s 172.27.0.0/24 -d 172.16.0.0/24 -j RETURN
#iptables -t nat -A POSTROUTING -s 172.27.0.0/24 -o eth0 -j MASQUERADE

最后说一下:比较容易踩坑的是使用公有云,由于外网网卡并不是直接与内网实例关联的,说以需要其他的途径才可以实现,一般对应服务商都有解决方案,而且关于ipsec连接配置也跟这个有关,具体还需要看一下实际情况。

参考链接

openswan github
ipsec vpn
唐霜的vpn教程
ucloud教程