1、strongswan+vpp简介
将默认的socket-default连接替换为VPP的punt socket方式,punt socket会将ike协议报文通过VPP上送到strongswan中,strongswan也会将回应的报文通过punt socket传输回vpp,IKE的协商层面是通过strongswan完成。
ike协商完成之后,strongswan通过vpp的C语言 API向VPP下发IPSEC的配置,sa spd 路由等等,下发完成配置之后,VPP的IPSEC隧道就完成了建立。
用strongswan替换VPP自身的IKE功能,是因为VPP本身的IKE只支持IKE V2而且功能的丰富度不如strongswan完善。
已有的开源项目简介
作者matfabia
https://github.com/matfabia/strongswan/tree/vpp
作者mestery
https://github.com/mestery/strongswan
该项目是基于上面原始项目进行修改,支持VPP 的1810版本,进行了小幅度的API适配整体和上面项目相差不大。随后该项目也停止更新了,但是该项目中有一个pull request比较关键,在4500 UDP端口上支持了NAT-T IKE,增加了一些VPP新支持的加密算法例如GCM的支持。但是该pull request并没有合入到该项目,因为作者可能已经忘记这个项目了。
作者rayshi-10
https://github.com/rayshi-10/Strongswan-Vpp2001
该项目是基于第二个项目做的,而且把第二个项目中pull request合入了进来,支持了VPP后来加入的更多加密和认证算法,而且支持NAT-T IKE。然后支持了VPP v20.01版本。这个版本的代码修改量还是比较大的。因为VPP v20.01版本API和数据结构的改动是相当大的,大部分原有的IPSEC配置API都发生的变化,进行了多次重构,但是而且设置还删除了一些配置属性,导致原有的流程可以需要改动比较大才能适配。
v20.01的VPP ipv4 ipv6的配置需要显示下发两条,而以前的版本是使用any属性标志下发一条就可以了。这部分的改动需要特别关注下,该项目目测这部分可能会有BUG。可以特别关注下该项目的manage_policy函数,例如下面的部分,is_anyaddr的情况只下发了一条policy。可能会出现问题
if (src->is_anyaddr(src) && dst->is_anyaddr(dst))
{
memset(mp->entry.local_address_stop.un.ip6, 0xFF, 16);
memset(mp->entry.remote_address_stop.un.ip6, 0xFF, 16);
}
该项目基于的strongswan版本是5.7.x版本的,不是最新的release。
2、基于rayshi-10的代码和strongswan最新release5.8.3进行修改
下载源码
首先下载strongswan主线代码,切换到5.9.6分支
git clone https://github.com/strongswan/strongswan.git git checkout 5.9.6
讯享网
或者
官网下载链接(推荐)

然后下载rayshi-10 strongswan + vpp 20.01项目代码
讯享网git clone https://github.com/rayshi-10/Strongswan-Vpp2001.git
替换文件
将该项目的
src/libcharon/plugins/kernel_vpp/ src/libcharon/plugins/socket_vpp/
以上两个目录替换到strongswan 5.9.6对应目录下,
然后将该项目configure.ac目录下kernel-vpp socket-vpp相关的内存,添加到strongswan 5.9.6对应的文件里,具体包括:
ARG_ENABL_SET([kernel-vpp], [enable the VPP kernel interface.])
ARG_ENABL_SET([socket-vpp], [enable VPP socket implementation for charon])
ADD_PLUGIN([kernel-vpp], [c charon])
ADD_PLUGIN([socket-vpp], [c charon])
AM_CONDITIONAL(USE_KERNEL_VPP, test x$kernel_vpp = xtrue)
AM_CONDITIONAL(USE_SOCKET_VPP, test x$socket_vpp = xtrue)
src/libcharon/plugins/socket_vpp/Makefile
src/libcharon/plugins/kernel_vpp/Makefile
同步添加以上内容后,后续生成configure命令里才会出现以下两个选项

