赞
踩
XFRM的正确发音是transform(转换)。它代表了内核协议栈接收IPsec消息时需要经过的转换过程,以恢复到原始消息;同样地,要发送的原始消息也需要转换为IPsec消息才能发送出去。
IPsec有两个重要的概念:安全关联(Security Association)和安全策略(Security Policy)。这两种类型的信息都需要储存在内核的XFRM(Transform)中。核心XFRM使用netns_xfrm结构来组织这些信息,也被称为xfrm实例( instance)(例子)。从名称可以看出,该实例与网络命名空间(network namespace)相关,每个命名空间都有一个彼此独立的实例。所以同一主机上的不同容器可以在没有干扰的情况下使用XFRM。
struct net
{
......
#ifdef CONFIG_XFRM
struct netns_xfrm xfrm;
#endif
......
}
上面提到了安全关联和安全策略信息,它们通常由用户模式 IPsec 进程发送到内核 XFRM(例如StrongSwan),这是在初始化网络命名空间时创建的。
static int __net_init xfrm_user_net_init(struct net *net)
{
struct sock *nlsk;
struct netlink_kernel_cfg cfg = {
.groups = XFRMNLGRP_MAX,
.input = xfrm_netlink_rcv,
};
nlsk = netlink_kernel_create(net, NETLINK_XFRM, &cfg);
......
return 0;
}
这样,当用户下载IPsec配置时,内核可以调用xfrm_netlink_rcv()来接收。
XFRM使用xfrm_state来表示IPsec堆栈中的安全关联(Security Association)。它包含了所有单向IPsec流量所需的信息,包括模式(传输或隧道)、密钥、替换参数等。用户态IPsec进程通过发送 XFRM_MSG_NEWSA 请求,允许XFRM创建一个xfrm_state结构。
xfrm_state包含许多字段,这里没有列出所有字段,只列出了最重要的字段:
每个xfrm_state都会添加到内核中的多个哈希表中,因此内核可以从多个特性中找到相同的SA:
用户可以通过 ip xfrm state 命令列出当前主机上的xfrm_state。
src 192.168.0.1 dst 192.168.0.2 proto esp spi 0xc420a5ed(3290473965) reqid 1(0x00000001) mode tunnel replay-window 0 seq 0x00000000 flag af-unspec (0x00100000) auth-trunc hmac(sha256) 0xa65e95de83369bd9f3be3afafc5c363ea5e5e3e12c3017837a7b9dd40fe1901f (256 bits) 128 enc cbc(aes) 0x61cd9e16bb8c1d9757852ce1ff46791f (128 bits) anti-replay context: seq 0x0, oseq 0x1, bitmap 0x00000000 lifetime config: limit: soft (INF)(bytes), hard (INF)(bytes) limit: soft (INF)(packets), hard (INF)(packets) expire add: soft 1004(sec), hard 1200(sec) expire use: soft 0(sec), hard 0(sec) lifetime current: 84(bytes), 1(packets) add 2019-09-02 10:25:39 use 2019-09-02 10:25:39 stats: replay-window 0 replay 0 failed 0
XFRM 使用 xfrm_policy 在协议栈中表示 IPsec 安全策略。通过发布此类规则,用户可以允许 XFRM 或禁止发送和接收具有特定特征的流。当用户的 IPsec 进程发送一个 XFRM_MSG_NEWPOLICY 请求时,可以创建一个 xfrm_policy 结构。
struct xfrm_policy { ...... struct hlist_node bydst; struct hlist_node byidx; /* This lock only affects elements except for entry. */ rwlock_t lock; atomic_t refcnt; struct timer_list timer; struct flow_cache_object flo; atomic_t genid; u32 priority; u32 index; struct xfrm_mark mark; struct xfrm_selector selector; struct xfrm_lifetime_cfg lft; struct xfrm_lifetime_cur curlft; struct xfrm_policy_walk_entry walk; struct xfrm_policy_queue polq; u8 type; u8 action; u8 flags; u8 xfrm_nr; u16 family; struct xfrm_sec_ctx *security; struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; struct rcu_head rcu; };
这个结构体有很多字段,但大部分并不需要关注。我们应该关注下面列出的这些字段。
与 xfrm_state 类似,用户可以通过 ip xfrm policies 命令列出当前主机上的xfrm_policy
src 10.1.0.0/16 dst 10.2.0.0/16 uid 0
dir out action allow index 5025 priority 383615 ptype main share any flag (0x00000000)
lifetime config:
limit: soft (INF)(bytes), hard (INF)(bytes)
limit: soft (INF)(packets), hard (INF)(packets)
expire add: soft 0(sec), hard 0(sec)
expire use: soft 0(sec), hard 0(sec)
lifetime current:
0(bytes), 0(packets)
add 2019-09-02 10:25:39 use 2019-09-02 10:25:39
tmpl src 192.168.0.1 dst 192.168.0.2
proto esp spi 0xc420a5ed(3290473965) reqid 1(0x00000001) mode tunnel
level required share any
enc-mask ffffffff auth-mask ffffffff comp-mask ffffffff
以下图示展示了 XFRM 框架接收 IPsec 消息的过程:
总体而言,IPsec 消息的接收是一个迂回的过程。当 IP 层接收到一条消息时,根据消息的协议字段,如果是 IPsec 类型(AH、ESP),它将进入 XFRM 框架进行接收。在这个过程中,更重要的过程是 xfrm_state_lookup(),它会寻找安全关联(SA),如果找到,则会再次进行路由。根据不同的协议和模式,会进入不同的处理过程。最后,原始消息的信息将被检索并重新进入 ip_local_delivery()。然后,它需要经过 XFRM 策略过滤,最终上传到应用层。
以下图示展示了 XFRM 框架发送 IPsec 消息的过程:
XFRM 在消息路由查找后发现 SA 是否满足要求。如果没有,则直接进入 ip_output(),否则进入 XFRM 进程,并根据模式和协议进行相应的处理。最后,它通过不同的路由返回到 ip_output()。
翻译:https://programmer.ink/think/xfrm-a-kernel-implementation-framework-of-ipsec-protocol.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。