IPsec 配置备忘 Part4 - Virtual IP

第四篇主要讲一下怎么给客户端下发内网 IP ~
Part1 传送门Part2 传送门Part3 传送门

Virtual IP (VIP)

接 Part3,有了 Tunnel 模式以后我们实际使用的 IP 地址就不用受制于机器的实际 IP 了。但是手动给每个客户端手动分配一个地址显然是不切实际的。于是我们可以使用 Virtual IP 功能自动向连入的客户端分配一个内网 IP,就像 DHCP 或者 SLAAC 那样。

场景配置

与之前完全对称的配置不同,使用 Virtual IP 时需要区分服务端和客户端。先在服务端配置将要分配的 IP,然后由客户端发起连接,服务端就会将配置好的 IP 分发出去。我使用 HostA 作为服务端,HostB 作为客户端。HostA 将会给 HostB 分配 IPv4 与 IPv6 各一个。使用的 Virtual IP 段是fd01::100-fd01::20010.10.10.100-10.10.10.150

hosta$ ip -br addr
eth1         UP             fd00::1/64 fd01::1/128 10.10.10.1/32

hostb$ ip -br addr
eth1         UP             fd00::2/64

和 Part3 相比,HostA 这里有一些与之前不同的地方,一是内部 IP 全部放在了 eth1 上(而不是 lo 上);二是内部 IP 的前缀长度都是最大值;三是增加了一个 IPv4 的内部 IP,用于和分配的 IPv4 Virtual IP 通信。同时 HostB 也不再手工分配fd01开头的内部 IP 了,将由 strongSwan 自动配置。

当连接建立后,我们应该能看到在 HostB 的 eth1 上出现两个新的,自动分配的 IP。且分配到的 IPv4 地址与 10.10.10.1 之间的通信是加密的,分配到的 IPv6 地址与 fd01::1 之间的通信是加密的。

配置文件

配置文件基于 Part3 修改而来,有变化的部分已添加注释:

hosta.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
connections {
conn_hosta_hostb {
version = 2
local_addrs = fd00::1
remote_addrs = fd00::2
proposals = null-sha-modp2048
# 指定要使用的 IP 池
pools = ip6pool,ip4pool
local {
id = CN=HOSTA_COMMON_NAME
auth = pubkey
}
remote {
id = %any
auth = pubkey
}
children {
child_sa {
# Local TS 加上新增的 IPv4 地址
local_ts = fd01::1/128,10.10.10.1/32
# Remote TS 设置为 "dynamic"
# strongSwan 会自动将其替换成分配出去的 Virtual IP
remote_ts = dynamic
mode = tunnel
esp_proposals = null-sha-modp2048
}
}
}
}

# 定义 IP 池
pools {
# IP 池的名称
ip6pool {
# 池中的 IP,也可以使用 fd01::100/120 这样的表示法
addrs = fd01::100-fd01::200
}
ip4pool {
addrs = 10.10.10.100-10.10.10.150
}
}
hostb.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
connections {
conn_hosta_hostb {
version = 2
local_addrs = fd00::2
remote_addrs = fd00::1
proposals = null-sha-modp2048
# 向服务器请求 VIP,0.0.0.0 代表任意 IPv4
# :: 代表任意 IPv6
vips = 0.0.0.0,::
local {
id = CN=HOSTB_COMMON_NAME
auth = pubkey
}
remote {
id = CN=HOSTA_COMMON_NAME
auth = pubkey
}
children {
child_sa {
# 类似 HostA 的 Remote TS,dynamic 会被自动替换
# 成从服务端接收到的 VIP
local_ts = dynamic
# 增加服务器的 IPv4 内网地址
remote_ts = fd01::1/128,10.10.10.1/32
mode = tunnel
esp_proposals = null-sha-modp2048
}
}
}
}

链接测试

与 Part3 中的对称链接不同,这次你必须从客户端发起连接,也就是从 HostB 执行如下命令:swanctl -i -c child_sa。连接建立后,你应该就能看到自动分配的 IP 了:

hostb$ ip -br addr
eth1         UP             fd00::2/64 fd01::100/128 10.10.10.100/32

此时再从 HostB 分别 ping fd00::1fd01::110.10.10.1,你应该能看到前者没有加密,而后两者的 ICMP 包被包在了fd00::1 <---> fd00::2的 IPv6-ESP 包里:

IPv4 ICMP inside IPv6 ESP