1.引言
1.1编写目的
本说明书提供了freeswan各个模块部件的说明,以供编码人员具体实现及今后的维护工作。
2.总体设计
2.1设计原则
在确定目标系统的过程中,主要遵循了以下几个原则:
? 目标系统基本上完整地实现IPSec协议族,完全支持VPN的要求; ? 目标系统的服务器端一定要建立在具有自主版权的内核操作系统之上; ? 目标系统的客户端使用方便、界面友好、配置和管理简单灵活。
2.2 软件结构
该软件由如下几个模块组成:
? KLIPS模块―― 实现对进入或外出IP包的安全处理,如:加密、认证等(运行在内核
空间)
? Pluto模块―― 实现IKE协议,完成安全联盟的协商(运行在用户空间) ? PF_KEY模块―― 实现pfkey2协议,完成上述两个模块间关于SA的通信
3.程序描述
3.1源代码文件组成
本程序由两大模块组成,一部分是klips,它运行在操作系统内核空间,主要负责安全联盟和密钥的管理工作,以及对数据报的加密、解密的处理工作;一部分是pluto,它是一个运行在用户空间的守护进程,主要负责安全联盟的协商工作。下面分别是它们的文件组成:
源文件目录
|―――freeswan
|――klips
|――libdes |――pluto |――utils
3.2 KLIPS(内核IPsec)详细设计
--―――klips
ipsec的核心实现模块
|――net
|――ipsec
|――ipsec_init.c |――ipsec_tunnel. |――ipsec_rcv.c
登记模块,并初始化 数据包的处理并发送模块 数据包接收并处理模块 管理SA的模块
sha1实现模块,由sha1.c改编 md5.c实现模块
|――ipsec_xform.c |――ipsec_sha1.c |――ipsec_md5c.c |――ipcomp.c |――radij.c
路由表的radix数的实现模块 对上个文件的改编 实现PF_KEY2协议的模块
|――ipsec_radij.c |――pfkey_v2.c
|――pfkey_v2_parser.c 对上个文件的改编 |――sysctl_net_ipsec.c
|――utils
|――eroute.c |――spi.c
用户操作eroute表的模块 用户操作SA库的模块 同上
用户操作虚接口的模块
|――spigrp.c |――tncfg.c
|――klipsdebug.c
3.2.1登记及初始化模块
3.2.1.1概要说明 3.2.1.1.1功能
向内核系统登记几个proc文件,以便于向内核空间中查询安全联盟和eoute表,以及
虚接口的状况;
初始化SA数据库(tdb链); 初始化SPDB数据库(eroute表); 初始化pf_key(PF_KEY套接口); 3.2.1.1.2模块所涉及的文件
ipsec_init.c: ipsec_xform.c: ipsec_radij.c: pfkey_v2.c: 3.2.1.2变量说明 3.2.1.2.1 proc文件结构
将下列结构登记到内核系统中,则内核就可以通过proc文件系统向应用程序提供一个安全的界面来存取如SA、eroute表等资料。
struct proc_dir_entry ipsec_eroute ; struct proc_dir_entry ipsec_spi ; struct proc_dir_entry ipsec_spigrp ; struct proc_dir_entry ipsec_tncfg ; struct proc_dir_entry ipsec_spinew ; struct proc_dir_entry ipsec_klipsdebug ; 3.2.1.2.2 notifier_block结构
struct notifier_block结构是在include/linux/notifier.h里面的: struct notifier_block {
int (*notifier_call)(struct notifier_block *self, unsigned long, void *); struct notifier_block *next; int priority; };
而register_netdevice_notifier函数在net/core/dev.c里面,是这样的: int register_netdevice_notifier(struct notifier_block *nb) {
return notifier_chain_register(&netdev_chain, nb); }
int ipsec_init(void) int ipsec_tdbinit(void) int ipsec_radijinit(void)
int pfkey_init(void)
而notifier_chain_register函数在include/linux/notifier.h里面,是这样的: extern __inline__ int notifier_chain_register(
struct notifier_block **list, struct notifier_block *n)
{
while(*list) {
if(n->priority > (*list)->priority) break;
list= &((*list)->next); }
n->next = *list; *list=n; return 0; }
显然就是根据每个block的优先级把这个block排列在一个block的链表里面,在notifier_chain_register函数里面我们可以发现这个链表是netdev_chain。实际上这个链表的作用就是在每个interface打开,关闭状态改变或者外界调用相应的ioctl的时候通知这个链表上面的所有相关的设备,而每一个协议都调用register_netdevice_notifier注册了一个netdev_notifier的结构体,这样就可以在interface改变的时候得到通知了(通过调用每个notifier_call函数)。 3.2.1.2.3 inet_protocol结构 struct inet_protocol ah_protocol = {
ipsec_rcv, NULL, 0,
/* AH handler ,定义此协议处理函数*/ /* TUNNEL error control,错误处理函数 */ /* next */
IPPROTO_AH, 0,
/* protocol ID */
/* copy */ /* data */ /* name */
NULL, \};
ipsec_rcv函数是用来接收数据的callback函数,第二个是错误处理函数,其它的copy是用来协议共享的,这个以后再说,data当然就是这个结构体的私有数据了。