Netlink 监听 XFRM 状态消息
XFRM是 Linux 2.6 内核为安全处理引入的一个可扩展功能框架,用来在数据包经过路由路径的过程中对其进行修改,包含 3 种数据结构:策略(xfrm policy),模板(template)和状态(xfrm state)。策略是通过模板和状态发生联系的。 ——http://goo.gl/ek9dJM
xfrm is an IP framework for transforming packets (such as encrypting their payloads). This framework is used to implement the IPsec protocol suite (with the state object operating on the Security Association Database, and the policy object operating on the Security Policy Database). It is also used for the IP Payload Compression Protocol and features of Mobile IPv6. ——http://goo.gl/l30ZGn
解析XFRM SA/SP消息,可以根据Linux定义的SA/SP结构来解析相关字段
struct xfrm_usersa_info *sa_info = nlmsg_data(nlmsghdr);
struct xfrm_userpolicy_info *sp_info = nlmsg_data(nlmsghdr);
这种方式太过麻烦,下面利用libnl-xfrm-3.0 API做解析工作.
安装libnl
ubuntu下使用apt-get install
安装的 libnl 没有 xfrm 库,所以下面手动安装了开发版libnl。
root@ubuntu:~/libnl# git clone https://github.com/thom311/libnl
root@ubuntu:~/libnl# cd libnl
root@ubuntu:~/libnl# ./autogen.sh
root@ubuntu:~/libnl# ./configure
root@ubuntu:~/libnl# make
root@ubuntu:~/libnl# make install
检查是否安装成功
root@ubuntu:~/libnl# pkg-config --cflags --libs libnl-xfrm-3.0
-I/usr/local/include/libnl3 -L/usr/local/lib -lnl-xfrm-3 -lnl-3
root@ubuntu:~/libnl# pkg-config --cflags --libs libnl-nf-3.0
-I/usr/local/include/libnl3 -L/usr/local/lib -lnl-nf-3 -lnl-route-3 -lnl-3
root@ubuntu:~/libnl# pkg-config --cflags --libs libnl-route-3.0
-I/usr/local/include/libnl3 -L/usr/local/lib -lnl-route-3 -lnl-3
root@ubuntu:~/libnl# pkg-config --cflags --libs libnl-genl-3.0
-I/usr/local/include/libnl3 -L/usr/local/lib -lnl-genl-3 -lnl-3
xfrm_listen.c
程序结构类似上篇《Netlink 监听路由变化消息 》,变化的是netlink协议,广播组, 而且 xfrm 消息不像 rtmsg那样包含很多属性,XFRM 数据都从头部获取。
- 如果 nlmsghdr->nlmsg_type == XFRM_MSG_NEWSA, nlmsg_data(nlmsghdr)就是 struct xfrm_usersa_info
-
如果 nlmsghdr->nlmsg_type == XFRM_MSG_NEWPOLICY, nlmsg_data(nlmsghdr)就是 struct xfrm_userpolicy_info
此外,程序只对SA进行了解析,依葫芦画瓢,解析SP也很简单,对读者来说也是一个不错的练习。
测试
我在《IPSec VPN 简介及实战 》讲过IPsec VPN基本概念及配置方法,
下面就用一个transport模式的配置实例来测试xfrm_listen
.
先在一个shell中执行 xfrm_listen
,在另一个shell中配置setkey -f transport_setkey.cfg
,成功的话xfrm_listen会输出如下结果:
root@ubuntu:~/apac/netlink# ./xfrm_listen
[+parse_nlmsg]
[+parse_nlmsg]
[+parse_nlmsg]
[+parse_sa]
src : 20.20.20.21 dst : 20.20.20.22
proto : 50(esp:50 ah:51) spi : 0x1000
repid : 0 mode : transport
replay window : 0
hmac(md5) 0xca2cef3e4e00a0a111d3aa0048ec1ce1
cbc(aes) 0xfd64273b58d4e10af257ee5f7518a5e88a9ae77cf6f5a741
sel src : 0.0.0.0/0 dst : 0.0.0.0/0
[+parse_nlmsg]
[+parse_sa]
src : 20.20.20.22 dst : 20.20.20.21
proto : 50(esp:50 ah:51) spi : 0x1100
repid : 0 mode : transport
replay window : 0
hmac(md5) 0xca2cef3e4e00a0a111d3aa0048ec1ce2
cbc(aes) 0xfd64273b58d4e10af257ee5f7518a5e88a9ae77cf6f5a742
sel src : 0.0.0.0/0 dst : 0.0.0.0/0
[+parse_nlmsg]
[+parse_sp]
[+parse_nlmsg]
[+parse_sp]
[+parse_nlmsg]
[+parse_sp]
ip xfrm
查询security association 如下所示
root@ubuntu:~# ip xfrm state list src 20.20.20.22 dst 20.20.20.21 proto esp spi 0x00001100 reqid 0 mode transport replay-window 0 auth-trunc hmac(md5) 0xca2cef3e4e00a0a111d3aa0048ec1ce2 96 enc cbc(aes) 0xfd64273b58d4e10af257ee5f7518a5e88a9ae77cf6f5a742 sel src 0.0.0.0/0 dst 0.0.0.0/0 src 20.20.20.21 dst 20.20.20.22 proto esp spi 0x00001000 reqid 0 mode transport replay-window 0 auth-trunc hmac(md5) 0xca2cef3e4e00a0a111d3aa0048ec1ce1 96 enc cbc(aes) 0xfd64273b58d4e10af257ee5f7518a5e88a9ae77cf6f5a741 sel src 0.0.0.0/0 dst 0.0.0.0/0
security policy 如下所示
root@ubuntu:~# ip xfrm policy list src 20.20.20.22/32 dst 20.20.20.21/32 dir fwd priority 2147481648 tmpl src 0.0.0.0 dst 0.0.0.0 proto esp reqid 0 mode transport src 20.20.20.21/32 dst 20.20.20.22/32 dir out priority 2147481648 tmpl src 0.0.0.0 dst 0.0.0.0 proto esp reqid 0 mode transport
libnl-xfrm问题
libnl-xfrm API 设计的还很粗糙,如
-
proto 是 uint8_t类型的,而下面却返回 Int
int xfrmnl_sa_get_proto();
-
spi 是 uint32_t类型的, 而下面却返回 int
xfrmnl_sa_get_spi();
-
分配 sa struct 用
xfrmnl_sa_alloc()
,释放却用xfrmnl_sa_put()
留下评论