当前位置:   article > 正文

XFRM--IPsec协议的内核实现框架_linux xfrm

linux xfrm

XFRM–A Kernel Implementation Framework of IPsec Protocol


IPsec 协议帮助IP层建立安全可信的数据传输通道。目前有StrongSwan、OpenSwan等成熟的解决方案,它们都使用Linux内核 XFRM 框架接收和发送消息。

在这里插入图片描述
在这里插入图片描述

XFRM的正确发音是transform(转换)。它代表了内核协议栈接收IPsec消息时需要经过的转换过程,以恢复到原始消息;同样地,要发送的原始消息也需要转换为IPsec消息才能发送出去。

概述

XFRM 示例

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 
    ......
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Netlink通道

上面提到了安全关联和安全策略信息,它们通常由用户模式 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样,当用户下载IPsec配置时,内核可以调用xfrm_netlink_rcv()来接收。

XFRM 状态

XFRM使用xfrm_state来表示IPsec堆栈中的安全关联(Security Association)。它包含了所有单向IPsec流量所需的信息,包括模式(传输或隧道)、密钥、替换参数等。用户态IPsec进程通过发送 XFRM_MSG_NEWSA 请求,允许XFRM创建一个xfrm_state结构。

xfrm_state包含许多字段,这里没有列出所有字段,只列出了最重要的字段:

  • Id: 它是一个xfrm_id结构,包含SA的目标地址、SPI和协议(AH/ESP)。
  • props: 表示SA的其他属性,包括IPsec模式(传输/隧道)、源地址等信息。

每个xfrm_state都会添加到内核中的多个哈希表中,因此内核可以从多个特性中找到相同的SA:

  • xfrm_state_lookup():通过指定SPI信息查找SA。
  • xfrm_state_lookup_byaddr():通过源地址查找SA。
  • xfrm_state_find():通过目标地址查找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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

XFRM 策略

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;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

这个结构体有很多字段,但大部分并不需要关注。我们应该关注下面列出的这些字段。

  • selector:表示策略匹配的流的特征。
  • action:取值为XFRM_POLICY_ALLOW(0)或XFRM_POLICY_BLOCK(1),前者表示允许流量通过,后者则表示禁止流量通过。
  • Xfrm_nr:表示与此策略相关联的模板数量。模板可被理解为 xfrm_state 的简化版本。xfrm_nr 确定流量转换的次数。通常此值为 1。
  • xfrm_vec:表示与此策略相关联的模板。数组的每个元素都是 xfrm_tmpl。可以将xfrm_tmpl解析为已完成状态。

与 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

接收和发送 IPsec 消息

接收

以下图示展示了 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()。

REF

  • Linux Kernel Networing Implementation and Throry

翻译:https://programmer.ink/think/xfrm-a-kernel-implementation-framework-of-ipsec-protocol.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/814594
推荐阅读
相关标签
  

闽ICP备14008679号