日期:2014-05-16  浏览次数:20426 次

基于openswan klips的IPsec VPN实现分析(六)SADB操作

基于openswan klips的IPsec VPN实现分析(六)SADB操作

转载请注明出处:http://blog.csdn.net/rosetta

    这里的操作是指由openswan的密钥管理守护进程pluto对于内核SADB的操作。如下来至rfc2367的密钥关联程序和PF_KEY的关系图。

                   

                     +----------------+

                     |密钥管理守护进程|

                     +----------------+

                       |           |

                       |           |

                       |           |                   应用程序

              ======[PF_KEY]====[PF_INET]==========================

                       |           |                   系统内核

               +------------+   +-----------------+

               |  密钥引擎 |   |     TCP/IP     |

               |    或者   |---|      包括       |

               |    SADB   |   |     IPsec      |

               +------------+   +-----------------+

                                        |

                                   +----------+

                                   | 网络接口 |

                                   +----------+

 

              图1:密钥关联程序和PF_KEY的关系


 

         pluto第二阶段协商成功收尾时,在发起方的quick_inR1_outI2()函数里调用install_ipsec_sa()增加SA。

        增加SA函数调用过程:

quick_inR1_outI2(), install_ipsec_sa(),setup_half_ipsec_sa(),kernel_ops->add_sa()(kernel_ops的成员赋值在《应用层和内核通信》一节讲,klips的add_sa指向的函数是pfkey_add_sa())。

删除SA函数调用过程:

在删除隧道或者SA过期等情况下调用相关删除函数,delete_ipsec_sa(),del_spi(),kernel_ops->del_sa()。

         如果存在多个SA的情况下,归组SA,即放到SA结构体数组中:

         setup_half_ipsec_sa(),kernel_ops->grp_sa()。

 

传说中的安全联盟SA概貌如斯:

struct kernel_sa {

   const ip_address *src; //源地址

   const ip_address *dst;  //目的地址

   

   const ip_subnet *src_client;//源保护子网

   const ip_subnet *dst_client;//目的保护子网

                 

   ipsec_spi_t spi; //spi

   unsigned proto; //安全协议

   unsigned satype; //安全联盟类型,比如ESP,AH,IPIP,IPCOMP等

   unsigned replay_window;//重放窗口

   unsigned reqid; //请求ID

                    

   unsigned authalg; //认证算法

   unsigned authkeylen; //认证算法密钥长度

   char *authkey;   //认证密钥

             

   unsigned encalg; //加密算法

   unsigned enckeylen; //加密算法密钥长度

   char *enckey; //加密密钥

 

   int encapsulation;//封装

   const char *text_said;

};

 

应用层构造SADB发送给内核,构造过程看似复杂,其实它只利用了一个指针数组做为中间buf,然后把此buf中的数据拷到pfkey_msg中,最后把pfkey_msg通过write pfkeyfd套接字把消息传给内核,最后释放指针和空间。

static bool pfkey_add_sa(const structkernel_sa *sa, bool replace)

{

   struct sadb_ext *extensions[SADB_EXT_MAX + 1]; //构造SADB临时使用的指针数组。

    boolsuccess = FALSE;

        

         //构造消息头结构体structsadb_msg信息。

   s