随笔-9  评论-21  文章-63  trackbacks-0

目录

1      实现总体思想 ... 2

1.1          Netfilter HOOK 机制的介绍 ... 2

1.2          处理模块之间的关系 ... 3

1.3          功能模块之间的关系 ... 5

2      各个模块的实现 ... 6

2.1          处理模块的实现 ... 6

2.1.1       Netfilter钩子函数 ... 6

2.1.1.1           实现思想 ... 6

2.1.1.2           实现细节 ... 6

2.1.2       进入IP包预处理 ... 7

2.1.2.1           实现思想 ... 7

2.1.2.2           实现细节 ... 7

2.1.3       IPSec进入策略处理 ... 7

2.1.3.1           实现思想 ... 7

2.1.3.2           实现细节 ... 7

2.1.4       路由 ... 8

2.1.4.1           实现思想 ... 8

2.1.4.2           实现细节 ... 8

2.1.5       本机对IP包处理 ... 8

2.1.5.1           实现思想 ... 8

2.1.5.2           实现细节 ... 8

2.1.6       IPSec进入处理 ... 9

2.1.6.1           实现思想 ... 9

2.1.6.2           实现细节 ... 9

2.1.7       转发处理 ... 10

2.1.7.1           实现思想 ... 10

2.1.7.2           实现细节 ... 10

2.1.8       本地IP包处理 ... 11

2.1.8.1           实现思想 ... 11

2.1.8.2           实现细节 ... 11

2.1.9       IPSec外出处理 ... 11

2.1.9.1           实现思想 ... 11

2.1.9.2           实现细节 ... 11

2.1.10            发送处理 ... 12

2.1.10.1         实现思想 ... 12

2.1.10.2         实现细节 ... 12

2.2          功能模块的实现 ... 13

2.2.1       策略库(SPD)的实现: ... 13

2.2.1.1           实现思想: ... 13

2.2.1.2           实现细节 ... 14

2.2.1.3           基本操作 ... 14

2.2.2       安全关联库(SAD)的实现 ... 14

2.2.2.1           实现思想 ... 14

2.2.2.2           实现细节 ... 15

2.2.2.3           基本操作 ... 15

2.2.3       AH协议处理模块实现 ... 15

2.2.3.1     AH格式: ... 16

2.2.3.2           实现功能: ... 16

2.2.3.3           实现模式: ... 16

2.2.4       ESP协议处理模块实现 ... 17

2.2.4.1     ESP格式 ... 17

2.2.4.2           实现功能: ... 17

2.2.4.3           实现模式 ... 17

2.2.5       算法实现 ... 18

2.2.5.1           实现思想 ... 18

2.2.5.2           实现细节 ... 18

2.2.6       日志、统计、配置与审计实现 ... 18

2.2.6.1           日志与审计 ... 18

2.2.6.2           统计 ... 18

2.2.6.3           配置 ... 18

2.2.7       应用程序与内核的通讯接口实现 ... 19

2.2.7.1           实现思想 ... 19

2.2.7.2           实现细节 ... 20

    1        实现总体思想

通过改造 Linux IP 协议栈源代码,使得 IP 实现与 IPSec 实现完全整合。该实现按功能分,可以分为以下几个功能模块模块:安全策略库,安全关联库, AH 协议处理, ESP 协议处理,算法 ( 加密卡的实现 ) ,日志、统计、配置与审计,面向应用的接口。按处理过程分,还可以分为以下几个处理模块:进入 IP 层预处理、 IPSec 进入策略处理、路由、本机对 IP 包处理、 IPSec 进入处理、转发处理、本地 IP 包处理、 IPSec 外出处理、发送处理。

Ipsec 协议实现与 IP 实现的整合思想:利用 Netfilter HOOK 机制,在接受 IP 包和发送 IP 包的过程中,在适当的处理位置调用相关的 ipsec 处理模块。

1.1      Netfilter HOOK 机制的介绍

                                                                      1

Netfilter linux2.4 内核实现数据包过滤 / 数据包处理 /NAT 等功能的抽象、通用化的框架。 Netfilter 框架包含以下三部分:

1、            为每种网络协议 (IPv4 IPv6 ) 定义一套钩子函数( IPv4 定义了 5 个钩子函数) , 这些钩子函数在数据报流过协议栈的几个关键点被调用。在这几个点中,协议栈将把数据报及钩子函数标号作为参数调用 netfilter 框架。

2、            内核的任何模块可以对每种协议的一个或多个钩子进行注册,实现挂接,这样当某个数据包被传递给 netfilter 框架时,内核能检测是否有任何模块对该协议和钩子函数进行了注册。若注册了,则调用该模块的注册时使用的回调函数,这样这些模块就有机会检查 ( 可能还会修改 ) 该数据包、丢弃该数据包及指示 netfilter 将该数据包传入用户空间的队列。

3、            那些排队的数据包是被传递给用户空间的异步地进行处理。一个用户进程能检查数据包,修改数据包,甚至可以重新将该数据包通过离开内核的同一个钩子函数中注入到内核中。

IP 层的五个 HOOK 点的位置如图 1 所示: (ipv4)

1.      NF_IP_PRE_ROUTING :刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验   和等检测), 源地址转换在此点进行;

