上一节完成了vpp-sswan基本环境的安装部署,接下来搭建环境来验证ike协商及转发功能,下图是基本环境配置组网情况:
接下来配置VPP1和VPP2基础网络环境,在vpp配置文件strartup.conf中unix 配置项分别加入"exec /etc/vpp/ipsec1.conf"及"exec /etc/vpp/ipsec2.conf",重启vpp之后,将自动生成上面组网环境。
创建/etc/vpp/ipsec1.conf文件
代码语言:javascript复制cat << EOF > /etc/vpp/ipsec1.conf
set interface state GigabitEthernet0/6/0 up
#创建lcp接口,将接口映射到内核中去,给strongswan ike交互使用。
lcp create GigabitEthernet0/6/0 host-if eth0
set interface ip address GigabitEthernet0/6/0 192.168.100.113/24
#创建lan侧接口,用于验证ipsec转发面流量,
create tap id 100 host-ip4-addr 192.168.200.2/24 host-ip4-gw 192.168.200.1
set interface state tap100 up
set interface ip address tap100 192.168.200.1/24
EOF
这里需要注意的是lcp创建需要在接口配置ip之前,才能将接口ip地址同步配置到内核eth0接口上。这应该算是lcp功能的一个bug吧?
创建/etc/vpp/ipsec2.conf文件
代码语言:javascript复制cat << EOF > /etc/vpp/ipsec2.conf
set interface state GigabitEthernet0/6/0 up
lcp create GigabitEthernet0/6/0 host-if eth0
set interface ip address GigabitEthernet0/6/0 192.168.100.2/24
create tap id 100 host-ip4-addr 192.168.110.2/24 host-ip4-gw 192.168.110.1
set interface state tap100 up
set interface ip address tap100 192.168.110.1/24
EOF
接下来配置strongswan,分别在两个环境中创建ipsec1.conf及ipsec2.conf文件,具体文件内容如下:vpp1环境 ipsec1配置文件/etc/swanstl/conf.d/ipsec1.conf
代码语言:javascript复制cat << EOF > /etc/swanctl/conf.d/ipsec1.conf
connections {
net-net {
local_addrs = 192.168.100.113
remote_addrs = 192.168.100.2
local {
auth = psk
id = sun.strongswan.org
}
remote {
auth = psk
id = moon.strongswan.org
}
children {
net-net {
local_ts = 192.168.200.0/24
remote_ts = 192.168.110.0/24
esp_proposals = aes128-sha1-modp2048
rekey_time = 240m
}
}
version = 1
mobike = yes
encap = yes # NAT-T if needed
proposals = aes128-sha256-x25519
}
}
secrets {
ike-net-net {
id = moon.strongswan.org
secret = simplepsk
}
}
EOF
vpp2系统中 ipsec2配置文件/etc/swanstl/conf.d/ipsec2.conf
代码语言:javascript复制cat << EOF > /etc/swanctl/conf.d/ipsec2.conf
connections {
net-net {
local_addrs = 192.168.100.2
remote_addrs = 192.168.100.113
local {
auth = psk
id = moon.strongswan.org
}
remote {
auth = psk
id = sun.strongswan.org
}
children {
net-net {
local_ts = 192.168.110.0/24
remote_ts = 192.168.200.0/24
esp_proposals = aes128-sha1-modp2048
rekey_time = 240m
}
}
version = 1
mobike = yes
encap = yes # NAT-T if needed
proposals = aes128-sha256-x25519
}
}
secrets {
ike-net-net {
id = moon.strongswan.org
secret = simplepsk
}
}
EOF
配置完成之后,使用sswanctl命令加载ipsec配置,下面是在vpp1环境中操作步骤:
代码语言:javascript复制#1、动态加载ipsec配置
root@learning-vpp1:~# swanctl --load-all
loaded ike secret 'ike-net-net'
no authorities found, 0 unloaded
no pools found, 0 unloaded
loaded connection 'net-net'
successfully loaded 1 connections, 0 unloaded
#2、查询ipsec配置
root@learning-vpp1:~# swanctl -L
net-net: IKEv1, reauthentication every 14400s
local: 192.168.100.113
remote: 192.168.100.2
local pre-shared key authentication:
id: sun.strongswan.org
remote pre-shared key authentication:
id: moon.strongswan.org
net-net: TUNNEL, rekeying every 14400s
local: 192.168.200.0/24
remote: 192.168.110.0/24
接下来就是通过swanctl命令行发起ike协商,生成ike sa及ipsec sa:
代码语言:javascript复制#1、发起ike sa协商
root@learning-vpp1:~# swanctl -i -i net-net
[IKE] initiating Main Mode IKE_SA net-net[1] to 192.168.100.2
[ENC] generating ID_PROT request 0 [ SA V V V V V ]
[NET] sending packet: from 192.168.100.113[500] to 192.168.100.2[500] (180 bytes)
[NET] received packet: from 192.168.100.2[500] to 192.168.100.113[500] (160 bytes)
[ENC] parsed ID_PROT response 0 [ SA V V V V ]
[IKE] received XAuth vendor ID
[IKE] received DPD vendor ID
[IKE] received FRAGMENTATION vendor ID
[IKE] received NAT-T (RFC 3947) vendor ID
[CFG] selected proposal: IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519
[ENC] generating ID_PROT request 0 [ KE No NAT-D NAT-D ]
[NET] sending packet: from 192.168.100.113[500] to 192.168.100.2[500] (172 bytes)
[NET] received packet: from 192.168.100.2[500] to 192.168.100.113[500] (172 bytes)
[ENC] parsed ID_PROT response 0 [ KE No NAT-D NAT-D ]
[IKE] remote host is behind NAT
[ENC] generating ID_PROT request 0 [ ID HASH N(INITIAL_CONTACT) ]
[NET] sending packet: from 192.168.100.113[4500] to 192.168.100.2[4500] (124 bytes)
[NET] received packet: from 192.168.100.2[4500] to 192.168.100.113[4500] (92 bytes)
[ENC] parsed ID_PROT response 0 [ ID HASH ]
[IKE] IKE_SA net-net[1] established between 192.168.100.113[sun.strongswan.org]...192.168.100.2[moon.strongswan.org]
[IKE] scheduling rekeying in 13487s
[IKE] maximum IKE_SA lifetime 14927s
initiate completed successfully
#2、查询这里协商ike sa 并未生成ipsec sa,需要手动生成。
root@learning-vpp1:~# swanctl -l
net-net: #1, ESTABLISHED, IKEv1, 32c65d2fe4e1c557_i* a0f0f26def283ba5_r
local 'sun.strongswan.org' @ 192.168.100.113[4500]
remote 'moon.strongswan.org' @ 192.168.100.2[4500]
AES_CBC-128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519
established 42s ago, rekeying in 13445s
#3、生成ipsec sa命令
root@learning-vpp1:~# swanctl -i -c net-net
[ENC] generating QUICK_MODE request 3470917660 [ HASH SA No KE ID ID ]
[NET] sending packet: from 192.168.100.113[4500] to 192.168.100.2[4500] (460 bytes)
[NET] received packet: from 192.168.100.2[4500] to 192.168.100.113[4500] (460 bytes)
[ENC] parsed QUICK_MODE response 3470917660 [ HASH SA No KE ID ID ]
[CFG] selected proposal: ESP:AES_CBC_128/HMAC_SHA1_96/MODP_2048/NO_EXT_SEQ
[KNL] UDP encap
[KNL] UDP encap
[KNL] policy have interface 192.168.100.113
[KNL] firstly created, spd for GigabitEthernet0/6/0 found sw_if_index is 1
[KNL] policy FWD interface
[KNL] policy have interface 192.168.100.113
[IKE] CHILD_SA net-net{1} established with SPIs c0173345_i cba88dca_o and TS 192.168.200.0/24 === 192.168.110.0/24
initiate completed successfully
#4、再次查询ipsec sa创建成功。
root@learning-vpp1:~# swanctl -l
net-net: #1, ESTABLISHED, IKEv1, 32c65d2fe4e1c557_i* a0f0f26def283ba5_r
local 'sun.strongswan.org' @ 192.168.100.113[4500]
remote 'moon.strongswan.org' @ 192.168.100.2[4500]
AES_CBC-128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519
established 152s ago, rekeying in 13335s
net-net: #1, reqid 1, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_2048
installed 12s ago, rekeying in 13256s, expires in 15828s
in c0173345, 0 bytes, 0 packets
out cba88dca, 0 bytes, 0 packets
local 192.168.200.0/24
remote 192.168.110.0/24
接下来先了解一下ipsec相关的术语,再vpp中查询sad及spd信息
代码语言:javascript复制#1、查询sa 安全关联信息,用户
vpp# show ipsec sa
[0] sa 1 (0x1) spi 3222745925 (0xc0173345) protocol:esp flags:[anti-replay tunnel udp-encap inbound ]
[1] sa 2 (0x2) spi 3416821194 (0xcba88dca) protocol:esp flags:[anti-replay tunnel udp-encap ]
##2、查询spd 安全策略数据库信息。
vpp# show ipsec spd
spd 1
ip4-outbound:
[7] priority 2883 action bypass type ip4-outbound protocol UDP
local addr range 0.0.0.0 - 255.255.255.255 port range 4500 - 4500
remote addr range 0.0.0.0 - 255.255.255.255 port range 4500 - 4500
packets 1 bytes 108
[5] priority 2883 action bypass type ip4-outbound protocol UDP
local addr range 0.0.0.0 - 255.255.255.255 port range 500 - 500
remote addr range 0.0.0.0 - 255.255.255.255 port range 500 - 500
packets 0 bytes 0
[3] priority 2883 action bypass type ip4-outbound protocol IPSEC_AH
local addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
remote addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
packets 0 bytes 0
[1] priority 2883 action bypass type ip4-outbound protocol IPSEC_ESP
local addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
remote addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
packets 0 bytes 0
[9] priority 2882 action protect type ip4-outbound protocol any sa 2
local addr range 192.168.200.0 - 192.168.200.255 port range 0 - 65535
remote addr range 192.168.110.0 - 192.168.110.255 port range 0 - 65535
packets 0 bytes 0
ip6-outbound:
ip4-inbound-protect:
[8] priority 2882 action protect type ip4-inbound-protect protocol any sa 1
local addr range 192.168.200.0 - 192.168.200.255 port range 0 - 65535
remote addr range 192.168.110.0 - 192.168.110.255 port range 0 - 65535
packets 0 bytes 0
ip6-inbound-protect:
ip4-inbound-bypass:
[6] priority 2883 action bypass type ip4-inbound-bypass protocol UDP
local addr range 0.0.0.0 - 255.255.255.255 port range 4500 - 4500
remote addr range 0.0.0.0 - 255.255.255.255 port range 4500 - 4500
packets 0 bytes 0
[4] priority 2883 action bypass type ip4-inbound-bypass protocol UDP
local addr range 0.0.0.0 - 255.255.255.255 port range 500 - 500
remote addr range 0.0.0.0 - 255.255.255.255 port range 500 - 500
packets 0 bytes 0
[2] priority 2883 action bypass type ip4-inbound-bypass protocol IPSEC_AH
local addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
remote addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
packets 0 bytes 0
[0] priority 2883 action bypass type ip4-inbound-bypass protocol IPSEC_ESP
local addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
remote addr range 0.0.0.0 - 255.255.255.255 port range 0 - 65535
packets 0 bytes 0
ip6-inbound-bypass:
ip4-inbound-discard:
ip6-inbound-discard:
接下来打流验证一下ipsec隧道是否正常通信,需要在vpp1和vpp2系统中分别配置去往两端的路由。
代码语言:javascript复制#vpp1 系统上配置192.168.110.0/24路由引入到vpp中。
ip route add 192.168.110.0/24 via 192.168.200.1 dev tap0
#vpp2系统上配置192.168.200.0/24路由引入到vpp中。
ip route add 192.168.200.0/24 via 192.168.110.1 dev tap0
在vpp1上面ping对端tap100接口IP地址192.168.110.2可以ping通。
代码语言:javascript复制root@learning-vpp1:~# ping 192.168.110.2 -I 192.168.200.2
PING 192.168.110.2 (192.168.110.2) from 192.168.200.2 : 56(84) bytes of data.
64 bytes from 192.168.110.2: icmp_seq=1 ttl=62 time=0.917 ms
64 bytes from 192.168.110.2: icmp_seq=2 ttl=62 time=0.355 ms
64 bytes from 192.168.110.2: icmp_seq=3 ttl=62 time=0.350 ms
64 bytes from 192.168.110.2: icmp_seq=4 ttl=62 time=0.451 ms
^C
--- 192.168.110.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3052ms
rtt min/avg/max/mdev = 0.350/0.518/0.917/0.233 ms
下面是在vpp1上抓取ipsec加密及解密trace流程如下:
代码语言:javascript复制#1、ping request报文trace流程图
13:52:32:110365: virtio-input
virtio: hw_if_index 3 next-index 4 vring 0 len 98
hdr: flags 0x00 gso_type 0x00 hdr_len 0 gso_size 0 csum_start 0 csum_offset 0 num_buffers 1
13:52:32:110366: ethernet-input
frame: flags 0x1, hw-if-index 3, sw-if-index 3
IP4: ca:b9:d8:0b:d2:2a -> 02:fe:53:3e:6d:0d
13:52:32:110368: ip4-input
ICMP: 192.168.200.2 -> 192.168.110.2
tos 0x00, ttl 64, length 84, checksum 0x5c30 dscp CS0 ecn NON_ECN
fragment id 0x2723, flags DONT_FRAGMENT
ICMP echo_request checksum 0xf378 id 6
13:52:32:110369: ip4-lookup
fib 0 dpo-idx 7 flow hash: 0x00000000
ICMP: 192.168.200.2 -> 192.168.110.2
tos 0x00, ttl 64, length 84, checksum 0x5c30 dscp CS0 ecn NON_ECN
fragment id 0x2723, flags DONT_FRAGMENT
ICMP echo_request checksum 0xf378 id 6
13:52:32:110370: ip4-rewrite
tx_sw_if_index 1 dpo-idx 7 : ipv4 via 192.168.100.2 GigabitEthernet0/6/0: mtu:9000 next:5 flags:[features ] 525400e31ca652540052388b0800 flow hash: 0x00000000
00000000: 525400e31ca652540052388b080045000054272340003f015d30c0a8c802c0a8
00000020: 6e020800f3780006003f22966c6500000000aa730c00000000001011
13:52:32:110370: ipsec4-output-feature
spd 1 policy 15
13:52:32:110371: esp4-encrypt
esp: sa-index 7 spi 3390304942 (0xca13f2ae) seq 63 sa-seq-hi 0 crypto aes-cbc-128 integrity sha1-96 udp-encap-enabled
13:52:32:110376: ip4-load-balance
fib 1 dpo-idx 7 flow hash: 0x00000000
UDP: 192.168.100.113 -> 192.168.100.2
tos 0x00, ttl 255, length 160, checksum 0x7188 dscp CS0 ecn NON_ECN
fragment id 0x0000
UDP: 4500 -> 4500
length 140, checksum 0x0000
13:52:32:110377: ip4-rewrite
tx_sw_if_index 1 dpo-idx 7 : ipv4 via 192.168.100.2 GigabitEthernet0/6/0: mtu:9000 next:5 flags:[features ] 525400e31ca652540052388b0800 flow hash: 0x00000000
00000000: 525400e31ca652540052388b0800450000a000000000ff117188c0a86471c0a8
00000020: 640211941194008c0000ca13f2ae0000003fee6baf19a9526939e558
13:52:32:110378: ipsec4-output-feature
spd 1 policy 7
13:52:32:110378: GigabitEthernet0/6/0-output
GigabitEthernet0/6/0 flags 0x02180001
IP4: 52:54:00:52:38:8b -> 52:54:00:e3:1c:a6
UDP: 192.168.100.113 -> 192.168.100.2
tos 0x00, ttl 255, length 160, checksum 0x7188 dscp CS0 ecn NON_ECN
fragment id 0x0000
UDP: 4500 -> 4500
length 140, checksum 0x0000
13:52:32:110379: GigabitEthernet0/6/0-tx
GigabitEthernet0/6/0 tx queue 0
buffer 0x9708b: current data -52, length 174, buffer-pool 0, ref-count 1, trace handle 0x6
local l2-hdr-offset 0 l3-hdr-offset 14
PKT MBUF: port 65535, nb_segs 1, pkt_len 174
buf_len 2176, data_len 174, ol_flags 0x0, data_off 76, phys_addr 0xa09c2340
packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
rss 0x0 fdir.hi 0x0 fdir.lo 0x0
IP4: 52:54:00:52:38:8b -> 52:54:00:e3:1c:a6
UDP: 192.168.100.113 -> 192.168.100.2
tos 0x00, ttl 255, length 160, checksum 0x7188 dscp CS0 ecn NON_ECN
fragment id 0x0000
UDP: 4500 -> 4500
length 140, checksum 0x0000
#2、ping reply报文trace流程
13:52:32:110575: dpdk-input
GigabitEthernet0/6/0 rx queue 0
buffer 0x9c8c0: current data 0, length 174, buffer-pool 0, ref-count 1, trace handle 0x7
ext-hdr-valid
PKT MBUF: port 0, nb_segs 1, pkt_len 174
buf_len 2176, data_len 174, ol_flags 0x0, data_off 128, phys_addr 0xa0b23080
packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
rss 0x0 fdir.hi 0x0 fdir.lo 0x0
IP4: 52:54:00:e3:1c:a6 -> 52:54:00:52:38:8b
UDP: 192.168.100.2 -> 192.168.100.113
tos 0x00, ttl 255, length 160, checksum 0x7188 dscp CS0 ecn NON_ECN
fragment id 0x0000
UDP: 4500 -> 4500
length 140, checksum 0x0000
13:52:32:110588: ethernet-input
frame: flags 0x1, hw-if-index 1, sw-if-index 1
IP4: 52:54:00:e3:1c:a6 -> 52:54:00:52:38:8b
13:52:32:110589: ip4-input
UDP: 192.168.100.2 -> 192.168.100.113
tos 0x00, ttl 255, length 160, checksum 0x7188 dscp CS0 ecn NON_ECN
fragment id 0x0000
UDP: 4500 -> 4500
length 140, checksum 0x0000
13:52:32:110589: ipsec4-input-feature
UDP: sa_id 7 type: 0 spd 1 policy 14 spi 3290334885 (0xc41e86a5) seq 63
13:52:32:110590: esp4-decrypt
esp: crypto aes-cbc-128 integrity sha1-96 pkt-seq 63 sa-seq 63 sa-seq-hi 0 pkt-seq-hi 0
13:52:32:110595: ip4-input-no-checksum
ICMP: 192.168.110.2 -> 192.168.200.2
tos 0x00, ttl 63, length 84, checksum 0x38e0 dscp CS0 ecn NON_ECN
fragment id 0x8b73
ICMP echo_reply checksum 0xfb78 id 6
13:52:32:110596: ip4-lookup
fib 0 dpo-idx 6 flow hash: 0x00000000
ICMP: 192.168.110.2 -> 192.168.200.2
tos 0x00, ttl 63, length 84, checksum 0x38e0 dscp CS0 ecn NON_ECN
fragment id 0x8b73
ICMP echo_reply checksum 0xfb78 id 6
13:52:32:110597: ip4-rewrite
tx_sw_if_index 3 dpo-idx 6 : ipv4 via 192.168.200.2 tap100: mtu:9000 next:6 flags:[] cab9d80bd22a02fe533e6d0d0800 flow hash: 0x00000000
00000000: cab9d80bd22a02fe533e6d0d0800450000548b7300003e0139e0c0a86e02c0a8
00000020: c8020000fb780006003f22966c6500000000aa730c00000000001011
13:52:32:110597: tap100-output
tap100 flags 0x01180009
IP4: 02:fe:53:3e:6d:0d -> ca:b9:d8:0b:d2:2a
ICMP: 192.168.110.2 -> 192.168.200.2
tos 0x00, ttl 62, length 84, checksum 0x39e0 dscp CS0 ecn NON_ECN
fragment id 0x8b73
ICMP echo_reply checksum 0xfb78 id 6
13:52:32:110597: tap100-tx
buffer 0x9c8c0: current data 52, length 98, buffer-pool 0, ref-count 1, trace handle 0x7
ext-hdr-valid
ip4 l2-hdr-offset 0 l3-hdr-offset 14
ipv4 hdr-sz 34 l2-hdr-offset 52 l3-hdr-offset 14 l4-hdr-offset 34 l4-hdr-sz 0
IP4: 02:fe:53:3e:6d:0d -> ca:b9:d8:0b:d2:2a
ICMP: 192.168.110.2 -> 192.168.200.2
tos 0x00, ttl 62, length 84, checksum 0x39e0 dscp CS0 ecn NON_ECN
fragment id 0x8b73
ICMP echo_reply checksum 0xfb78 id 6
至此,strongswan vpp实现ipsec策略模式转发已经打通,我也是首次接触策略模式处理逻辑,后面会详细分析一下业务处理流程。