IPsec 配置备忘 Part3 - Tunnel 模式

第三篇简单介绍一下 IPsec 的 Tunnel 模式,没看过前两篇的快去看~
Part1 传送门Part2 传送门

Tunnel 模式简介

Tunnel mode header layout 前两篇中我们使用的都是 Transport 模式,但是实际使用中,更常用的是 Tunnel 模式。Transport 模式只加密四层及以上数据,而不修改 IP 头,原始的 IP 头将会原样传输。这意味着我们只能进行点对点传输,因为只有一个 IP 头,我们无法告知对方服务器我们实际要访问的地址。Tunnel 模式则是连原始的 IP 头也一起加密,然后再在前端添加一个新的 IP 头,这样服务器在收到数据包后,可以解密并读取内部的 IP 头,再转发给实际的目标服务器。

配置场景

这次的场景在 Part2 的基础上略有改动:在 HostA 与 HostB 的lo接口上分别添加fd01::1/64fd01::2/64:

hosta$ ip -6 -br addr
lo               UNKNOWN        fd01::1/64 ::1/128
eth1             UP             fd00::1/64 [--omit--]
[--omit--]

hostb$ ip -6 -br addr
lo               UNKNOWN        fd01::2/64 ::1/128
eth1             UP             fd00::2/64 [--omit--]
[--omit--]

在没有建立连接的情况下,fd00::1 和 fd00::2 可互 ping,fd01::1 和 fd01::2 不可互 ping。在建立连接后,fd00::1 和 fd00::2 可互 ping,但是不加密,fd01::1 和 fd01::2 可互 ping 且流量加密。

配置文件

配置文件也是在 Part2 的基础上改动而来,变化部分已加注释

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
# hosta
connections {
conn_hosta_hostb {
version = 2
local_addrs = fd00::1
remote_addrs = fd00::2
# 使用 NULL 加密以方便抓包观察
proposals = null-sha-modp2048
local {
id = CN=HOSTA_COMMON_NAME
auth = pubkey
}
remote {
id = %any
auth = pubkey
}
children {
child_sa {
# Traffic selector 改为 fd01::*
# 这意味着 fd00::* 不被选中,也就不会被加密
local_ts = fd01::1/128
remote_ts = fd01::2/128
# 传输模式改为 Tunnel
mode = tunnel
esp_proposals = null-sha-modp2048
}
}
}
}
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
connections {
conn_hosta_hostb {
version = 2
# 交换 local 与 remote
local_addrs = fd00::2
remote_addrs = fd00::1
proposals = null-sha-modp2048
local {
# 使用 HostB 的 id
id = CN=HOSTB_COMMON_NAME
auth = pubkey
}
remote {
id = %any
auth = pubkey
}
children {
child_sa {
# 交换 local 与 remote
local_ts = fd01::2/128
remote_ts = fd01::1/128
mode = tunnel
esp_proposals = null-sha-modp2048
}
}
}
}

链接测试

启动 strongSwan 和 Wireshark,在 HostA 上,可以 ping fd00::2 但是不能 ping fd01::2。然后用sudo swanctl -i -c child_sa建立连接,依然可以 ping fd00::2 但是数据不加密,同时能够 ping 通 fd01::2 了。抓包可以看出明显的ETHERNET-IP-ESP-IP-ICMP的包头层次,并且外层 IP 使用 fd00::* 进行数据传输,内层 IP 使用 fd01::* 的实际目的地址:

Tunnel mode packet example