2.      NF_IP_LOCAL_IN :经路由查找后,送往本机的通过此检查点 ,INPUT 包过滤在此点进行;

3.      NF_IP_FORWARD :要转发的包通过此检测点 ,FORWORD 包过滤在此点进行;

4.      NF_IP_POST_ROUTING :所有马上便要通过网络设备出去的包通过此检测点,内置的目的地址转换功能(包括地址伪装)在此点进行;

5.      NF_IP_LOCAL_OUT :本机进程发出的包通过此检测点, OUTPUT 包过滤在此点进行。

1.2      处理模块之间的关系

IPSec 安全网关对 IP 报文的接收、转发和发送处理的整个过程如图 2 。当安全网关的网卡接收的数据报时,通过中断触发内核的中断处理程序,将网卡接收的数据报传送到内核空间,然后再通过 IP 层预处理程序将数据报转换为 IP 包。此时,我们将利用内核的 Netfilter 机制提供的 HOOK PRE_ROUTING ,将 IP 包传送到 IPSec 进入策略处理模块。该模块将决定哪些包可以进入安全网关,哪些包需要丢弃。对于允许进入网关的 IP 包,将送回到路由处理模块。路由处理根据 IP 头决定 IP 包是发送到本机还是继续转发。

对于发送到本机的 IP 包,首先经过内核对 IP 包的处理,如:分片重组、选项处理等等。然后利用 HOOK LOCAL_IN ,将重组的 IP 包传送到 IPSec 进入处理模块。 IPSec 进入处理模块将对 IPSec 包和非 IPSec 包进行区分,对于发往本机的非 IPSec 包将直接传送到传输层处理模块;对于 IPSec 包将进行认证或解密等 IPSec 处理,并剥去 IPSec 头。处理完后,将重新组装成 IP 包发回到 IP 层预处理模块。这样该 IP 包将重新通过路由来决定发往何处。

对于转发的 IP 包,首先进行转发处理,如:决定下一跳、减少 TTL 、对某些特殊情况发送 ICMP 包。然后,利用 HOOK IP_FORWARD ,将 IP 包传送到外出 IPSec 外出处理模块。 IPSec 处理将根据策略区分 IPSec 包、非 IPSec 包以及包发往何处。对于 IPSec 包将丢弃。对于发往内部网的非 IPSec 包,直接将包传送给发送处理模块,发往内部网。对于发往外部网的 IP 包,将根据策略进行认证或加密等 IPSec 处理,最后将处理过的 IP 包传送到发送处理模块。

对于从安全网关传输层发送的报文,首先进行本地的 IP 包处理,构建 IP 包。然后对 IP 包进行路由,决定 IP 包的出口。路由之后将利用 HOOK LOCAL_OUTPUT ,将 IP 包传送到 IPSec 外出处理模块。 IPSec 外出处理将根据策略决定那些包需要进行 IPSec 处理。对于不需要处理的 IP 包,直接传送到发送处理模块。对于需要进行 IPSec 处理的 IP 包,将根据策略进行认证或加密等 IPSec 处理,然后将 IPSec 包重新发回到路由处理模块,决定 IPSec 包将发往何处。当再次经过 HOOK 点时, IPSec 外出处理将通过策略将处理过的 IP 包直接传送到发送处理模块。发送处理模块将进行分片等处理,最后将包发送到网卡。

                                                        2

 

  1.3      功能模块之间的关系

各功能模块之间的关系如图 3 所示。安全策略库存放了由用户或系统管理员所制定的策略,策略将决定通讯的双方是否采用 IPSec 处理,以及决定采用何种 IPSec 协议、模式、算法和嵌套需求。安全关联库由一系列安全关联项组成。安全关联是两个通讯实体经过协商建立起来的一种协定。它们决定了用来保护数据包安全所需的各种参数:序号计数器;抗重播窗口; AH 验证算法及其密钥; ESP 加密、认证算法、密钥;安全关联的生存期; IPsec 协议模式。算法库存放了多种可选的认证和加密算法,在处理时将通过安全关联中的算法项来指明所需要使用的算法。面向应用的接口提供了管理安全策略库,以及配置网关,处理日志、统计、审计信息的接口。用户或系统管理员可通过配置服务器关联全策略库,还可以进行手工注入安全关联或者启动 IKE 动态协商安全关联,以及对日志、统计、配置、审计信息的提取和处理。

                                                                      3

 

2        各个模块的实现

2.1      处理模块的实现

2.1.1       Netfilter 钩子函数

2.1.1.1      实现思想

利用 Linux 提供的 Netfilter 框架,并在 Netfilter 框架提供的 HOOK 点上注册并实现 IPSec 相关处理函数,使得 IPSec 处理能加入到 IP 包接收或发送处理过程的适当位置。

2.1.1.2      实现细节

Linux 内核的 Netfilter 框架在 ipv4 中提供了 5 HOOK 点(图 1 ),在每个 HOOK 点上都可以通过一个注册函数 nf_register_hook(struct nf_hook_ops *reg) 将自己实现的处理函数挂接到 HOOK 点上。这样在每一次 HOOK 点被激活时,都将查询并执行该 HOOK 点所注册的处理函数。然后在处理结束时返回相关的信息来决定被处理的包是丢弃、拒绝,还是继续进行 HOOK 点后面的处理。

