使用libreswan搭建IPSec Site to Site 站点到站点云上配置

暗香疏影 创作者

我们知道在Linux可以通过libreswan或者strongswan来配置站点到站点的IPSec 专用网络。
在云上配置会稍微不一样,因为我们云上是弹性IP。下面我以Rocky Linux为例使用libreswan 4.12版本演示配置
(libreswan 5开始去除了ipsec auto, ipsec verify等工具。)

我们先展示大致的拓扑:
IPSEC-Site-to-Site
站点A 10.0.1.0/24;站点B 172.16.2.0/24
IPsec IP A1: 10.0.1.101
IPsec IP B1: 172.16.2.101
其他机器IP A2: 10.0.1.102
其他机器IP B2: 172.16.2.102

红帽 - 配置站点到站点的 VPN

安装libreswan

Setup ipsec vpn server with libreswan
Setup ipsec site to site server with libreswan 2

如果使用Debian系列,除了需要wget下载获取最新版,tar -zxvf解压后还额外需要apt install其他依赖组件,然后make all, make install源码编译。可以参考解压后文件夹内的cat INSTALL的操作说明。
其中Debian系列除去安装说明中的依赖,还需要额外安装certutil,也就是apt-get install libnss3-tools才可以成功初始化NSS数据库。
如果make all有报错就看情况apt/dnf install。提示:如果是RHEL系列要确保有EPEL源。
详情请参考:
libreswan 4.12 - How To Install Libreswan on Ubuntu 22.04|20.04
或参考GitHub libreswan 中Readme说明。

实际上,无论是使用strongswan还是libreswan在ubuntu的操作都稍微复杂。可能直接使用GitHub中一键设置IPsec VPN 然后改配置更快。(不过他直接安装最新版,是版本5的,可能用的不习惯)

1
dnf install libreswan -y

初始化NSS数据库

1
ipsec initnss

启用ipsec

1
systemctl enable ipsec

系统及防火墙配置

系统配置 IP转发及禁用重定向

编辑/etc/sysctl.conf是系统内核层面设置IP转发,实际上应该也可以通过防火墙配置实现。
确保IP Forwarding为1

1
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

查看配置

1
cat /etc/sysctl.d/50-libreswan.conf

结果应如下:

1
2
3
4
5
6
7
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.rp_filter = 0

配置立刻生效有两种方式,一种是sysctl -p,但是这个方式是只加载/etc/sysctl.conf的。
另一种方式是同时尝试加载/etc/sysctl.d/下的文件:

1
sysctl --system

防火墙配置

在云上,确保安全组端口UDP 500和UDP 4500都在开放状态。
我们需要这些IP协议是允许的(不是端口):ESP Protocol (IP Protocol 50)和AH Protocol (IP Protocol 51)。

因为我们还需要配置IP masquerading(IP地址伪装),一种是使用iptables,也就是先禁用firewalld然后安装iptables。实际上现在的iptables也是使用nf_tables API来实现类似过时iptables的命令及效果。另一种更快速的方式就是直接使用firewalld。
首先我们先确保firewalld全部端口开放,然后再启用IP地址伪装。

我们需要网段内全部机器都开启firewalld并启用IP地址伪装。
Firewalld RedHat Zone概念
firewalld默认是使用Public Zone, 这个域默认是当你未设置开启端口时则拒绝。而trusted Zone则是全部默认开启。所以我们先切换为这个Zone。

如果使用Debian/Ubuntu系列,默认是ufw防火墙。他配置IP masquerading还是有点困难的。但是可以通过禁用ufw然后安装firewalld来实现。

1
systemctl enable firewalld.service --now
1
2
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
1
firewall-cmd --set-default-zone trusted
1
2
3
# 如果选择trusted的话,本身其实完全开放的,是不需要以下两条命令的。
firewall-cmd --zone=public --permanent --add-port=1-65535/tcp
firewall-cmd --zone=public --permanent --add-port=1-65535/udp

如果在内核没有配置IP转发,你可以通过防火墙配置实现:

1
firewall-cmd --add-forward --permanent

添加IP地址伪装:

