Linux核心網路:實現和理論(2014)-第十章 IPsec

龍蝦天天發表於2017-05-10

...

XFRM框架

       IPsec基於XFRM(讀作“transform”)框架實現,該框架源於USAGI專案,其目標是提供一種產品化的IPv6和IPsec協議棧。術語“transform”指的是在核心協議棧中根據一些IPsec規則轉發入方向報文或者出方向報文。Linux核心2.5引入了XFRM框架,XFRM是一種協議族獨立的基本框架,這意味著對於IPv4和IPv6而言存在一個通用的部分,這部分位於net/xfrm之中。IPv4和IPv6擁有各自的ESP、AH和IPCOMP實現,例如IPv4 ESP模組位於net/ipv4/esp4.c,IPv6 ESP模組在net/ipv6/esp6.c中。除此之外,IPv4和IPv6為支援XFRM基本框架還實現了一些與各自協議相關的一些模組,比如net/ipv4/xfrm4_policy.c或者net/ipv6/xfrm6_policy.c。
        XFRM框架支援網路名稱空間,這是一種輕量級的程式虛擬化,允許單個或者一組程式擁有自己的網路協議棧(在第14章會討論網路名稱空間)。每個網路名稱空間(資料型別struct net的例項)都包含一個名為xfrm的成員,該成員是資料型別struct netns_xfrm的例項。這個物件包含很多你在本章會碰到的資料結構和變數,比如XFRM策略雜湊表、XFRM狀態雜湊表、sysctl引數、XFRM狀態垃圾回收器、計數器等等。
struct netns_xfrm {
        struct hlist_head       *state_bydst;
        struct hlist_head       *state_bysrc;
        struct hlist_head       *state_byspi;
        . . .
        unsigned int            state_num;
        . . .
 
        struct work_struct      state_gc_work;
 
        . . .
 
        u32                     sysctl_aevent_etime;
        u32                     sysctl_aevent_rseqth;
        int                     sysctl_larval_drop;
        u32                     sysctl_acq_expires;
};
(include/net/netns/xfrm.h)

XFRM初始化

        在IPv4中,XFRM初始化工作在xfrm_init()函式完成,其呼叫棧為ip_rt_init()->xfrm4_init()->xfrm_init(),ip_rt_init()方法位於net/ipv4/route.c檔案中。而在IPv6中,通過呼叫ipv6_route_init()方法中的xfrm6_init()方法實現了XFRM的初始化。通過建立NETLINK_XFRM型別netlink套接字(socket)併傳送/接收netlink訊息可以實現使用者空間和核心之間的通訊。
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;
} 
        從使用者空間發出的訊息(比如XFRM_MSG_NEWPOLICY建立新的安全策略或者XFRM_MSG_NEWSA建立新的安全聯盟)會被xfrm_netlink_rcv()方法處理,該方法又會被xfrm_user_rcv_msg()方法呼叫(第二章曾討論過netlink套接字)。
        XFRM策略和XFRM狀態是XFRM框架的基礎資料結構,接下來我將陸續介紹什麼是XFRM策略以及XFRM狀態。

XFRM策略

        安全策略是一種規則,告訴IPsec一條特定流量是否應該處理或者旁路,xfrm_policy結構用來描述IPsec策略。一個安全策略包含一個選擇器(一個xfrm_selector物件)。當其選擇器匹配一條流時會提供一種策略。XFRM選擇器有一系列屬性組成:比如source和destination address、source和destination port、protocol等等,用這些屬性來識別一條流:
struct xfrm_selector {
        xfrm_address_t  daddr;
        xfrm_address_t  saddr;
        __be16  dport;
        __be16  dport_mask;
        __be16  sport;
        __be16  sport_mask;
        __u16   family;
        __u8    prefixlen_d;
        __u8    prefixlen_s;
        __u8    proto;
        int     ifindex;
        __kernel_uid32_t        user;
};

(include/uapi/linux/xfrm.h)
        xfrm_selector_match()方法使用XFRM selector、flow和family(IPv4對應AF_INET,IPv6對應AF_INET6)作為引數,當特定XFRM流量匹配中特定選擇器時返回true。注意xfrm_selector結構同樣用在XFRM狀態中,在本節後續將看到。安全策略(Security Policy)使用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];
};

(include/net/xfrm.h)
         下面將重點介紹一些xfrm_policy結構中重要的成員:
  • refcnt:XFRM引用計數,在xfrm_policy_alloc()方法中初始化為1,在xfrm_pol_hold()方法中增加計數,在xfrm_pol_put()方法中減少計數。
  • timer:Per-policy定時器,定時器的回撥函式在xfrm_policy_alloc()方法中的xfrm_policy_timer()裡設定。xfrm_policy_timer()方法在策略到期時進行相關處理:某個策略到期後呼叫xfrm_policy_delete()方法時負責刪除對應策略,向通過呼叫km_policy_expired()方法註冊的Key Manager傳送XFRM_MSG_POLEXPIRE事件。
  • lft:XFRM策略有效期(xfrm_lifetime_cfg物件),每一個XFRM策略都有一個有效期(使用時間或者位元組計數表示)。使用者可以使用ip命令和限制的引數設定XFRM有效期,比如:ip xfrm policy add src 172.16.2.0/24 dst 172.16.1.0/24 limit byte-soft 6000...該命令設定XFRM策略有效期的軟位元組限制是6000,請參閱幫助8-ip xfrm。您可以執行ip -stat xfrm policy show命令檢視有效期的配置項,顯示XFRM策略的有效期(lft)。
  • curlft:XFRM策略當前的有效期,反映某個策略當前有效期的情況,curlft是一個xfrm_lifetime_cur物件,由四個成員組成,每個成員都是unsigned型別的64bit屬性
  •         bytes:IPsec子系統處理的位元組數量,在Tx路徑的xfrm_output_one()方法和Rx路徑的xfrm_input()方法中增加。
  •         packets:IPsec子系統處理的報文數量,在Tx路徑的xfrm_output_one()方法和Rx路徑的xfrm_input()方法中增加。
  •         add_time:新增策略的時間戳,在xfrm_policy_insert()方法和xfrm_sk_policy_insert()方法中新增策略時初始化。
  •         use_time:最新一次訪問策略的時間,在xfrm_lookup()方法或者_xfrm_policy_check()方法中更新use_time的時間戳,使用xfrm_policy_insert()方法和xfrm_sk_policy_insert()方法中新增策略時初始化為0。
  • 注意:您可以執行ip -stat xfrm policy show命令檢視有效期的配置項,顯示某個XFRM策略的當前有效期(curlft)。
         




(未完待續)

原文源自網路,若有興趣可直接閱讀原文(http://apprize.info/linux/kernel/11.html)


相關文章