因此我们的工作便是生成一个 struct nf_hook_ops 结构的实例(结构如下):

 struct nf_hook_ops

{

struct list_head list; 

nf_hookfn *hook;

int pf;

int hooknum;   

     int priority;

};

并将该结构中的一个相关处理函数 nf_hookfn (定义如下)实现为我们所需的相关 IPSec 处理函数:

unsigned int nf_hookfn(unsigned int hooknum,

                   struct sk_buff **skb,

                   const struct net_device *in,

                   const struct net_device *out,

                   int (*okfn)(struct sk_buff *));

并用 nf_register_hook 将该实例注册到由 hooknum 所指定的 HOOK 点上。这样,当 hooknum 指定的 HOOK 点被激活时(如在 ip_rcv 中的: NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish) ),将根据 priority 所指定的优先级,依次执行在该 HOOK 点注册的函数,因此我们所实现的相关 IPSec 处理函数将得到执行。

Netfilter 还提供了一系列返回信息(如下):

l       NF_ACCEPT 继续正常传输数据报

l       NF_DROP 丢弃该数据报,不再传输

l       NF_STOLEN 模块接管该数据报,不要继续传输该数据报

l       NF_QUEUE 对该数据报进行排队 ( 通常用于将数据报给用户空间的进程进行处理 )

l       NF_REPEAT 再次调用该钩子函数

在处理结束后将通过返回信息来决定被处理的数据报在 HOOK 点之后应该怎样处理。

2.1.2       初始化 IPSec 的实现

2.1.2.1      注册 HOOK

2.1.3       进入 IP 包预处理

2.1.3.1      实现思想

从网卡传来的数据报在进入 IP 层处理之前先进行一些检查,并在此时激活第一个 HOOK 点: NF_IP_PRE_ROUTING ,对进入本机的包进行进入前预处理。我们实现的 IPSec 进入策略处理模块也在此时通过 HOOK 点被调用执行。

2.1.3.2      实现细节

该模块首先对传入的 IP 包进行必要的检查:

1、 通过包类型标志 pkt_type 检查 IP 包是否是其他机器( PACKET_OTHERHOST )的,如果是就丢弃。

2、 检查 IP 包的长度是否合法。

3、 检查 IP 版本。

4、 检查校样和。

最后激活 HOOK 点: NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,ip_rcv_finish) 。然后将依次调用在该 HOOK 点上注册处理函数,其中包括我们实现的 IPSec 进入策略处理模块。。

2.1.4       IPSec 进入策略处理

2.1.4.1      实现思想

该模块将根据 IP 报文的相关信息构造选择符。然后通过选择符查询进入安全策略库,找到第一个匹配项(策略)。再根据策略对 IP 进行策略检查和处理:

1、 对于外部网的进入包

drop :(增强型包过滤)不允许某些外部网的包进入;不允许某些外部网的不加密包进入;不允许某些网应该加密却未加密的包进入;不允许某些外部网的加密包进入。

reject :类似于 drop ,不过要对 ICMP 包进行特殊处理。

accept :对某些外部网的不加密包或加密包允许通过,对已经经过 IPSec 处理的包(用于 IPSec 嵌套的情况)允许通过。

2、 对于内部网的进入包

drop :对某些内部网机器的 IP 包不允许通过

accept :允许内部网的 IP 包通过

最后对于通过的包,传回到 ip_rcv_finish 继续处理

2.1.4.2      实现细节

1、 IP 包中提取源/目的 IP 地址、源/目的端口、下一层协议等信息。

2、 根据这些提取的信息查询进入安全策略库,找到匹配的策略项。

3、 根据策略项所指定的策略进行处理:

丢弃:返回 NF_DROP Netfilter 机制将丢弃该数据包,不再传输。并将该事件记录到日志中。

拒绝:返回 NF_STOLEN Netfilter 机制将接管该数据包,不再继续传输。并将该事件记录到日志中。

接收:返回 NF_ACCEPT Netfilter 机制将正常传输该数据包:将该包传送给 ip_rcv_finish 。其中对于 IPSec 包需要作上标记(利用标记变量 nmask ),表明该包需要在以后进行 IPSec 处理。

2.1.5       路由

2.1.5.1      实现思想

根据 IP 包的源地址、目的地址和服务类型( tos )等信息查找路由表,找到该 IP 包对应的路由项,并记录该项。在路由项中指出了 IP 包接下来该如何处理:对于本地 IP 包,将交给本机的 IP 处理模块 ip_local_deliver ;对于非本机接收包,适合转发的将交给转发处理模块 ip_forward ,其他情况将作特殊处理。

2.1.5.2      实现细节

1、 将从 IP 包中提取的源地址、目的地址和服务类型值,通过适当的散列算法产生散列值。

2、 根据散列值在路由缓存散列表中查找散列位置

3、 进一步根据源地址、目的地址、输入接口、服务类型在散列链中找到正确的路由项。

4、 根据路由项中指定的输入处理函数,调用适当的函数:对于本地 IP 包调用 ip_local_deliver ;对于其他 IP 包调用 ip_forward

2.1.6       本机对 IP 包处理

2.1.6.1      实现思想