1
firewall-cmd --add-masquerade --permanent
1
firewall-cmd --reload
1
firewall-cmd --list-all

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
trusted (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: eth0
sources:
services:
ports:
protocols:
forward: yes
masquerade: yes
forward-ports:
source-ports:
icmp-blocks:
rich rules:

ipsec.conf配置信息

leftid和rightid不能是内网ip, 所以配置为名字。
因为是云上,本机端配成内网ip, 然后加上leftnexthop=%defaultroute。
对端直接填写对端公网IP

ike和esp填写方式可以aes256-sha256;dh14或者aes256-sha256;modp2048

DH Group参考:

1
2
3
4
5
6
7
8
9
10
11
12
MODP

Diffie-Hellman Group 1 (768-bit)
Diffie-Hellman Group 2 (1024-bit)
Diffie-Hellman Group 5 (1536-bit)
Diffie-Hellman Group 14 (2048-bit)
Diffie-Hellman Group 15 (3072-bit)
ECP

Diffie-Hellman Group 19 (256-bit random)
Diffie-Hellman Group 20 (384-bit random)
Diffie-Hellman Group 21 (521-bit random)

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
conn ecs
type=tunnel

left=10.0.1.101
leftid=@ipsec-02
leftnexthop=%defaultroute
leftsubnet=10.0.1.0/24

right=x.x.x.x
#right 填写公网IP
rightid=@ipsec-01
rightsubnet=172.16.2.0/24
#rightsubnet选择对端网段

authby=secret
auto=start
dpddelay=60
dpdtimeout=300
dpdaction=restart
# mobike=no
# mobike默认是no, 这是问如果公网IP发生变化会不会自动重连。选择yes是会。
ikev2=insist
# 版本4(包含4.15)请继续使用ikev2=insist, libreswan版本5之后,请使用keyexchange=ikev2
fragmentation=yes

ike=aes256-sha256;dh14
esp=aes256-sha256;dh14
ikelifetime=86400s
salifetime=86400s

对端则刚好相反。

我们还需要配置Pre-Shared Key 预共享密钥。(在工作生产环境,PSK容易被爆破,请使用证书验证。)

1
2
3
vim /etc/ipsec.secrets

%any %any : PSK "123456password"

%any代表全部,你也可以设置为[local ip] [remote ip] : PSK “123456password”

验证

验证ipsec配置

该方法仅限于libreswan 4, libreswan 5已删除该命令。你可以通过ipsec add [connection name]来查看错误提示。

1
ipsec verify

这里列表应该为全部OK状态,不能有rp_filter ENABLED状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Verifying installed system and configuration files

Version check and ipsec on-path [OK]
Libreswan 4.12
Checking for IPsec support in kernel [OK]
NETKEY: Testing XFRM related proc values
ICMP default/send_redirects [OK]
ICMP default/accept_redirects [OK]
XFRM larval drop [OK]
Pluto ipsec.conf syntax [OK]
Checking rp_filter [OK]
Checking that pluto is running [OK]
Pluto listening for IKE on udp 500 [OK]
Pluto listening for IKE/NAT-T on udp 4500 [OK]
Pluto ipsec.secret syntax [OK]
Checking 'ip' command [OK]
Checking 'iptables' command [OK]
Checking 'prelink' command does not interfere with FIPS [OK]
Checking for obsolete ipsec.conf options [OK]

如果遇到rp_filter是enabled的话,可以根据提示的文件夹,直接echo修改为0临时绕过。(重启失效)

1
2
3
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/ip_vti0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/lo/rp_filter

重启ipsec服务

1
ipsec restart
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
# 验证ipsec连接
ipsec status

#不只是active变成1,同时IPsec SAs也需要出现连接才算成功,例如:
000 "ecs": 10.0.1.0/24===10.0.1.101[@ipsec-01]---10.0.1.253...57.23.248.32[@ipsec-02]===172.16.2.0/24; erouted; eroute owner: #3
000 "ecs": oriented; my_ip=unset; their_ip=unset; my_updown=ipsec _updown;
000 "ecs": xauth us:none, xauth them:none, my_username=[any]; their_username=[any]
000 "ecs": our auth:secret, their auth:secret, our autheap:none, their autheap:none;
000 "ecs": modecfg info: us:none, them:none, modecfg policy:push, dns:unset, domains:unset, cat:unset;
000 "ecs": sec_label:unset;
000 "ecs": ike_life: 86400s; ipsec_life: 86400s; ipsec_max_bytes: 2^63B; ipsec_max_packets: 2^63; replay_window: 128; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0;
000 "ecs": retransmit-interval: 500ms; retransmit-timeout: 60s; iketcp:no; iketcp-port:4500;
000 "ecs": initial-contact:no; cisco-unity:no; fake-strongswan:no; send-vendorid:no; send-no-esp-tfc:no;
000 "ecs": policy: IKEv2+PSK+ENCRYPT+TUNNEL+PFS+UP+IKE_FRAG_ALLOW+MOBIKE+ESN_NO+ESN_YES;
000 "ecs": v2-auth-hash-policy: none;
000 "ecs": conn_prio: 24,24; interface: eth0; metric: 0; mtu: unset; sa_prio:auto; sa_tfc:none;
000 "ecs": nflog-group: unset; mark: unset; vti-iface:unset; vti-routing:no; vti-shared:no; nic-offload:auto;
000 "ecs": our idtype: ID_FQDN; our id=@ipsec-01; their idtype: ID_FQDN; their id=@ipsec-02
000 "ecs": liveness: active; dpdaction:restart; dpddelay:60s; retransmit-timeout:60s
000 "ecs": nat-traversal: encaps:auto; keepalive:20s
000 "ecs": newest IKE SA: #2; newest IPsec SA: #3; conn serial: $1;
000 "ecs": IKE algorithms: AES_CBC_256-HMAC_SHA2_256-MODP2048
000 "ecs": IKEv2 algorithm newest: AES_CBC_256-HMAC_SHA2_256-MODP2048
000 "ecs": ESP algorithms: AES_CBC_256-HMAC_SHA2_256_128-MODP2048
000 "ecs": ESP algorithm newest: AES_CBC_256-HMAC_SHA2_256_128; pfsgroup=<Phase1>
000
000 Total IPsec connections: loaded 1, active 1
000
000 State Information: DDoS cookies not required, Accepting new IKE connections
000 IKE SAs: total(1), half-open(0), open(0), authenticated(1), anonymous(0)
000 IPsec SAs: total(1), authenticated(1), anonymous(0)
000
000 #2: "ecs":4500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 86125s; REPLACE in 86395s; newest; idle;
000 #3: "ecs":4500 STATE_V2_ESTABLISHED_CHILD_SA (established Child SA); LIVENESS in 55s; REKEY in 86125s; REPLACE in 86395s; newest; eroute owner; IKE SA #2; idle;
000 #3: "ecs" esp.f43861@57.23.248.32 esp.4dfe174@10.0.1.101 tun.0@57.23.248.32 tun.0@10.0.1.101 Traffic: ESPin=0B ESPout=0B ESPmax=2^63B

如果使用SSH Key去连接对端的话,除了要将私钥添加到 ~/.ssh/id_rsa 和设置好对端公钥外,还需要将权限降低为0400,否则默认他不会读取该文件。

1
chown 0400 ~/.ssh/id_rsa

使用站点其他机器验证:(不使用云上路由表的情况下)
我们先

1
ip route

查看一下目前IP路由的方式。

然后我们将对端的IP段添加到本机,并使用本端IPSec连接的机器作为网关。那么添加路由如下:
站点A:

1
sudo ip route add 172.16.2.0/24 via 10.0.1.101 dev eth0 metric 50

metric 50是路由的优先级,默认是100, 越低则优先级越高,可以不填写。
通过以下命令可以得知特定IP走哪个路由,例如10.0.1.101:

1
2
ip route get 10.0.1.101
ip route get 10.0.1.102

持久化静态路由

RHEL系列:
随便新建一个文件在network-scripts,并命名为01-eth0

1
sudo nano /etc/sysconfig/network-scripts/01-eth0

然后输入

1
172.16.2.0/24 via 10.0.1.101

即可。

使用站点其他机器验证的时候,请断开连接后重连进行验证。无需验证IPsec A站点和B站点,直接验证IPsec A站点其他机器和IPsec B站点其他机器。

错误排查

1
2
3
4
5
6
7
8
# 状态及日志
systemctl status ipsec

# 查看日志
journalctl -xe |grep pluto
journalctl -xe |grep ipsec
#或
journalctl -xe
1
2
3
4
# tcpdump
tcpdump -i any src 10.0.1.101 and host 172.16.2.102
tcpdump -i any src 10.0.1.101 and host not 47.100.x.x
tcpdump -n -i interface esp or udp port 500 or udp port 4500
  • 标题: 使用libreswan搭建IPSec Site to Site 站点到站点云上配置
  • 作者: 暗香疏影
  • 创建于 : 2024-10-31 17:00:00
  • 更新于 : 2024-11-03 17:46:00
  • 链接: https://blog.23ikr.com/2024/10/31/2024-10-31-IPSec-Site-to-Site-libreswan/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论