上一篇Linux的gre隧道 讲到GRE隧道, 但是GRE是明文传输的, 有一定的安全隐患, 于是需要进行加密处理, 加密一般有两个, GRE over IPSec和IPSec over GRE
两者的区别是, GRE over IPSec是先将数据封装成GRE协议, 再通过IPSec隧道加密传输, 对于外界来说, 看到的都是ESP加密数据包, 并不知道内部是什么, 当然也不知道你内部是GRE.
而IPSec over GRE是先将数据用IPSec加密, 再通过GRE隧道出去, 对于外界来说, 知道你是用GRE传输的, 但是传输的是什么就不知道了, 看到的都是ESP
这里用的是Centos+libreswan来做IPSec, 当然也可以用strongswan/openswan什么的. 原理都是一样的
Server A:
IP: 1.0.0.4
GRE IP: 10.0.0.1
Server B:
IP: 1.0.0.5
GRE IP: 10.0.0.2
首先在两台服务器上都安装libreswan
yum install -y libreswan
装好之后都要执行一下
ipsec initnss
接下来生成rsa密钥对. 在两台server上都执行
ipsec newhostkey
这需要一些时间
GRE over IPsec
在Server A上运行
ipsec showhostkey --left
可以看到类似这样的输出:
ipsec showhostkey loading secrets from "/etc/ipsec.secrets" # rsakey AQOcq+xzO leftrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlOOuKiSvP0RDFPHzKBYgse9tT........
然后我们复制leftrsasigkey以及后面的一大串到剪切板备用
之后编辑
/etc/ipsec.d/ipsec.conf
这个文件默认是不存在的, 直接创建就可以了, 然后加入以下内容
config setup protostack=netkey conn gre1 left=1.0.0.4 right=1.0.0.5 authby=rsasig auto=start leftprotoport=gre rightprotoport=gre type=transport leftrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlOOuKiSvP0RDFPHzKBYgse9tT........
然后不要关闭编辑这个文件, 同时你应该知道为什么要把刚刚的一大串复制备用了吧. 接着在Server B上执行
ipsec showhostkey --right
注意是–right, 同时也把rightrsasigkey和后面的一串复制给Server A上的ipsec.conf后, 跟着leftrsasigkey另起一行, 最后的文件内容类似与
conn gre1 left=1.0.0.4 right=1.0.0.5 authby=rsasig auto=start leftprotoport=gre rightprotoport=gre type=transport leftrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlO........ rightrsasigkey=0sAQPiT6xbnBMuPLbXxfT3iQ9yDhlD4U7FdqOR......
然后在Server B上也创建同样的ipsec.conf文件, 并且内容和Server A上是ipsec.conf差不多, 只不过是把left和right对调一下, 也就是:
conn gre1 left=1.0.0.5 right=1.0.0.4 authby=rsasig auto=start leftprotoport=gre rightprotoport=gre type=transport leftrsasigkey=0sAQPiT6xbnBMuPLbXxfT3iQ9yDhlD4U7FdqOR...... rightrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlO........
特别需要注意leftrsasigkey和rightrsasigkey的内容也要调换!
然后启动ipsec服务, 在两台Server 上都执行
systemct start ipsec
启动成功后在Server A上ping Server B的GRE IP
ping 10.0.0.2
如果能成功ping 通, 那基本就成功了, 此时在Server B上用tcpdump看下包
先看enp0s3上的包
tcpdump -nn -i enp0s3 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp0s3, link-type EN10MB (Ethernet), capture size 65535 bytes 22:44:37.448828 IP 1.0.0.5 > 1.0.0.4: ESP(spi=0x2cf3f2c6,seq=0x9), length 132 22:44:37.449159 IP 1.0.0.4 > 1.0.0.5: ESP(spi=0x3c9c7eb2,seq=0x9), length 132 22:44:38.450729 IP 1.0.0.5 > 1.0.0.4: ESP(spi=0x2cf3f2c6,seq=0xa), length 132
可以看到数据是ESP加密的, 然后再看看gre1上的包
tcpdump -nn -i gre1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on gre1, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 22:45:40.492113 IP 10.0.0.2 > 10.0.0.1: ICMP echo request, id 3800, seq 64, length 64 22:45:40.492174 IP 10.0.0.1 > 10.0.0.2: ICMP echo reply, id 3800, seq 64, length 64 22:45:41.492888 IP 10.0.0.2 > 10.0.0.1: ICMP echo request, id 3800, seq 65, length 64 22:45:41.492910 IP 10.0.0.1 > 10.0.0.2: ICMP echo reply, id 3800, seq 65, length 64
gre1上的包已经是明文了.
但是当我们在Server A上直接ping Server B是1.0.0.5 ip, 在enp0s3上看到是明文的ICMP echo包, 这说明了IPSec仅作用于gre协议上, 这实际是leftprotoport和rightprotoport起的作用.
如果没有指定这两个参数, 那你ping 1.0.0.5的ip的时候也会被IPSec加密.
IPSec over GRE
这里和上面是配置文件区别在于
去掉了leftprotoport, rightprotoport, type. 同时left和right都改成gre ip, 而不是公网ip
也就是配置文件类似于
conn gre1 left=10.0.0.1 right=10.0.0.2 authby=rsasig auto=start leftrsasigkey=0sAQPiT6xbnBMuPLbXxfT3iQ9yDhlD4U7FdqOR...... rightrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlO........
注意, 此处的left和right分别是Server A和Server B在GRE 隧道上的IP, 同时需要注意Server A和Server B是left和right的值需要相对应.
其他的部分都是一样的. 包括key什么的.
当配置好之后, 启动IPSec或者重启IPSec服务
然后我们继续在Server A上不间断的ping Server B的GRE IP
ping 10.0.0.2
在Server B上tcpdump查看enp0s3上的数据包
tcpdump -nn -i enp0s3 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp0s3, link-type EN10MB (Ethernet), capture size 65535 bytes 22:56:57.936479 IP 1.0.0.5 > 1.0.0.4: GREv0, length 156: IP 10.0.0.2 > 10.0.0.1: ESP(spi=0x538dedb6,seq=0x5), length 132 22:56:57.936578 IP 1.0.0.4 > 1.0.0.5: GREv0, length 156: IP 10.0.0.1 > 10.0.0.2: ESP(spi=0x0d038130,seq=0x5), length 132 22:56:58.936917 IP 1.0.0.5 > 1.0.0.4: GREv0, length 156: IP 10.0.0.2 > 10.0.0.1: ESP(spi=0x538dedb6,seq=0x6), length 132 22:56:58.937212 IP 1.0.0.4 > 1.0.0.5: GREv0, length 156: IP 10.0.0.1 > 10.0.0.2: ESP(spi=0x0d038130,seq=0x6), length 132
我们可以看到Server A和Server B之间公网IP的数据是通过GRE协议传输的, 同时GRE的两端是GRE IP, 但是具体这两个GRE IP在传输什么是无法被外界获取的, 都是ESP加密过的了.
特殊NAT情况
有时候会遇到Server处在NAT后方, 但是Server在NAT上有一对一的对应IP, 比如腾讯云的情况
腾讯云的Server的公网IP并不是直接绑在Server的网卡上的, 而是在一个NAT上的.
举个例子来说, 我腾讯云公网IP是1.2.3.4, 但是我在Server上用ip addr看到的eth0的IP却是这样的:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 52:54:00:d4:6f:3a brd ff:ff:ff:ff:ff:ff inet 10.104.224.4/18 brd 10.104.255.255 scope global eth0 valid_lft forever preferred_lft forever
可以看到网卡上的IP是内网的10.104.224.4, 这种情况下IPSec over GRE是不受影响的, 但是按照上面的思路缺无法建立GRE over IPSec
假设有这么一个上述的Server C,
公网IP是1.2.3.4
网卡上绑定是: 10.1.0.0.1
要和Server A建立GRE over IPSec, 当你Server C上这么配置的时候
conn gre1 left=1.2.3.4 right=1.0.0.4 authby=rsasig auto=start leftprotoport=gre rightprotoport=gre type=transport leftrsasigkey=0sAQPiT6xbnBMuPLbXxfT3iQ9yDhlD4U7FdqOR...... rightrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlO........
启动IPSec服务的时候, 在Server C上会看到类似这样的错误
022 "gretx": We cannot identify ourselves with either end of this connection. 1.2.3.4 or 1.0.0.4 are not usable
因为Server C上并没有绑定1.2.3.4这个IP, IPSec服务就无法在1.2.3.4这个IP上监听了.
而当你把Server C上的left改成10.1.0.0.1之后, Server C虽然可以启动IPSec了, 但是Server A上又会报这样的错误:
003 "gretx" #1: NAT-Traversal: Result using RFC 3947 (NAT-Traversal) sender port 500: peer behind NAT 002 "gretx" #1: transition from state STATE_MAIN_I2 to state STATE_MAIN_I3 108 "gretx" #1: STATE_MAIN_I3: sent MI3, expecting MR3 003 "gretx" #1: received Vendor ID payload [CAN-IKEv2] 002 "gretx" #1: Main mode peer ID is ID_IPV4_ADDR: '10.1.0.0.1' 003 "gretx" #1: we require IKEv1 peer to have ID '1.2.3.4', but peer declares '10.1.0.0.1' 218 "gretx" #1: STATE_MAIN_I3: INVALID_ID_INFORMATION 002 "gretx" #1: sending encrypted notification INVALID_ID_INFORMATION to 1.2.3.4:4500
注意看倒数第三行的错误, Server A要求对端(也就是Server C)返回的ID是1.2.3.4, 但实际上Server C返回的却是10.1.0.0.1, 这是因为Server C在启动IPSec服务的时候, 监听了10.1.0.0.1这个IP, 但是正常情况下应该是要监听1.2.3.4, 然而1.2.3.4也无法监听.
解决办法就是: 在Server C的ipsec.conf里面加上一个leftid字段, 值是1.2.3.4, 也就是Server C的实际公网IP
Server C的正确配置像这样:
conn gre1 left=%defaultroute right=1.0.0.4 authby=rsasig auto=start leftprotoport=gre rightprotoport=gre type=transport leftrsasigkey=0sAQPiT6xbnBMuPLbXxfT3iQ9yDhlD4U7FdqOR...... rightrsasigkey=0sAQOcq+xzOPYivlZ8kXvALHTJhWwH2IluTzlO........ leftid=1.2.3.4
这样就可以顺利的在Server A和C之间建立起GRE over IPSec了
同理就算两台Server都是这种NAT结构, 只需要都增加leftid和rightid就可以解决问题了.
日志是这样的:
10月 16 20:19:28 greoveripsec-138-7 addconn[2056]: cannot load config ‘/etc/ipsec.conf’: /etc/ipsec.d/ipsec.conf:9: syntax error, unexpected KEYWORD, expecting $end [leftrsasigkey]
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: ipsec.service: control process exited, code=exited status=3
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: Failed to start Internet Key Exchange (IKE) Protocol Daemon for IPsec.
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: Unit ipsec.service entered failed state.
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: ipsec.service failed.
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: ipsec.service holdoff time over, scheduling restart.
10月 16 20:19:28 greoveripsec-138-7 systemd[1]: Starting Internet Key Exchange (IKE) Protocol Daemon for IPsec…
你好,按照你得方法,IPsec服务起不来,有报错,还请指点。
● ipsec.service – Internet Key Exchange (IKE) Protocol Daemon for IPsec
Loaded: loaded (/usr/lib/systemd/system/ipsec.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since 日 2020-10-18 23:43:12 CST; 14s ago
Docs: man:ipsec(8)
man:pluto(8)
man:ipsec.conf(5)
Process: 5612 ExecStartPre=/usr/libexec/ipsec/addconn –config /etc/ipsec.conf –checkconfig (code=exited, status=3)
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: ipsec.service: control process exited, code=exited status=3
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: Failed to start Internet Key Exchange (IKE) Protocol Daemon for IPsec.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: Unit ipsec.service entered failed state.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: ipsec.service failed.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: ipsec.service holdoff time over, scheduling restart.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: start request repeated too quickly for ipsec.service
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: Failed to start Internet Key Exchange (IKE) Protocol Daemon for IPsec.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: Unit ipsec.service entered failed state.
10月 18 23:43:12 greoveripsec-138-7 systemd[1]: ipsec.service failed.
这个看起来是配置文件写错了。如果能有完整的/etc/ipsec.conf就知道原因了
conn gre1
authby=rsasig
auto=start
type=transport
left=192.168.88.4
leftprotoport=gre
leftrsasigkey=0sAwEAAbVtN2BjwRq9hqtQwTazkEF+kZXWfSBlH/m4KhmPU1a20FipUmqmVlhy/MZn27hMl6aaPP1iXonU4mb3PKCOCDoZJgIU3b7b6Q1uaQGlkXArUIdezHBZ9YUp+Rx676lWjPRJJt5EURUWTEpe5LbPdzrArfn/gfcFMQyhvBCggS60sIBFD/M
6RUgds2wOKDndG8y89UnRhPiibF1erqb069MTTe2w+nQFAJEsN6SyNEaSUndCbsh1nAB2ETwL1+n3j9662DC7k6wEaF6QY53aNzFPySx7huPLpsP/bibfLLgrSRtffXRNM0rmIbXSIk89iWadjQKoPW5JaovwOCA0Px2UNWCYjnsup/0XfcsZqO+gxQzd1NatNSYE82
4S0pUHoS37gKKQqKdz/rdI3XdEdIQz3nMSENaU8LA1UmUjUNfmebCaJklKDMsm/+UF3PVPNeGVw7zhyM1B2Qx66MmoHFbSifRVVqVf7vlsURtCnOZ/qViZeswnHLNOW176TlhbX0scIc4ROocBmDnppUflPo/Gj4kSO4zoVHk2P2YjuqVaxElCq1/BBGqZAel74VAMP
SQwu4yxXkWWm4dRdE/Yw3TtbNMdGAlp6PyeWMIKEMcf85kavpjVT8MXNMDM6LBJpftbQ+izPit/48OaQU0ZVE6LpLK1tvxDyCHj
right=192.168.88.2
rightprotoport=gre
rightrsasigkey=0sAwEAAdZkTtxI8voB7dzi12Vm6S/WCQj/Rx0KvGUQSvnsH4fV7LlZpgss/0IVteZ0QUzUcCGu7TrBnLNPfHiHH5e4u+BSUMXRBtkqiFGZv1NnQ8eIVxj5V1UDOfpfoNyEl4Az7X0pwYuDzpS8A6GiAMCwm30VeXrU7bluS9Zbo
b7A2hycBPiTTVVyzh4xRtm1bzHD8mIm/zCUpiE6WXLyaEkTRT/+R93WwUPHa7FWBaom5i+Dj50gKa+67Bn/2qqC5FOSlI+QSfJKd0DKOb+kSZNgr0bQaZbHE8MP8Vkt56W/bMDjZa7WGznQEVTsJVPGXTuH6PqFl2SqHpR7DtZjyC+8REU3YxHWC1NoZmZMttW6P/FV
hQgko9PfVVzfmIj1+xwkDEky7dK40qSmgORnNsqn6fs9NFRywTqMImupf8XOK8HWz4jR3UI2coILXsQMgFV27YzXjFMQXfePdckWrLBORkUt82l69dWjAflyKdqDg/kRYQ6GtWQmjsgM+vHuqAiQ+UEx3WZjdPqCKm+92WmKbIpAWpXA3VXXNnZ8EnkQnpZm5LNYzPr
Cq52f8F63I69iLQQXgdaSOkZcl8U=
这两个sigkey的部分是不是换行了?leftrsasigkey的这部分我这里看到的是分成了四行了,应该是一行的。不知道是粘贴到评论的时候换行了还是配置文件就是错误的换行了。
您好,十分感谢您的回复。我检查过,没有分行。我有几个疑惑:
1.A设备的leftrsasigkey是否就是B设备的rightrsasigkey?反之亦然?
2.config setup
protostack=netkey #这两行是否需要在ipsec.conf中写上?
3.支持psk吗?是否要配置IKE?
十分感谢您的解答,如果方便我们可以加联系方式沟通下:qq:119713621,微信:13794413554.可有偿解答,再次感谢。
是的,对于A设备来说left是自己,right的B,对于B来说,B的right也就是A设备的left。
另外一点是,配置文件里面除了conn,version,config这几个指令之外,其他的诸如rightrsasigkey这些是以tab开头缩进的,不知道用空格缩进会不会是导致这个的原因。
不愧是师傅
花花棒!