对经过路由传送来的 IP 包,首先检查是否存在分片。如果存在分片,必须缓存 IP 分片包。等所有的分片到齐时,进行分片重组处理,将分片合成完整的 IP 报文。然后激活 HOOK 点: NF_IP_LOCAL_IN ,对进入 IP 包进行相关处理。我们实现的 IPSec 进入处理模块也在此时调用。

2.1.6.2      实现细节

1、            检查 IP 包的 3 位标志字段,当 IP 包片偏量 (frag_off) 14 (IP_MF) 1 , 表示该 IP 包有后继分片。这时将进行分片重组处理 ip_defrag

2、            分片重组处理:

l       根据分片包的 16 位标识、源地址、目的地址、协议字段计算分片包的散列值。

l       根据散列值,定位该包在分片链中的位置。

l       如果有分片链,说明已有其他分片到达。将该分片插入到对应的分片队列中。

l       检查该分片是否是最后一个分片,分片是否都到齐了。如果都满足,则将分片重组为一个完整的 IP 包。

l       返回新的 IP 包。

3、            激活 HOOK 点: NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL, ip_local_deliver_finish) 。然后将依次调用在该 HOOK 点上注册处理函数,其中包括我们实现的 IPSec 进入处理模块。

2.1.7       IPSec 进入处理

2.1.7.1      实现思想

首先检查 nmask 标记,判断该 IP 包是否是一个 IPSec 包。如果不是,则将利用返回值 NF_ACCEPT 继续正常传输该数据报到 ip_local_deliver_finish 。如果是,则将进行 IPSec 进入处理,并在处理完后调用 ip_rcv IP 包传送回进入 IP 包预处理模块,此时应该返回 NF_DROP ,使该包不在向上传输。

IPSec 进入处理首先将从 IP 包中提取目的地址、下一协议、安全参数索引( spi )信息,并根据这些信息查找安全关联库( SAD ),找到对应的唯一的一个 SA 。然后根据找到的 SA 进行: SA 状态处理、 SA 生存期处理、重播窗口处理、模式处理、相关 IPSec 协议处理( AH ESP )。当处理完一个 SA 后,必须要标记处理过的 SA (用于后期的进入策略匹配),并检查是否存在 SA 串(即多个 SA )。如果有,则循环处理 SA 串,直到遇到传输层协议头或者非本机的 IP 头(表明 SA 串上的所有 SA 都处理完毕)。

最后根据处理过的 IP 包的相关信息查找安全策略库( SPD ),找到该 IP 包所对应的进入策略(该策略应该与发送端的外出策略是相同的)。然后检查该策略所指定的 SA 串是否与处理过并标记的 SA 串相同,从而判断是否进行了所要求的 IPSec 处理。如果不相同,则丢弃该 IP 包,并进行日志记录。

2.1.7.2      实现细节

1、            检查 nmask 标记(该标记在进入策略处理时被设置上)。如果不是 IPSec 包,返回 NF_ACCEPT ;如果是,继续进行 IPSec 进入处理。

2、            提取 IP 头中的目的地址、下一协议,通过下一协议字段信息,提取 IPSec 头中的安全参数索引( spi )信息。

3、            根据 <dst proto spi> 三元组查找安全关联库( SAD )。如果没找到对应的 SA (或 SA 串),则将该 IP 包丢弃,并记录日志信息;如果找到了对应的 SA (或 SA 串),则将根据 SA (或 SA 串)对 IPSec 包进行下面的处理。

4、            检查 SA 的状态 :对于幼稚( SADB_SASTATE_LARVAL )和死亡( SADB_SASTATE_DEAD )状态的包将丢弃,并记录日志信息

5、            检查 SA 的生存期。生存期分为以下几种:字节数、包数、使用时间、增加时间,并且对于每一种生存期还有软硬之分。如果是硬生存期过期了,则将激活 IKE 模块动态协商一个新的 SA ,将过期的 SA (或 SA 束)删除,并将 IP 包丢弃,并记录日志信息;如果是软生存期过期了,同样要激活 IKE 模块动态协商一个新的 SA ,但此时并不删除 SA (或 SA 束),而是将 SA 的状态标记为正在死亡( SADB_SASTATE_DYING )。而且不丢弃该数据包,继续进行处理。

6、            检查重播窗口:检查时将判断到达的 IPSec 包的序列号是否小于该网关所记录的处理过的最大 IPSec 包的序列号。如果小,则再检查序号的差值是否超过了窗口的大小。如果没有超过,则检查窗口,判断该 IPSec 包是否已经到达过,如果已经到达过,则将该包丢弃;如果没到达,则接收。如果到达的 IPSec 包的序列号大于处理过的最大序列号,则接收,并继续处理。

7、            根据 SA 指定的 IPSec 协议( AH ESP )、算法和密钥进行认证或(和)解密处理。

8、            更新重播窗口:此时检查如果被处理的 IPSec 包的序列号大于网关处理过的最大序列号,并且序号的差值小于窗口大小,则更新窗口,标记该到达并处理过的包。最后将网关处理的最大序列号更新为该被处理 IPSec 包的序列号。

9、            更新 SA 的生存期:字节数、包数、使用时间。

10、         记录下该 SA 信息,以便与以后进行进入策略检查。