注意,该项目的configure.ac里面缺少下面两条配置
讯享网ADD_PLUGIN([kernel-vpp], [c charon]) ADD_PLUGIN([socket-vpp], [c charon])
ADD_PLUGIN([kernel-iph], [c charon])
ADD_PLUGIN([kernel-vpp], [c charon])
ADD_PLUGIN([kernel-pfkey], [c charon starter nm cmd])
ADD_PLUGIN([kernel-pfroute], [c charon starter nm cmd])
ADD_PLUGIN([kernel-netlink], [c charon starter nm cmd])
ADD_PLUGIN([resolve], [c charon cmd])
ADD_PLUGIN([save-keys], [c])
ADD_PLUGIN([socket-default], [c charon nm cmd])
ADD_PLUGIN([socket-dynamic], [c charon cmd])
ADD_PLUGIN([socket-win], [c charon])
ADD_PLUGIN([socket-vpp], [c charon])
ADD_PLUGIN([bypass-lan], [c charon nm cmd])
注意dnssec_status_t的修改
dnssec_status_t (src/libstrongswan/resolver/resolver_response.h)枚举变量在strongswan vpp中进行了重命名,将这个枚举中的变量全都加了DNSS前缀,可能是因为这个枚举里面的变量和VPP里面的内容重名了,我们在替换时,如果编译失败了,可能是忘记重命名该名称导致
重命名后的效果如下
enum dnssec_status_t { / * The validating resolver has a trust anchor, has a chain of * trust, and is able to verify all the signatures in the response. * [RFC4033] */ DNSS_SECURE, / * The validating resolver has a trust anchor, a chain of * trust, and, at some delegation point, signed proof of the * non-existence of a DS record. This indicates that subsequent * branches in the tree are provably insecure. A validating resolver * may have a local policy to mark parts of the domain space as * insecure. [RFC4033] */ DNSS_INSECURE, / * The validating resolver has a trust anchor and a secure * delegation indicating that subsidiary data is signed, but the * response fails to validate for some reason: missing signatures, * expired signatures, signatures with unsupported algorithms, data * missing that the relevant NSEC RR says should be present, and so * forth. [RFC4033] */ DNSS_BOGUS, / * There is no trust anchor that would indicate that a * specific portion of the tree is secure. This is the default * operation mode. [RFC4033] */ DNSS_INDETERMINATE, };
修改PUNT read socket path
在src/libcharon/plugins/socket_vpp/socket_vpp_socket.c中该项目中vpp的punt read path是/tmp目录,该地址可以自行设定,例如我将该地址进行了下面的修改,和VPP其他unix socket放置在同一目录
讯享网#define READ_PATH "/var/run/vpp/ike-punt-read.sock"
3、编译项目
下载依赖
系统是Ubuntu 20.04,使用下面的命令下载编译中的依赖项
Ubuntu更换国内源方法参考
apt install gperf apt install python3 apt install gmp10 apt install libgmp-dev
编译vpp
讯享网git clone https://github.com/FDio/vpp.git git checkout stable/2001 make install-dep make install-ext-deps #时间较长 make build-release
采用源码编译安装方式安装,编译完位置在vpp/build-root/install-vpp-native/vpp
注意:编译过程可能会遇到以下问题
1、launchpadlib 1.10.13 requires testresources, which is not installed
2、Cannot import name find_packages
安装VPP到系统中
cp build-root/install-vpp-native/vpp/include/* /usr/include/ -r cp build-root/install-vpp-native/vpp/lib/* /lib64/ -r ----centos cp build-root/install-vpp-native/vpp/lib/* /lib/ -r ----ubuntu cp build-root/install-vpp-native/vpp/lib/vpp_plugins /lib/ -r cp build-root/install-vpp-native/vpp/bin/vpp /usr/bin/ cp build-root/install-vpp-native/vpp/bin/vppctl /usr/bin/
讯享网cp build-root/install-vpp_debug-native/vpp/include/* /usr/include/ -r cp build-root/install-vpp_debug-native/vpp/lib/* /lib64/ -r ---centos cp build-root/install-vpp_debug-native/vpp/lib/* /lib/ -r ---ubuntu cp build-root/install-vpp_debug-native/vpp/lib/vpp_plugins /lib/ -r cp build-root/install-vpp_debug-native/vpp/bin/vpp /usr/bin/ cp build-root/install-vpp_debug-native/vpp/bin/vppctl /usr/bin/
编译strongswan
预处理
configure.ac(与项目https://github.com/rayshi-10/Strongswan-Vpp2001.git对应文件对比)
合适的位置添加以下内容:
ARG_ENABL_SET([kernel-vpp], [enable the VPP kernel interface.]) ARG_ENABL_SET([socket-vpp], [enable VPP socket implementation for charon]) ADD_PLUGIN([kernel-vpp], [c charon]) ADD_PLUGIN([socket-vpp], [c charon]) AM_CONDITIONAL(USE_KERNEL_VPP, test x$kernel_vpp = xtrue) AM_CONDITIONAL(USE_SOCKET_VPP, test x$socket_vpp = xtrue) src/libcharon/plugins/socket_vpp/Makefile src/libcharon/plugins/kernel_vpp/Makefile
执行编译
./autogen.sh
./configure --enable-socket-vpp --enable-kernel-vpp --enable-libipsec --enable-openssl --enable-charon --enable-systemd --enable-swanctl --enable-vici
make
注意:没有autogen.sh的话,从别的版本拷贝一个,configure必须重新生成
安装strongswan到系统中
讯享网make install
安装好的默认目录是/usr/local/,主要文件和目录如下所示
/usr/local/bin/pki /usr/local/sbin/ipsec /usr/local/sbin/swanctl /usr/local/sbin/etc/
4、运行测试
测试拓扑
目前我测试了strongswan官方文档中拓扑的Roadwarrior Case和Site-to-Site Case,这两种拓扑是移动客户端场景和网关-网关的部署场景。 这里要注意,strongswan的配置方式可能发生了比较大的变化,之前是通过配置ipsec目录下的内容去实现的,而最新的版本一般是通过配置swanctl相关的内容去完成。
注意:官方项目中的README里面的内容是有些错误的,不要去看那部分的内容,例如Roadwarrior Case中网关和客户端的配置中都写的是:
讯享网local_ts = 10.1.0.0/16
而显然配置应该是服务器是local_ts = 10.1.0.0/16而客户端应该是remote_ts = 10.1.0.0/16
这里应该去参考https://www.strongswan.org/testresults.html该页面中swanctl的部分,这个页面是测试例和执行的情况,是随着版本更新的,而且每发布一个版本会自动跑一遍这些部署场景,这里面有非常详细的每个阶段swanctl的配置和状态,学习新的部署场景和配置应该从这个页面去学习。
搭建方式
VPP启动前dpdk配置
。。。
vpp启动配置
startup.conf(一般放置于目录/etc/vpp/)
statseg { default per-node-counters on } socksvr { socket-name /var/run/vpp/vpp-api.sock } unix { #交互模式 interactive cli-listen /run/vpp/cli.sock #使用telnet 127.0.0.1 5002访问 #cli-listen 127.0.0.1:5002 log /tmp/vpe.log nodaemon coredump-size 1M } punt { socket /var/run/vpp/ike-punt-write.sock } api-trace { on } heapsize 4G buffers { buffers-per-numa 40000 } plugins { plugin dpdk_plugin.so { enable } } cpu { # Dynamic Create Option main-core 0 corelist-workers 1-7 } dpdk { log-level debug huge-dir /dev/hugepages no-tx-checksum-offload dev 0000:00:06.0 { name G1/1 } dev 0000:00:07.0 { name G1/2 } }
上面的配置CPU部分需要根据自己的环境编写,绑定工作线程和主线程到某些CPU核。dpdk部分的接口PCI号,也需要根据实际的情况填写,上面的配置ipsec加解密使用了openssl的能力,没有使用dpdk的加解密套件,使用dpdk加解密套件请看最后一节。
上面配置中比较重要的一点是punt这一部分,该配置必须填写。
strongswan使用到了两个punt socket:

- 其中一个是VPP startup.conf中指定,是write socket,strongswan写报文使用该unix socket。
- 另一个是punt读接口,该unix socket在strongswan的socket-vpp插件中启动时,动态向vpp注册,接口的路径在代码中写死。
上面已经说过这个问题了。
dev 0000:00:06.0 { name G1/1 }中00:06:0通过lspci查询网卡信息获得。
G1/1仅是别名,后续vppctl指令设置时使用。dev 0000:00:07.0同理。
需要额外注意的是,corelist-workers的值需要视情况而定,可以适当增加虚拟机的核数或减少该值。
vpp启动
cd vpp/build-root/install-vpp-native/vpp
./bin/vpp -c /etc/vpp/startup.conf &
vpp运行配置
VPP成功启动后,需要配置接口的IP信息,这一部分信息就根据上面提到的测试例页面中的拓扑来配置就可以。
下面是我的环境中site-to-site中配置CLI命令
moon的配置
讯享网vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.1/24 vppctl set int ip addr G1/2 10.1.0.1/16
sun的配置
vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.2/24 vppctl set int ip addr G1/2 10.2.0.1/16
制作证书
使用证书认证的话,就需要自己制作证书了,这一部分是比较复杂的,因为strongswan的证书验证比较严格,而且根据网上教程制作出来的证书大多都是认证不通过的。我这里编写了一个脚本去制作这两个场景的证书。使用了strongswan的pki这个工具,在制作证书之前,需要先下载一个程序,如果不下载该程序的话,可能会生成密钥非常慢,长达几十分钟。
讯享网apt install haveged systemctl start haveged
证书的制作要点就是配置中的id和证书中的CN以及SAN选项要一致
Roadwarrior Case
10.1.0.0/16 -- | 192.168.0.1 | === | x.x.x.x | moon-net moon carol
该脚本是跑在Roadwarrior Case中的移动客户端carol上面的,在此场景中我们carol的管理IP是192.168.199.102,moon的管理IP是192.168.199.101,证书生成之后自动拷贝的,也可以手动拷贝到对应的目录
讯享网#!/bin/bash INSTALLDIR="/usr/local" CONFIGPATH="$INSTALLDIR/etc" SERVER_HOST=moon.strongswan.org SERVER_IP=192.168.0.1 CLIENT_HOST= CLIENT_IP=192.168.0.100 # remove old files rm -rf cert > /dev/null 2>&1 mkdir cert && cd cert # create CA certificate echo -e "\033[32mCreate CA certificate...\033[0m" pki --gen --outform pem > ca.key.pem pki --self --in ca.key.pem --dn "C=CN, O=StrongSwan, CN=StrongSwan CA" --ca --outform pem > ca.cert.pem # create server certificate echo -e "\033[32mCreate server certificate...\033[0m" pki --gen --outform pem > server.key.pem pki --pub --in server.key.pem | ipsec pki --issue --cacert ca.cert.pem \ --cakey ca.key.pem --dn "C=CN, O=StrongSwan, CN=$SERVER_HOST" \ --san "$SERVER_HOST" --san="$SERVER_IP" --flag serverAuth --flag ikeIntermediate \ --outform pem > server.cert.pem # create client certificate echo -e "\033[32mCreate client certificate...\033[0m" pki --gen --outform pem > client.key.pem pki --pub --in client.key.pem | ipsec pki --issue --cacert ca.cert.pem \ --cakey ca.key.pem --dn "C=CN, O=StrongSwan, CN=$CLIENT_HOST" \ --san "$CLIENT_HOST" --san="$CLIENT_IP" \ --outform pem > client.cert.pem echo -e "\033[32mInstall certificate...\033[0m" cp ca.cert.pem $CONFIGPATH/swanctl/x509ca/strongswanCert.pem cp client.cert.pem $CONFIGPATH/swanctl/x509/carolCert.pem cp client.key.pem $CONFIGPATH/swanctl/private/carolKey.pem sshpass -pnsfocus scp ca.cert.pem 192.168.199.101:$CONFIGPATH/swanctl/x509ca/strongswanCert.pem sshpass -pnsfocus scp server.cert.pem 192.168.199.101:$CONFIGPATH/swanctl/x509/moonCert.pem sshpass -pnsfocus scp server.key.pem 192.168.199.101:$CONFIGPATH/swanctl/private/moonKey.pem
说明:
这里
–self表示自签证书,–in是输入的私钥,–dn是判别名,–ca表示生成 CA,其它同上。
- C 表示国家名,同样还有 ST 州/省名,L 地区名,STREET(全大写) 街道
- O 表示组织名
- CN 为通用名
sshpass使用说明
site-to-site case
10.1.0.0/16 -- | 192.168.0.1 | === | 192.168.0.2 | -- 10.2.0.0/16 moon-net moon sun sun-net
讯享网#!/bin/bash INSTALLDIR="/usr/local" CONFIGPATH="$INSTALLDIR/etc" SERVER_HOST=moon.strongswan.org SERVER_IP=192.168.0.1 CLIENT_HOST=sun.strongswan.org CLIENT_IP=192.168.0.2 # remove old files rm -rf cert > /dev/null 2>&1 mkdir cert && cd cert # create CA certificate echo -e "\033[32mCreate CA certificate...\033[0m" pki --gen --outform pem > ca.key.pem pki --self --in ca.key.pem --dn "C=CN, O=StrongSwan, CN=StrongSwan CA" --ca --outform pem > ca.cert.pem # create server certificate echo -e "\033[32mCreate server certificate...\033[0m" pki --gen --outform pem > server.key.pem pki --pub --in server.key.pem | ipsec pki --issue --cacert ca.cert.pem \ --cakey ca.key.pem --dn "C=CN, O=StrongSwan, CN=$SERVER_HOST" \ --san "$SERVER_HOST" --san="$SERVER_IP" --flag serverAuth --flag ikeIntermediate \ --outform pem > server.cert.pem # create client certificate echo -e "\033[32mCreate client certificate...\033[0m" pki --gen --outform pem > client.key.pem pki --pub --in client.key.pem | ipsec pki --issue --cacert ca.cert.pem \ --cakey ca.key.pem --dn "C=CN, O=StrongSwan, CN=$CLIENT_HOST" \ --san "$CLIENT_HOST" --san="CLIENT_IP" \ --outform pem > client.cert.pem echo -e "\033[32mInstall certificate...\033[0m" cp ca.cert.pem $CONFIGPATH/swanctl/x509ca/strongswanCert.pem cp client.cert.pem $CONFIGPATH/swanctl/x509/carolCert.pem cp client.key.pem $CONFIGPATH/swanctl/private/carolKey.pem sshpass -pnsfocus scp ca.cert.pem 192.168.199.101:$CONFIGPATH/swanctl/x509ca/strongswanCert.pem sshpass -pnsfocus scp server.cert.pem 192.168.199.101:$CONFIGPATH/swanctl/x509/moonCert.pem sshpass -pnsfocus scp server.key.pem 192.168.199.101:$CONFIGPATH/swanctl/private/moonKey.pem
配置strongswan
开启vpp插件
在进行配置之前,需要先启用我们的kernel-vpp和socket-vpp插件。首先我们将
/usr/local/etc/strongswan.d/charon/kernel-netlink.conf /usr/local/etc/strongswan.d/charon/socket-default.conf
两个默认插件的内容修改一下将默认加载变成不加载load = no
然后将我们新增的两个插件加载状态变为yes
讯享网/usr/local/etc/strongswan.d/charon/socket-vpp.conf /usr/local/etc/strongswan.d/charon/kernel-vpp.conf
修改为load = yes
strongswan新版本,配置的内容主要是/usr/local/etc/swanctl/swanctl.conf文件,具体的场景和配置可以参考上面给出的官方测试例的配置。
Roadwarrior Case配置
10.1.0.0/16 -- | 192.168.0.1 | === | x.x.x.x | moon-net moon carol
网关 moon端配置
证书位置:
讯享网/usr/local/etc/swanctl/x509ca/strongswanCert.pem /usr/local/etc/swanctl/x509/moonCert.pem /usr/local/etc/swanctl/private/moonKey.pem
swanctl配置:
/usr/local/etc/swanctl/swanctl.conf: connections { rw { local { auth = pubkey certs = moonCert.pem id = moon.strongswan.org } remote { auth = pubkey } children { net-net { local_ts = 10.1.0.0/16 } } version = 2 proposals = aes128-sha256-curve25519 } }
vpp 运行配置:
讯享网vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.1/24 vppctl set int ip addr G1/2 10.1.0.1/16
移动端carol配置
证书位置:
/usr/local/etc/swanctl/x509ca/strongswanCert.pem /usr/local/etc/swanctl/x509/carolCert.pem /usr/local/etc/swanctl/private/carolKey.pem
swanctl配置:
讯享网/usr/local/etc/swanctl/swanctl.conf: connections { home { remote_addrs = 192.168.0.1 local_addrs = 192.168.0.100 local { auth = pubkey certs = carolCert.pem id = } remote { auth = pubkey id = moon.strongswan.org } children { home { remote_ts = 10.1.0.0/16 start_action = start } } version = 2 proposals = aes128-sha256-curve25519 } }
vpp运行配置:
vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.100/24
site-to-site配置
讯享网10.1.0.0/16 -- | 192.168.0.1 | === | 192.168.0.2 | -- 10.2.0.0/16 moon-net moon sun sun-net
site1 moon配置
证书位置:
/usr/local/etc/swanctl/x509ca/strongswanCert.pem /usr/local/etc/swanctl/x509/moonCert.pem /usr/local/etc/swanctl/private/moonKey.pem
swanctl配置:
讯享网/usr/local/etc/swanctl/swanctl.conf: connections { gw-gw { local_addrs = 192.168.0.1 remote_addrs = 192.168.0.2 local { auth = pubkey certs = moonCert.pem id = moon.strongswan.org } remote { auth = pubkey id = sun.strongswan.org } children { net-net { local_ts = 10.1.0.0/16 remote_ts = 10.2.0.0/16 rekey_time = 5400 rekey_bytes = rekey_packets = esp_proposals = aes128gcm128-sha256 } } version = 2 mobike = no reauth_time = 10800 proposals = aes128-sha256-x25519 } }
vpp配置:
vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.1/24 vppctl set int ip addr G1/2 10.1.0.1/16
site2 sun配置
证书位置:
讯享网/usr/local/etc/swanctl/x509ca/strongswanCert.pem /usr/local/etc/swanctl/x509/carolCert.pem /usr/local/etc/swanctl/private/carolKey.pem
swanctl配置:
/usr/local/etc/swanctl/swanctl.conf: connections { gw-gw { local_addrs = 192.168.0.2 remote_addrs = 192.168.0.1 local { auth = pubkey certs = carolCert.pem id = sun.strongswan.org } remote { auth = pubkey id = moon.strongswan.org } children { net-net { local_ts = 10.2.0.0/16 remote_ts = 10.1.0.0/16 rekey_time = 5400 rekey_bytes = rekey_packets = esp_proposals = aes128gcm128-sha256 } } version = 2 mobike = no reauth_time = 10800 proposals = aes128-sha256-x25519 } }
vpp配置:
讯享网vppctl set int state G1/1 up vppctl set int state G1/2 up vppctl set int state local0 up vppctl set int ip addr G1/1 192.168.0.2/24 vppctl set int ip addr G1/2 10.2.0.1/16
开始运行
首先启动VPP,配置好strongswan的配置和VPP的配置,然后两端都使用systemctl start strongswan-starter.service(新版本strongswan5.9.6 不能使用该命令,该服务操作的配置文件是ipsec.conf)启动strongswan
cat /usr/lib/systemd/system/strongswan-starter.service [Unit] Description=strongSwan IPsec IKEv1/IKEv2 daemon using ipsec.conf After=syslog.target network-online.target [Service] ExecStart=/usr/local/sbin/ipsec start --nofork Restart=on-abnormal [Install] WantedBy=multi-user.target
新版本strongswan5.9.6使用以下文件,systemctl start strongswan.service
讯享网cat /usr/lib/systemd/system/strongswan.service [Unit] Description=strongSwan IPsec IKEv1/IKEv2 daemon using swanctl After=network-online.target [Service] Type=notify ExecStart=/usr/local/sbin/charon-systemd ExecStartPost=/usr/local/sbin/swanctl --load-all --noprompt ExecReload=/usr/local/sbin/swanctl --reload ExecReload=/usr/local/sbin/swanctl --load-all --noprompt Restart=on-abnormal [Install] WantedBy=multi-user.target Alias=strongswan-swanctl.service
可以使用swanctl --stats命令查看一下vpp的插件加载是否正确,在/var/log/messages文件中查看日志是否有报错等等。
然后查看一下VPP端,strongswan是否已经建立好了连接,如果建立成功之后,vpp中应该会有如下的显示
[root@localhost home]# vppctl show api clients Shared memory clients Name PID Queue Length Queue VA Health strongswan 14102 0 0x00000001301ce9c0 OK [root@localhost home]# vppctl show udp punt IPV4 UDP ports punt : 500, 4500 IPV6 UDP ports punt : 500, 4500
在两端执行swanctl --load-all加载所有的配置和证书。
在协商的发起端执行初始化命令,这个net-net是根据当前的swanctl.conf配置文件中children字段里面的内容填写的。
讯享网swanctl --initiate --child net-net 或者 swanctl --initiate --child home
查看日志/var/log/messages是否成功,如果有类似如下的显示,则证明IKE协商成功了
Apr 8 18:05:06 localhost ipsec: 08[CFG] initiating 'home' Apr 8 18:05:06 localhost ipsec: 08[IKE] initiating IKE_SA home[1] to 192.168.0.1 Apr 8 18:05:06 localhost ipsec: 08[ENC] generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ] Apr 8 18:05:06 localhost ipsec: 08[NET] sending packet: from 192.168.0.2[500] to 192.168.0.1[500] (240 bytes) Apr 8 18:05:06 localhost ipsec: 05[NET] sending vpp packet: from 192.168.0.2[500] to 192.168.0.1[500] by sock 8 Apr 8 18:05:06 localhost charon: 16[ENC] parsed IKE_AUTH response 1 [ IDr CERT AUTH SA TSi TSr N(MOBIKE_SUP) N(NO_ADD_ADDR) ] Apr 8 18:05:06 localhost ipsec: 10[NET] received packet: from 192.168.0.1[500] to 192.168.0.2[500] (273 bytes) Apr 8 18:05:06 localhost ipsec: 10[ENC] parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(FRAG_SUP) N(HASH_ALG) N(CHDLESS_SUP) N(MULT_AUTH) ] Apr 8 18:05:06 localhost ipsec: 10[CFG] selected proposal: IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519 Apr 8 18:05:06 localhost ipsec: 10[IKE] received cert request for "C=CN, O=StrongSwan, CN=StrongSwan CA" Apr 8 18:05:06 localhost ipsec: 10[IKE] sending cert request for "C=CN, O=StrongSwan, CN=StrongSwan CA" Apr 8 18:05:06 localhost ipsec: 10[IKE] authentication of '' (myself) with RSA_EMSA_PKCS1_SHA2_256 successful Apr 8 18:05:06 localhost ipsec: 10[IKE] sending end entity cert "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost ipsec: 10[IKE] establishing CHILD_SA home{1} Apr 8 18:05:06 localhost ipsec: 10[ENC] generating IKE_AUTH request 1 [ IDi CERT N(INIT_CONTACT) CERTREQ IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(NO_ADD_ADDR) N(MULT_AUTH) N(EAP_ONLY) N(MSG_ID_SYN_SUP) ] Apr 8 18:05:06 localhost ipsec: 10[ENC] splitting IKE message (1488 bytes) into 2 fragments Apr 8 18:05:06 localhost ipsec: 10[ENC] generating IKE_AUTH request 1 [ EF(1/2) ] Apr 8 18:05:06 localhost ipsec: 10[ENC] generating IKE_AUTH request 1 [ EF(2/2) ] Apr 8 18:05:06 localhost ipsec: 10[NET] sending packet: from 192.168.0.2[500] to 192.168.0.1[4500] (1252 bytes) Apr 8 18:05:06 localhost ipsec: 10[NET] sending packet: from 192.168.0.2[500] to 192.168.0.1[4500] (308 bytes) Apr 8 18:05:06 localhost ipsec: 05[NET] sending vpp packet: from 192.168.0.2[500] to 192.168.0.1[4500] by sock 8 Apr 8 18:05:06 localhost ipsec: 05[NET] sending vpp packet: from 192.168.0.2[500] to 192.168.0.1[4500] by sock 8 Apr 8 18:05:06 localhost ipsec: 11[NET] received packet: from 192.168.0.1[4500] to 192.168.0.2[500] (1252 bytes) Apr 8 18:05:06 localhost ipsec: 11[ENC] parsed IKE_AUTH response 1 [ EF(1/2) ] Apr 8 18:05:06 localhost ipsec: 11[ENC] received fragment #1 of 2, waiting for complete IKE message Apr 8 18:05:06 localhost ipsec: 16[NET] received packet: from 192.168.0.1[4500] to 192.168.0.2[500] (164 bytes) Apr 8 18:05:06 localhost ipsec: 16[ENC] parsed IKE_AUTH response 1 [ EF(2/2) ] Apr 8 18:05:06 localhost ipsec: 16[ENC] received fragment #2 of 2, reassembled fragmented IKE message (1344 bytes) Apr 8 18:05:06 localhost ipsec: 16[ENC] parsed IKE_AUTH response 1 [ IDr CERT AUTH SA TSi TSr N(MOBIKE_SUP) N(NO_ADD_ADDR) ] Apr 8 18:05:06 localhost ipsec: 16[IKE] received end entity cert "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost ipsec: 16[CFG] using certificate "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost ipsec: 16[CFG] using trusted ca certificate "C=CN, O=StrongSwan, CN=StrongSwan CA" Apr 8 18:05:06 localhost charon: 16[IKE] received end entity cert "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost ipsec: 16[CFG] checking certificate status of "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost ipsec: 16[CFG] certificate status is not available Apr 8 18:05:06 localhost charon: 16[CFG] using certificate "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost charon: 16[CFG] using trusted ca certificate "C=CN, O=StrongSwan, CN=StrongSwan CA" Apr 8 18:05:06 localhost charon: 16[CFG] checking certificate status of "C=CN, O=StrongSwan, CN=" Apr 8 18:05:06 localhost charon: 16[CFG] certificate status is not available Apr 8 18:05:06 localhost charon: 16[CFG] reached self-signed root ca with a path length of 0 Apr 8 18:05:06 localhost charon: 16[IKE] authentication of 'moon.strongswan.org' with RSA_EMSA_PKCS1_SHA2_256 successful Apr 8 18:05:06 localhost charon: 16[IKE] IKE_SA home[1] established between 192.168.0.2[]...192.168.0.1[moon.strongswan.org] Apr 8 18:05:06 localhost charon: 16[IKE] scheduling rekeying in 14049s Apr 8 18:05:06 localhost charon: 16[IKE] maximum IKE_SA lifetime 15489s Apr 8 18:05:06 localhost charon: 16[CFG] selected proposal: ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ Apr 8 18:05:06 localhost charon: 16[KNL] firstly created, spd for G1/1 found sw_if_index is 1 Apr 8 18:05:07 localhost charon: 16[IKE] CHILD_SA home{1} established with SPIs c079e4f7_i c8e6f92e_o and TS 192.168.0.2/32 === 10.1.0.0/16 Apr 8 18:05:07 localhost charon: 16[IKE] peer supports MOBIKE
此时如果你查看vpp的配置应该可以看到ipsec相关的内容
讯享网[root@localhost home]# vppctl show ipsec all [0] sa 1 (0x1) spi (0xf7e479c0) protocol:esp flags:[tunnel ] [1] sa 2 (0x2) spi (0x2ef9e6c8) protocol:esp flags:[tunnel ] spd 1 ip4-outbound: [1] priority 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 [3] priority 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 [5] priority 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 0 - 65535 packets 0 bytes 0 [7] priority 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 0 - 65535 packets 0 bytes 0 [10] priority action protect type ip4-outbound protocol any sa 2 local addr range 192.168.0.2 - 192.168.0.2 port range 0 - 65535 remote addr range 10.1.0.0 - 10.1.255.255 port range 0 - 65535 packets 0 bytes 0 ip6-outbound: ip4-inbound-protect: [8] priority action protect type ip4-inbound-protect protocol any sa 1 local addr range 192.168.0.2 - 192.168.0.2 port range 0 - 65535 remote addr range 10.1.0.0 - 10.1.255.255 port range 0 - 65535 packets 0 bytes 0 [9] priority action protect type ip4-inbound-protect protocol any sa 1 local addr range 192.168.0.2 - 192.168.0.2 port range 0 - 65535 remote addr range 10.1.0.0 - 10.1.255.255 port range 0 - 65535 packets 0 bytes 0 ip6-inbound-protect: ip4-inbound-bypass: [0] priority 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 [2] priority 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 [4] priority 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 0 - 65535 packets 0 bytes 0 [6] priority 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 0 - 65535 packets 0 bytes 0 ip6-inbound-bypass: SPD Bindings: 1 -> G1/1 [root@localhost home]# vppctl show ipsec sa detail [0] sa 1 (0x1) spi (0xf7e479c0) protocol:esp flags:[tunnel ] locks 3 salt 0x0 thread-indices [encrypt:-1 decrypt:-1] seq 0 seq-hi 0 last-seq 0 last-seq-hi 0 window 0000000000000000000000000000000000000000000000000000000000000000 crypto alg aes-cbc-128 key [redacted] integrity alg sha-256-128 key [redacted] packets 0 bytes 0 table-ID 0 tunnel src 192.168.0.1 dst 192.168.0.2 resovle via fib-entry: 10 stacked on: [@3]: dpo-load-balance: [proto:ip4 index:12 buckets:1 uRPF:13 to:[3:1773]] [0] [@2]: dpo-receive: 192.168.0.2 on G1/1 [1] sa 2 (0x2) spi (0x2ef9e6c8) protocol:esp flags:[tunnel ] locks 2 salt 0x0 thread-indices [encrypt:-1 decrypt:-1] seq 0 seq-hi 0 last-seq 0 last-seq-hi 0 window 0000000000000000000000000000000000000000000000000000000000000000 crypto alg aes-cbc-128 key [redacted] integrity alg sha-256-128 key [redacted] packets 0 bytes 0 table-ID 0 tunnel src 192.168.0.2 dst 192.168.0.1 resovle via fib-entry: 15 stacked on: [@3]: dpo-load-balance: [proto:ip4 index:17 buckets:1 uRPF:18 to:[3:1884]] [0] [@5]: ipv4 via 192.168.0.1 G1/1: mtu:9000 fafce41c0800
查看vpp的fib表,也动态添加了对应的路由进去,例如在Roadwarrior场景中,客户端carol中自动添加的10.1.0.0/16的路由,通过192.168.0.1 G1/1出去
[root@localhost home]# vppctl show ip fib ipv4-VRF:0, fib_index:0, flow hash:[src dst sport dport proto ] epoch:0 flags:none locks:[adjacency:1, default-route:1, nat-hi:2, ] 0.0.0.0/0 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:1 buckets:1 uRPF:0 to:[0:0]] [0] [@0]: dpo-drop ip4 0.0.0.0/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:2 buckets:1 uRPF:1 to:[0:0]] [0] [@0]: dpo-drop ip4 10.1.0.0/16 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:18 buckets:1 uRPF:20 to:[0:0]] [0] [@5]: ipv4 via 192.168.0.1 G1/1: mtu:9000 fafce41c0800 10.2.0.0/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:14 buckets:1 uRPF:15 to:[0:0]] [0] [@0]: dpo-drop ip4 10.2.0.0/16 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:13 buckets:1 uRPF:14 to:[0:0]] [0] [@4]: ipv4-glean: G1/2: mtu:9000 ffffffffffffe0806 10.2.0.1/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:16 buckets:1 uRPF:19 to:[0:0]] [0] [@2]: dpo-receive: 10.2.0.1 on G1/2 10.2.255.255/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:15 buckets:1 uRPF:17 to:[0:0]] [0] [@0]: dpo-drop ip4 192.168.0.0/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:10 buckets:1 uRPF:9 to:[0:0]] [0] [@0]: dpo-drop ip4 192.168.0.1/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:17 buckets:1 uRPF:18 to:[3:1884]] [0] [@5]: ipv4 via 192.168.0.1 G1/1: mtu:9000 fafce41c0800 192.168.0.0/24 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:9 buckets:1 uRPF:8 to:[1:108]] [0] [@4]: ipv4-glean: G1/1: mtu:9000 ffffffffffffce41c0806 192.168.0.2/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:12 buckets:1 uRPF:13 to:[3:1773]] [0] [@2]: dpo-receive: 192.168.0.2 on G1/1 192.168.0.255/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:11 buckets:1 uRPF:11 to:[0:0]] [0] [@0]: dpo-drop ip4 224.0.0.0/4 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:4 buckets:1 uRPF:3 to:[0:0]] [0] [@0]: dpo-drop ip4 240.0.0.0/4 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:3 buckets:1 uRPF:2 to:[0:0]] [0] [@0]: dpo-drop ip4 255.255.255.255/32 unicast-ip4-chain [@0]: dpo-load-balance: [proto:ip4 index:5 buckets:1 uRPF:4 to:[0:0]] [0] [@0]: dpo-drop ip4
如果是Roadwarrior场景我们在移动客户端carol ping 10.1.0.1可以成功ping通
讯享网vpp# ping 10.1.0.1 116 bytes from 10.1.0.1: icmp_seq=1 ttl=64 time=7.7229 ms 116 bytes from 10.1.0.1: icmp_seq=2 ttl=64 time=1.2671 ms 116 bytes from 10.1.0.1: icmp_seq=3 ttl=64 time=4.2904 ms 116 bytes from 10.1.0.1: icmp_seq=4 ttl=64 time=8.3667 ms 116 bytes from 10.1.0.1: icmp_seq=5 ttl=64 time=1.3370 ms
此时如果在中间抓包的话,应该看到的是ESP报文,我们查看vpp的节点统计,数据如下,说明IPSEC隧道建立成功了
vpp# show errors Count Node Reason 5 ipsec4-output-feature IPSec policy protect 5 esp4-encrypt ESP pkts received 5 esp4-decrypt ESP pkts received 5 ipsec4-input-feature IPSEC pkts received 5 ipsec4-input-feature IPSEC pkts matched 5 ipsec4-output-feature IPSec policy bypass 5 esp4-encrypt ESP pkts received
同理,site-to-site的场景也可以通过这个方法来进行验证。更多的场景应用可以通过上面说的官方测试例的网站来进行搭建。
使用DPDK加解密套件
上面的VPP startup.conf配置文件使用了openssl的加解密套件,但是如果想要更高的处理性能的话,需要使用DPDK的加解密套件。添加方式是将上面的startup.conf文件dpdk部分修改为下面的配置添加dpdk加密虚拟设备vdev crypto_aesni_mb
dpdk
{
log-level debug
huge-dir /dev/hugepages
vdev crypto_aesni_mb
dev 0000:00:06.0 { name G1/1 }
dev 0000:00:07.0 { name G1/2 }
}
添加完成之后,可以使用下面的命令查看
讯享网show dpdk crypto devices show dpdk crypto show ipsec backends
查看DPDK解加密设备是否加载
vpp# show dpdk crypto devices
crypto_aesni_mb crypto_aesni_mb up
numa_node 0, max_queues 8
SYMMETRIC_CRYPTO, SYM_OPERATION_CHAINING, CPU_AVX2, CPU_AESNI, OOP_LB_IN_LB_OUT
Cipher: aes-cbc-128, aes-cbc-192, aes-cbc-256, aes-ctr-128, aes-ctr-192, aes-ctr-256, aes-gcm-128, aes-gcm-192, aes-gcm-256
Auth: md5-96, sha1-96, sha-256-96, sha-256-128, sha-384-192, sha-512-256
enqueue 0 dequeue 0 enqueue_err 0 dequeue_err 0
free_resources 1 :
thr_id -1 qp 7 enc_inflight 0, dec_inflights 0
used_resources 7 :
thr_id 1 qp 0 enc_inflight 0, dec_inflights 0
thr_id 2 qp 1 enc_inflight 0, dec_inflights 0
thr_id 3 qp 2 enc_inflight 0, dec_inflights 0
thr_id 4 qp 3 enc_inflight 0, dec_inflights 0
thr_id 5 qp 4 enc_inflight 0, dec_inflights 0
thr_id 6 qp 5 enc_inflight 0, dec_inflights 0
thr_id 7 qp 6 enc_inflight 0, dec_inflights 0
show dpdk crypto placement查看dpdk加解密设备绑定的线程,此处需要注意一点,如果VPP采用多线程工作模式的话,dpdk的加密设备是不会绑定在vpp_main主线程的,而且加解密处理入口节点dpdk-crypto-input也只绑定在了工作线程。作为正常网关转发是可以工作的,因为进来的ipsec报文都会走到dpdk-crypto-input节点处理,在工作线程处理,包含dpdk的解加密资源。
但是如果是类似于上面的操作,通过网关去直接ping对端的话,是无法通的,有如下报错
dpdk-esp4-encrypt Cipher/Auth not supported
查看/var/log/messages显示以下的log
讯享网dpdk_esp_encrypt_inline:247: unsupported SA by thread index 0
vpp# show dpdk crypto placement Thread 1 (vpp_wk_0): crypto_aesni_mb dev-id 0 queue-pair 0 Thread 2 (vpp_wk_1): crypto_aesni_mb dev-id 0 queue-pair 1 Thread 3 (vpp_wk_2): crypto_aesni_mb dev-id 0 queue-pair 2 Thread 4 (vpp_wk_3): crypto_aesni_mb dev-id 0 queue-pair 3 Thread 5 (vpp_wk_4): crypto_aesni_mb dev-id 0 queue-pair 4 Thread 6 (vpp_wk_5): crypto_aesni_mb dev-id 0 queue-pair 5 Thread 7 (vpp_wk_6): crypto_aesni_mb dev-id 0 queue-pair 6
查看ipsec加密后端是否变成dpdk backend
vpp# show ipsec backends
IPsec AH backends available:
Name Index Active
crypto engine backend 0 yes
IPsec ESP backends available:
Name Index Active
crypto engine backend 0 no
dpdk backend 1 yes
持续更新。。。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/121029.html