Xfrm -- Kernel Implementation Framework of IPSec Protocol

catalogue

1 Overview

1.1 XFRM instance

1.2 Netlink channel

1.3 XFRM State

1.3 XFRM Policy

2 receive and send IPsec message

2.1 receiving

2.2 sending

IPsec protocol helps the IP layer to establish a safe and reliable packet transmission channel. There are already such StrongSwan,OpenSwan And other mature solutions, and they all use the XFRM framework in the Linux kernel to receive and send messages.

The correct pronunciation of XFRM is transform, which means that the IPsec message received by the kernel protocol stack needs to be converted before it can be restored to the original message; Similarly, the original message to be sent needs to be converted into IPsec message before it can be sent.

1 Overview

1.1 XFRM instance

There are two important concepts in IPsec: Security Association and security policy. These two types of information need to be stored in the kernel XFRM. Core XFRM uses netns_xfrm is a structure to organize this information. It is also called XFRM instance. It can also be seen from its name that this instance is related to network namespace. Each namespace has such an instance, which is independent of each other. Therefore, different containers on the same host can use XFRM without interference with each other

struct net
{
    ......
   #ifdef CONFIG_XFRM
    struct netns_xfrm    xfrm;
    #endif 
    ......
}

1.2 Netlink channel

The Security Association and Security Policy information mentioned above are generally distributed to the kernel XFRM by the user mode IPsec process (eg. StrongSwan). This distributed channel is created during the initialization of network namespace.

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;
}

In this way, when the user issues the IPsec configuration, the kernel can call {xfrm_netlink_rcv() to receive

1.3 XFRM State

XFRM uses xfrm_state refers to the Security Association in the IPsec protocol stack. It represents all the information required for a one-way IPsec traffic, including mode (Transport or Tunnel), key, replay parameters and so on. User mode IPsec process sends an XFRM_ MSG_ At the request of newsA, XFRM can create an xfrm_state structure

xfrm_state contains many fields, which are not posted here. Only the most important fields are listed:

  • id: it's an xfrm_id structure, including the destination address, SPI, and protocol (AH/ESP) of the SA
  • props: indicates other properties of the SA, including IPsec Mode(Transport/Tunnel), source address and other information

Each xfrm_state will add multiple hash tables to the kernel, so the kernel can find the same SA from multiple features:

  • xfrm_state_lookup(): find SA through specified SPI information
  • xfrm_state_lookup_byaddr(): find SA by source address
  • xfrm_state_find(): find SA by destination address

Users can list xfrm on the current host through the ip xfrm state ls command_ 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.3 XFRM Policy

XFRM uses xfrm_policy refers to the Security Policy in the IPsec protocol stack. By issuing such rules, users can enable XFRM to allow or prohibit the sending and receiving of streams with certain characteristics. User mode IPsec process sends an XFRM_ MSG_ The policy request allows XFRM to create an XFRM}xfrm_policy structure

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;
};

There are many fields in this structure, but most of them don't need to be concerned. Let's focus on the following fields:

  • selector: indicates the characteristics of the flow matched by the Policy
  • action: the value is XFRM_POLICY_ALLOW(0) or XFRM_POLICY_BLOCK(1). The former indicates that the traffic is allowed, while the latter indicates that it is not allowed.
  • xfrm_nr: indicates the number of templates associated with this Policy. template can be understood as xfrm_ Simplified version of state, xfrm_nr determines the number of times the traffic is converted. Usually, this value is 1
  • xfrm_vec: represents the template associated with this Policy. Each element of the array is xfrm_tmpl, an xfrm_tmpl can be restored to a complete state

And xfrm_ Similar to state, users can list xfrm on the current host through the ip xfrm policy ls command_ 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

2 receive and send IPsec message

2.1 receiving

The following figure shows the process of XFRM framework receiving IPsec messages:

On the whole, the receiving of IPsec message is a circuitous process. When receiving the message at the IP layer, according to the protocol field of the message, if it is of IPsec type (AH, ESP), it will enter the XFRM framework for receiving. In this process, the more important process is xfrm_state_lookup(), this function searches for SA. If it is found, it will enter different processing processes according to different protocols and modes. Finally, it will obtain the information of the original message and re-enter the IP address_ local_ deliver(). Then, you need to go through the filtering of XFRM Policy, and finally send it to the application layer.

2.2 sending

The following figure shows the process of sending IPsec messages by XFRM framework:


 

XFRM checks whether there is a SA that meets the conditions after searching the message route. If not, it goes directly to ip_output(), otherwise it will enter the XFRM processing process, conduct corresponding processing according to the mode and protocol, and finally return to ip_output()

Keywords: ipsec linux-kernel

Added by VTS on Tue, 25 Jan 2022 12:53:15 +0200