11、         提取 IPSec 头指出的下一协议:如果还是 IPSec 协议,说明有多个 SA SA 串)对该数据包进行了处理,则需要利用原 IP 头和处理过的数据区组成新的 IP 包,进行循环处理;如果是 IP 协议,说明 SA (或 SA 串)已经处理完毕,则需要根据内部的 IP 头信息组建新的 IP 包,并跳出循环进入后继的处理。

12、         进行进入策略匹配:根据新的 IP 包信息(源地址/目的地址、源端口/目的端口、协议)查找安全策略库( SPD ),找到该包所对应的第一个进入处理策略(可能匹配多个)。检查该策略所指定的 SA (或 SA 串)即其应用的顺序是否与 10 中记录过的 SA (或 SA 串)以及顺序相同。如果相同,则说明满足进入策略允许该数据报进入安全网关;如果不相同,则将再次查找策略库(遍历策略库),直到匹配成功。如果最后还没有找到正确的进入策略,则将丢弃该数据报,并记录日志信息。

13、         最后调用 IP 包与处理模块( ip_rcv ),重新对新生成的 IP 包进行处理。

14、         返回 NF_DROP ,说明 IP 包不从该 HOOK 点返回。

2.1.8       转发处理

2.1.8.1      实现思想

对于非本地的 IP 包,需要将它进行转发。转发处理首先要检查 IP 头的 TTL 字段不能小于 1 ,否则将向该 IP 包的发送者发送 ICMP 超时差错包。减小 TTL 值。接下来提取该 IP 包的路由信息(在转发前已经记录),根据路由信息获得该 IP 包的外出设备。然后根据外出设备的 MTU IP 头的分片标志,判断允许分片,如果需要分片且不允许分片( DF 位设置为 1 ),则发送 ICMP_DEST_UNREACH 目的不可达 ICMP 报文。最后激活 HOOK 点: IP_FORWARD ,对转发 IP 包进行相关处理。我们实现的 IPSec 外出处理模块也在此时调用。

2.1.8.2      实现细节

1、            检查 IP 头的 TTL 字段:如果小于 1 ,则向该 IP 包的发送者发送 ICMP 生存期超时差错包,丢弃该包

2、            减少该 IP 包的 TTL 值。

3、            提取转发前记录的路由信息,找到外出设备。

4、            根据外出设备的 MTU IP 头的分片标志,判断允许分片,如果需要分片且不允许分片( DF 位设置为 1 ),则发送 ICMP_DEST_UNREACH 目的不可达 ICMP 报文。

5、            激活 HOOK 点: NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2, ip_forward_finish); 调用我们实现的 IPSec 外出处理模块。

2.1.9       本地 IP 包处理

2.1.9.1      实现思想

对于本地传输层( TCP UDP )产生的包,首先将进行路由,然后组装成 IP 包。最后包激活 HOOK 5 NF_IP_LOCAL_OUT 。在这个 HOOK 点上将调用我们实现的 IPSec 外出处理模块。

2.1.9.2      实现细节

1.       查找路由

2.       填充 IP 头,组装 IP

3.       激活 HOOK 5 NF_IP_LOCAL_OUT

对于 TCP NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ip_queue_xmit2)

对于 UDP NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,ip_send)

2.1.10    IPSec 外出处理

2.1.10.1   实现思想

IPSec 的外出处理函数挂在 HOOK 点: NF_IP_FORWARD NF_IP_LOCAL_OUT 上。在这里首先将根据 IP 包的相关信息查找安全策略库( SPD ),找到该 IP 包对应的外出策略。策略将决定对该 IP 包的几种处理: ACCEPT; IPSEC SAList; DROP; TRAP; HOLD ACCEPT 表示对 IP 包不做任何 IPSec 处理,允许 IP 包直接通过。 IPSEC SAList 表示将根据 SAList 指示的安全关联串( SA 串)对 IP 包进行 IPSec 处理。 DROP 表示将丢弃策略不允许外出的 IP 包,或者先前试图等待 SA 协商,但 SA 却不能协商成功的包。 TRAP 表示要求更新一个安全关联( SA ),此时将设置 SA HOLD ,并通过发送 PF_KEY 消息来触发 IKE 守护进程进行安全关联( SA )的协商。 HOLD 表示 SA 还未协商成功,要求丢弃 IP 包。

对于可以进行 IPSec 外出处理的包,根据策略提供的信息,查找安全关联库( SAD ),找到该 IP 包应该应用的安全关联( SA SA 串)。如果没有找到 SA ,则将通过发送 PF_KEY 消息来触发 IKE 守护进程进行安全关联( SA SA 串)的协商,此时 IP 包被暂时保持,直到 sa 创建或超时。如果找到了 SA (或 SA 串),则检查 SA 的状态、生存期。然后进行 IPSec 协议处理,根据 SA (或 SA 串)所指定的协议( AH ESP ),循环对 IP 包进行认证、加密等处理。 SA 串处理完毕后,将重新构建 IP 包,并对新的 IP 包重新进行路由。最后返回 NF_ACCEPT ,表示该 IP 包将进入激活 HOOK 点时指定的处理函数: ip_queue_xmit2 ip_send ,进入发送处理模块。

2.1.10.2   实现细节

1.       查找 SPD (外出策略)库,找到匹配项的所定义的目标动作。

1)   ACCEPT :返回 NF_ACCEPT ,即包不用经过任何加工处理,直接通过。

