该测试计划描述了在 cryptodev 框架内,在 Intel® 82599 10 GbE 控制器 (IXGBE) 上对 IPsec 流的对称加密处理进行内联硬件加速的验证方法。
限制:支持 AES-GCM 128 ESP 隧道/传输模式和仅身份验证模式。
参考链接:
- https://tools.ietf.org/html/rfc4301
- https://tools.ietf.org/html/rfc4302
- https://tools.ietf.org/html/rfc4303
- http://dpdk.org/doc/guides/sample_app_ug/ipsec_secgw.html
ESP:封装安全有效负载,数据包封装格式
SPI:安全参数索引
SPI 是一个任意的 32 位值,接收器使用它来识别传入数据包所绑定的 SA。
Sequence Number: 这个无符号的 32 位字段包含一个计数器值,每发送一个数据包,该值就会加一
AES:高级加密标准
GCM:伽罗瓦计数器模式
先决条件
DUT 的 2 * 10Gb 以太网端口以全双工方式直接连接到对等流量生成器的不同端口。
将两个端口绑定到 vfio-pci。modprobe vfio-pci
该套件依赖PyCryptodome,它提供经过认证的加密模式(GCM)模块依赖:cryptography(1.7.2)、pycryptodome(3.4.7)、pycryptodomex(3.4.7)、pycryptopp(0.6.0)、scapy(2.3.3 或更高版本)
在IPSEC应用程序中添加打印代码:
sed -i -e 's/if (nb_rx > 0)/if (nb_rx > 0) {/g' -e '/\/\* dequeue and process completed crypto-ops \*\//i\\t\t\t}' -e '/process_pkts(qconf, pkts, nb_rx, portid);/i\\t\t\t\tprintf("[debug]receive %llu packet in rxqueueid=%llu\\n",(unsigned long long)nb_rx, (unsigned long long)queueid);' examples/ipsec-secgw/ipsec-secgw.c
重新编译 examples/ipsec-secgw:
meson configure -Dexamples=ipsec-secgw x86_64-native-linuxapp-gcc
ninja -C x86_64-native-linuxapp-gcc
测试用例
配置文件内容如下:
#SP IPv4 rules
sp ipv4 out esp protect 1005 pri 1 dst 192.168.105.0/24 sport 0:65535 dport 0:65535
#SA rules
sa out 1005 aead_algo aes-128-gcm aead_key 2b:7e:15:16:28:ae:d2:a6:ab:f7:15:88:09:cf:4f:3d:de:ad:be:ef \
mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5 \
port_id 1 \
type inline-crypto-offload \
sa in 5 aead_algo aes-128-gcm aead_key 2b:7e:15:16:28:ae:d2:a6:ab:f7:15:88:09:cf:4f:3d:de:ad:be:ef \
mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5 \
port_id 1 \
type inline-crypto-offload \
#Routing rules
rt ipv4 dst 172.16.2.5/32 port 1
rt ipv4 dst 192.168.105.10/32 port 0
启动 ipsec-secgw 示例并确保 SP/SA/RT 规则成功加载。
检查 ipsec-secgw 是否可以检测无效的密码算法。
检查 ipsec-secgw 是否可以检测无效的身份验证算法。
检查 ipsec-secgw 是否可以检测无效的密钥格式。
IPSec加密
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 --config="(0,0,20),(1,0,21)" -f ./enc.cfg
使用 scapy 监听未受保护的端口:
sniff(iface='%s',count=1,timeout=10)
使用 scapy 将突发(32)个普通数据包(目标 ip 为 192.168.105.0)发送到受保护的端口。
检查从不受保护的端口接收到的突发 esp 数据包:
检查 esp 数据包的格式是否正确。
查看 scapy 输出上的解密数据包:
使用 Jumboframe 的 IPSec 加密
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 --config="(0,0,20),(1,0,21)" -f ./enc.cfg
使用 scapy 监听未受保护的端口
默认帧大小为 1518,向受保护端口发送突发(1000)个数据包,目标 ip(192.168.105.0)。
检查从不受保护的端口接收到的突发 esp 数据包。
检查 esp 数据包的格式是否正确。
在 scapy 输出中查看解密的数据包
向受保护端口发送突发(8192)个巨型数据包,目标 IP 为(192.168.105.0)。
检查是否无法从不受保护的端口接收突发 esp 数据包。
将巨型帧大小设置为 9000,并将端口 1 指定为非保护模式来启动它:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 -j 9000 --config="(0,0,20),(1,0,21)" -f ./enc.cfg
使用 scapy 监听未受保护的端口
向受保护端口发送突发(8192)个巨型数据包,目标 IP 为(192.168.105.0)。
检查从不受保护的端口接收到的突发巨型数据包。
检查 esp 数据包的格式是否正确。
在 scapy 输出中查看解密的数据包
向受保护端口发送突发(9000)个巨型数据包,目标 IP 为(192.168.105.0)。
检查是否无法从不受保护的端口接收突发巨型数据包。
使用 RSS 的 IPSec 加密
为不同的 IP 地址创建具有多个 SP/SA/RT 规则的配置文件。
启动 ipsec-secgw,在每个端口上启用两个队列,并将端口 1 分配为不受保护的模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 --config="(0,0,20),(0,1,20),(1,0,21),(1,1,21)" -f ./enc_rss.cfg
使用 scapy 监听未受保护的端口
向受保护端口发送具有不同目标 IP 的突发(32)数据包。
检查未受保护端口上从队列 0 和队列 1 接收的突发 esp 数据包。tcpdump -Xvvvi ens802f1
检查 esp 数据包的格式是否正确。
在 scapy 输出中查看解密的数据包
IPSec 解密
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 --config="(0,0,20),(1,0,21)" -f ./dec.cfg
向未受保护的端口发送两个 burst(32) esp 数据包。
第一个将在 IPsec 应用程序中产生错误“IPSEC_ESP:加密操作失败”,但它将设置 SA。第二个将解密并发回解密后的数据包。
检查从受保护端口接收的已解封装的突发数据包 tcpdump -Xvvvi ens802f0
使用错误密钥进行 IPSec 解密
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 --config="(0,0,20),(1,0,21)" -f ./dec.cfg
更改dec.cfg密钥与发送数据包加密密钥不一样
向未受保护的端口发送一个突发(32)esp 数据包。
IPsec 应用程序将产生错误“IPSEC_ESP:加密操作失败”,但它将设置 SA。
向未受保护的端口发送一个突发(32)esp 数据包。
检查已解封装的突发数据包无法从受保护端口接收,IPsec 应用程序将产生错误“IPSEC_ESP:加密操作失败”。
使用 Jumboframe 进行 IPSec 解密
使用两个 82599 端口启动 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 –vdev “crypto_null” –log-level 8 –socket-mem 1024,1 – -p 0xf -P -u 0x2 –config=”(0,0,20),(1,0,21)” -f ./dec.cfg
默认帧大小为 1518,向未受保护的端口发送两个突发(1000)esp 数据包。
第一个将在 IPsec 应用程序中产生错误“IPSEC_ESP:加密操作失败”,但它将设置 SA。第二个将解密并发回解密后的数据包。
检查从受保护端口接收的已解封装的突发(1000)数据包。
向未受保护的端口发送突发(8192)esp 数据包。
检查突发(8192)已解封装的数据包无法从受保护的端口接收。
将巨型帧大小设置为 9000,并将端口 1 指定为非保护模式来启动它:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 -j 9000 --config="(0,0,20),(1,0,21)" -f ./dec.cfg
向未受保护的端口发送两个突发(8192)esp 数据包。
第一个将在 IPsec 应用程序中产生错误“IPSEC_ESP:加密操作失败”,但它将设置 SA。第二个将解密并发回解密后的数据包。
检查从受保护端口接收的已解封装的突发(8192)个数据包。
向未受保护的端口发送突发(9000)esp 数据包。
检查突发(9000)已解封装的数据包无法从受保护端口接收。
使用 RSS 进行 IPSec 解密
为不同的 IP 地址创建具有多个 SA 规则的配置文件。
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1 --vdev
"crypto_null" --log-level 8 --socket-mem 1024,1 -- -p 0xf -P -u
0x2 -config="(0,0,20),(0,1,20),(1,0,21),(1,1,21)" -f ./dec_rss.cfg
向未受保护的端口发送两个具有不同 IP 的 burst(32) esp 数据包。
第一个将在 IPsec 应用程序中产生错误“IPSEC_ESP:加密操作失败”,但它将设置 SA。第二个将解密并发回解密后的数据包。
检查从受保护端口上的队列 0 和 1 接收的已解封装的突发(32)数据包。
IPSec 同时加密/解密
启动具有两个 82599 端口的 ipsec-secgw,并将端口 1 分配给非保护模式:
sudo ./x86_64-default-linuxapp-gcc/examples/dpdk-ipsec-secgw -l 20,21 -a 83:00.0 -a 83:00.1
--vdev "crypto_null" --log-level 8 --socket-mem 1024,1
-- -p 0xf -P -u 0x2 --config="(0,0,20),(1,0,21)" -f ./enc_dec.cfg
同时向受保护和不受保护的端口发送正常和 esp 数据包。
注意,在测试入站 IPSec 时,第一个将在 IPsec 应用程序中产生错误“IPSEC_ESP:无效填充”,但它将设置 SA。第二个将解密并发回解密后的数据包。
检查从不受保护和受保护的端口接收的 esp 和正常数据包。