2)   DROP :返回 NF_DROP ,丢掉此包不再传输

3)   TRAP :发送 PF_key 消息 ACCQUIRE IKE 守护进程,在 SPD 中把它替换成 HOLD ,返回 NF_STOLEN ,不继续传输该数据报。

4)   HOLD :截取符合此策略的包,更新以前截获的包,返回 NF_STOLEN ,不继续传输该数据报。

5)   IPSEC Salist :进行 IPSec 处理。以下便是详细的步骤说明。

2.       根据策略提供的信息,查找安全关联库( SAD ),寻找该 IP 包应该应用的安全关联( SA SA 串)。如果没有找到 SA ,则将通过发送 PF_KEY 消息来触发 IKE 守护进程进行安全关联( SA SA 串)的协商,此时 IP 包被暂时保持,直到 sa 创建或超时。

3.       如果找到了 SA SA 串),检查当前 SA 的状态,对于已经过时的 SA, 要释放 SA 和这个 SA 包。

4.       设置重播窗口。

5.       检查 SA 的生命期,包括使用时间,已处理的字节数,处理的 IP 包数目。对于已经过生命期的 SA, 要删除,发 PF_key 消息给 IKE 。(* IKE 应该自己维护 SA , 更新删除应该能自动进行不需内核干涉或提醒,但是要实现对于字节的限制应该只能由内核告诉 IKE 进行更新)

6.       根据 SA 中的协议设置 AH ESP 头,然后转到 SA 链的下一个 SA ,重复从 4 开始的处理。

7.       设置新的 MTU (如果实现了 PMTU 机制,要做相应的处理)

8.       根据 SA 指定的协议( AH ESP )设置头空间和尾空间,并使用 SA 规定的协议中应该使用的加密或验证算法处理 IP 包数据区内容。

9.       处理结束后调整 IP 头重新设置校验和。

10.    更新 SA 的生命期

11.    对于 SA 串将循环处理 SA 串上的每一个 SA

12.    对新的 IP 包重新进行路由。

13.    返回 NF_ACCEPT ,将 IP 包传送到进入激活 HOOK 点时指定的处理函数: ip_queue_xmit2 ip_send 。进入发送处理模块。

2.1.11    发送处理

2.1.11.1   实现思想

首先要判断是否需要进行分片处理。转发的 IP 包,或者是本地产生的经过 IPSec 处理过的 IP 包的长度有可能大于发送接口的 MTU ,此时必须进行分片处理。分片结束后将 IP 包交给链路层处理模块,然后由网卡发送该数据包。

2.1.11.2   实现细节

1、 判断是否需要分片,如果需要,则调用分片函数 ip_fragment 进行分片。

2、 IP 包交给链路层处理模块: dev_queue_xmit

2.2      功能模块的实现

2.2.1       策略库( SPD )的实现:

2.2.1.1      实现思想:

我们将安全策略库的配置设置在安全网关上,各个安全网关独立配置策略库。但要保证策略的一致性。

安全策略库( SPD )说明了对 IP 数据报提供何种保护,并以何种方式实施保护。 SPD 中策略项的建立和维护应通过协商;而且对于进入和外出处理都应该有自己的策略库。对于进入或外出的每一份数据报,都可能有三种处理:丢弃、绕过或应用 IPSec SPD 提供了便于用户或系统管理员进行维护的管理接口。可允许主机中的应用程序选择 IPSec 安全处理。 SPD 中的策略项记录对 SA(SA ) 进行了规定,其字段包含了 IPsec 协议、模式、算法和嵌套等要求。 SPD 还控制密钥管理 ( ISAKMP) 的数据包,即对 ISAKMP 数据包的处理明确说明。

SPD 是利用 radix 树型结构来构造。每一个结点就是一个策略项。策略项中包含一个 SAID 数据结构,它是 SPD SAD 之间的接口。可以由它来查找 SAD ,从而指定相关的 SA (或 SA 串)。这样使得策略项可以对应相关的一个 SA 或者多个 SA SA 串)。

SPD 中策略项的查找是通过选择符来进行的。 SA SA 束的粒度决定于选择符。通过选择符,可以找到外出或进入 IP 包应该实行的策略项。两个策略项的选择符可以相同。我们选用第一匹配项,并保证 SPD 始终以同样的顺序进行查找,这样就保证了第一匹配策略项的一致性选择。

2.2.1.2      实现细节

1、 策略库的构建方式:采用 radix 树型结构。存放在内核中。

2、 选择符的构成。选择符包含下列参数:目的地 IP 地址、源 IP 地址、名字(用户 ID 、系统名字)、数据保密等级、源端口和目的端口

3、 策略项的构成。策略项包含下列参数: radix 树相关数据结构、 SAID 结构、地址、掩码。

4、 为用户层提供的接口( PF_key ),允许用户程序可通过接口对库进行操作:添加、删除、搜索(匹配)。

5、 对策略库的操作时机:用户通过配置界面对策略库进行相关操作; IKE 协商 SA 完毕后,在更新 SAD 的同时,也要建立新的 SAD SPD 之间的关联。

2.2.1.3      基本操作

用户配置程序通过 PF_key 接口调用内核相关程序程序,实现对安全策略库的操作。

1、 添加策略项: ipsec_create_policy

根据用户传入的信息构造策略项结构,然后将该结构加入到 radix 树中。

2、 删除策略项: ipsec_delete_policy

根据用户传入信息,在 radix 树中找到该策略项,然后删除该节点。

3、 查找策略项: ipsec_find_policy

根据用户传入信息,在 radix 树中查找到该策略项。

2.2.2       安全关联库( SAD )的实现

2.2.2.1      实现思想

安全关联( SA )是构成 IPSec 的基础。 SA 是两个通信实体经过协商建立起来的一种协定。他们决定了用来保护数据保安全的 IPSec 协议、模式、算法及密钥、生存期、抗重播窗口、计数器等等。 SA 是单向的,因此外出和进入处理需要不同的 SA SA 还与协议相关,每一种协议都有一个 SA

安全关联库( SAD )维护了 IPSec 协议用来保障数据保安全的 SA 记录。每个 SA 都在 SAD 中有一条记录相对应。对于外出处理,应 SPD 中查找指向 SAD SA 的指针,如 SA 未建立,则应激活 IKE 建立 SA ,并同 SPD SAD 的记录关联起来。对于进入处理, SAD 的记录用目的 IP 地址、 IPSec 协议类型和 SPI 标识。

SAD 是利用 HASH 表来构造的。

SAD 的查找是通过一个三元组( SAID ):协议、目的地址、 SPI 来进行的,三元组标识了唯一的 SA 。通过对 SAID 的散列找到 SA 头,然后再进行详细匹配找到相应的 SA

SA 的管理可以通过手工进行,也可以通过 IKE 来进行动态协商。为了进行 SA 的管理,我们利用 PF_key 实现了一个用户应用与内核通讯的接口。

2.2.2.2      实现细节

1、 安全关联库( SAD )的构建方式:通过 hash 表(如图)

2、 SAD 库的查找通过一个 SAID < 目的地址、协议、 SPI>

3、 SA 记录的构成。每一个 SA 的基本结构包括:

l       序号计数器: 32 比特。

l       序号计数器溢出标志:标识序号计数器是否溢出。如果溢出,则产生一个审计事件,并禁止用 SA 继续发送数据包。

l       抗重播窗口: 32 比特计数器及位图,用于决定进入的 AH ESP 数据包是否为重发的。

l       AH 验证算法及其密钥等。

l       ESP 加密算法、密钥、 IV 模式、 IV 等。

l       ESP 验证算法、密钥等。如未选择验证服务,该字段为空。

l       安全关联的生存期:一个时间间隔。

l       IPsec 协议模式:隧道、传输或通配:主机实施应支持所有模式;网关实施应支持隧道模式

l       PMTU :所考察的路径的 MTU 及其寿命变量。

4、 SAD SPD 之间是通过 SAID 进行关联的。通过查看 SPD 中的 SAID 值,可对 SAD 进行查找,找到该策略项所应该实施的 SA

5、 安全关联库与用户程序( IKE )的接口,通过 PF_key 来实现。无论是手工创建一个 SA ,还是通过密钥管理协议 IKE 动态创建 SA ,都通过该接口对 SAD SPD 进行操作。

2.2.2.3      基本操作

1、 创建一个 SA ipsec_create_sa

根据用户提供的 SA 相关参数构建 SA 结构,然后提取 SAID 值,并对 SAID 进行散列。将 SA 结构放入散列链头。

2、 删除一个 SA ipsec_delete_sa

根据用户参数,提取 SAID 。根据 SAID 查找 SAD ,找到后将 SA 结构从链中删除。

3、 查找一个 SA ipsec_find_sa

根据用户参数,提取 SAID 。对 SAID 散列后,在 SAD 散列表中中找到 SA 链头,再进行详细 SAID 匹配找到为一的 SA

2.2.3       AH 协议处理模块实现

2.2.3.1     
AH 格式:

 


各字段含义如下:

1)      下一头( 8 比特):标识紧跟验证头的下一个头的类型。

2)      载荷长度( 8 比特):以 32- 位字为单位的验证头的长度,再减去 2 。例如,缺省的验证数据字段的长度是 96 比特( 3 32- 位字),加上 3 个字长的固定头,头部共 6 个字长,因此该字段的值为 4

3)      保留( 16 比特):保留为将来使用。

4)      安全参数索引( 32 比特):用于标识一个安全关联。

5)      序号( 8 比特):单增的计数器值。

6)      验证数据(可变):该字段的长度可变(但应为 32- 位字的整数倍),包含的数据有数据包的 ICV (完整性校验值)或 MAC

2.2.3.2      实现功能:

AH 用于为 IP 提供数据完整性、数据原始身份验证和一些可选的、有限的抗重播服务。

2.2.3.3      实现模式:

在安全网关上只实现隧道模式:

AH

外部 IP

下一个头

载荷长度

保留

文本框: 已验证 安全参数索引 (SPI)

序列号

 

验证数据

 

内部 IP

TCP

数据

2.2.4       ESP 协议处理模块实现

2.2.4.1     
ESP 格式

各字段含义如下:

1)      安全参数索引( 32 比特):标识一个安全关联。

2)      序号( 32 比特):单增的计数器值。

3)      载荷数据(可变):传输层数据段(传输模式)或 IP 包(隧道模式),通过加密得到保护。

4)      填充( 0-255 字节):额外的字节。有的加密算法要求明文长度是 8 位组的某个整倍数。

5)      填充长度( 8 比特):表示填充的字节数。

6)      下一头( 8 比特):通过标识载荷中的第一个头(如 IPv6 中的扩展头,或诸如 TCP 之类的上层协议头),确定载荷数据字段中数据的类型。

验证数据(可变):长度可变的字段(应为 32- 位字的整数倍),用于填入 ICV ICV 的计算范围为 ESP 包中除去验证数据字段的部分。

2.2.4.2      实现功能:

ESP 用于为 IP 提供机密性、数据源验证、抗重播以及数据完整性等安全服务。

2.2.4.3      实现模式

在安全网关上只实现隧道模式:

 

    ESP

IP

安全参数索引 (SPI)

序列号

文本框: 已验证 内部 IP

文本框: 已加密 TCP

 

数据

填充项

填充项长度

下一个头

验证数据

 

2.2.5       算法实现

2.2.5.1      实现思想

支持多种认证算法和加密算法,并且可以动态添加。其中现有认证算法支持: hmac-md5-96 hmac-sha1-96 ;加密算法支持: 3des-md5-96 3des-sha1-96 。密钥生成分为两种:一种是预共享密钥 PSK ,一种是公私钥 RSA 。如果利用 PSK 生成密钥,则通讯双方的 PSK 密钥必须相同。

2.2.5.2      实现细节

 

2.2.6       日志、统计、配置与审计实现

2.2.6.1      日志与审计

VPN 网关将记录对网关进行的各种操作,包括错误信息、安全规则文件的修改等等。并按照安全等级、事件名称和发生时间、事件内容及操作者以图表的方式显示在 VPN 配置服务器上。

通过安全事件的日志记录,可以提高 VPN 网关管理的安全性,并通过审查日志发现违反安全规则的操作,并及时采取相应的措施。

2.2.6.2      统计

对各种流量信息进行统计:通过的总 IP 包数,丢弃的总 IP 包数、经过 IPSec 处理过的 IP 包数、绕过处理的 IP 包数,各种流过的协议,时间统计等等。

2.2.6.3      配置

为用户提供友好的配置界面,可以对 VPN 网关的的各种信息进行配置。(如图)

2.2.7       应用程序与内核的通讯接口实现

2.2.7.1      实现思想

用户的各种配置请求,以及密钥管理守护进程( IKE )都将涉及到对内核相关数据结构(安全策略库 SPD 、安全关联库 SAD )的修改。因此我们利用 PF_KEY 协议来实现用户应用程序与内核的通讯。(如图)

如图,用户配置信息和 IKE 守护进程可以通过 PF_KEY 协议接口对内核空间的安全策略库( SAD )进行操作。同样,内核程序也可以通过 PF_KEY 协议接口向应用程序发出协商 SA 的请求。

PF_KEY 协议簇的 socket 的操作同其他类型的 socket 操作无差别。

int  s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);

用户进程通过使用这个 socket 接口来发送和接收信息与内核通信。对这个 socket 的操作同其它 socket 一样, bind(), connect(), socketpair(), accept(), getpeername(), getsockname(), ioctl(), and listen().

  实现的主要消息种类:

             SADB_ADD        向内核的 SADB 增加一个 SA

             SADB_DELETE     从内核的 SADB 删除一个 SA

             SADB_GET         从内核的 SADB 获取一个 SA

             SADB_REGISTER   IKE 守护进程注册策自己能提供服务的协议类型, AH ESP 或其它

             SADB_EXPIRE      内核发送给 IKE 守护进程某个 SA 过期,包括软、硬过期

 

2.2.7.2      实现细节

1 PF_KEY 消息头格式

上面是 ­­PF_KEY 消息的基本头,每个基本头后面都可以跟随一个或多个扩展域:生存期域、地址域、密钥域等等。

2 、内核实现

内核启动时调用 ipsec_init()(/ipsec_init.c), 为了使用 pf_key 接口它调用 pfkey_init()(/pfkey_v2.c) 。此函数注册它要服务的 SA 类型: AH,ESP,IPIP, 如果配置了 IP_COMP 那么也注册。首先建立几个全局变量结构结构,然后把定义的 SA 类型添加到对应的 pfkey_supported_list 队列中,然后注册 pfkey socket 操作集。

l       struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1]

每种 SA 类型一个链表数组,说明了当前内核支持的 Sa 类型。

l       struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];

每种 SA 类型一个链表数组,说明了在当前内核中注册使用的 pfkey socket

l       struct socket_list *pfkey_open_sockets = NULL

应用 pfkey 接口的进程打开的 socket

l       struct sock *pfkey_sock_list = NULL;

应用 pfkey 接口的进程打开的 socket 对应的 sock

应用程序和内核之间通讯时,首先要建立一个 ­­­PF_KEY 消息结构,然后将消息类型和消息相关内容填入 PF_KEY 消息中,最后发送消息。

在接收消息时,将会根据不同的消息类型进行不同的处理。


posted on 2006-12-03 21:19 Flutist 阅读(575) 评论(0)  编辑 收藏 引用 所属分类: 学习文章
只有注册用户登录后才能发表评论。