2.2用户空间数据结构
在内核中加入相关的内核模块选项后,为了在用户空间使用iptables软件提供相关的规则必须为该软件提供相关的命令行选项,为了使各个扩展模块使用一个版本的iptables软件而不必编写相关扩展的特定软件版本,采用共享库可以解决该问题,共享库应该具有-init()功能,它的功能和内核模块功能相似,在装载时被自动调用,该功能根据添加的新MATCH和新TARGET不同分别调用register-match()或register-target(),共享库可以提供初始化数据结构和提供相关选项的功能。编写共享库中使用的重要数据结构是iptables_match,它作为参数传递给register-match()注册相关的命令行匹配选项让iptables识别该新匹配。
Struct iptables_match
{struct iptables_match *next;用于形成一个MATCH列表的指针,初始化为NULL
ipt_chainlabel name; MATCH功能的名字,
必须与库函数名相同便于主程序根据MATCH名加载相应的动态连接库
const char *version;版本信息通常被设置IPTABLES_version宏
size_t size;该MATCH的数据大小
size_t userspacesize;由于内核可能修改某些域,
在这里填写被改变数据区大小,它一般和size大小同
void (*help)(void);打印帮助选项大纲
void (*init)();初始化ipt-entry-match结构
int (*parse)();扫描并接收本MATCH的命令行参数,正确接受返回非0
void (*final_check)();检查是否强制选项(如--ids)被描述,如果不正确退出
void (*print)();查询当前表中的规则时,显示使用了当前match规则的额外信息
void (*save)();PARSE的反转,被iptable-save调用再生match的命令行参数
const struct option *extra_opts;NULL结尾的参数列表,提供命令行其余选项
/*以下参数由iptables内部使用,用户不必填写*/
Unsigned int option_offset;
Struct ipt_entry_match *m;
Unsigned int mflags;
Unsigned int used;
}
2.3 入侵检测模块的实现
本文介绍的功能扩展主要是通过IPTABLE命令向防火墙“IP表”添加字符串匹配规则和数据包内容相匹配从而实现对数据包的检测,在内核中需要添加一个ids检测匹配模块,在用户空间命令行上需要提供一个 “iptables -m ids –ids “匹配内容””的选项。
在内核模块中主要是实现MATCH指针函数,在该函数中使用了字符串的模式匹配算法用于检测数据包的内容。模式匹配是指在文本Text= tlt2t3...tn中检索子串Pat=P1 P2...pn(模式)的所有出现,著名的匹配算法有BF算法、KMP算法、BM算法及一些改进算法,基于BM算法的BMH算法 被证明是一种快速、高效的算法,于是在设计时采用该算法。
BMH算法于1980年Horspool提出的,该算法在匹配的过程中模式从左向右进行,但字符的比较从右向左进行,在发现不匹配时,算法根据预先计算好的skip数组将模式右移,BMH算法在最坏的情况下复杂度为O(NM),在一般情况下比BM有更好的性能,它只使用一个数组,简化了初始化过程.以下是在match函数中使用的BMH算法:
Char *ids_match
(char *pattern, char *text, int pattern_len, int text_len)
{
int k, right_end,j, i,*skip;
K = right_end = pattern _len-1;
for (i = 0; i <1024; i++) skip[i] = pattern_len;//初始化skip数组
for (i = 0; pattern [i]; i++) skip[pattern [i]] = k - i; //对skip数组进行修正
While (right_end < text_len){
For (i = 0; i < pattern _len && text [right_end - i] == pattern [k - i]; i++);
If (i == pattern _len) {
return text+(right_end - k);//返回text匹配的开始处
}
right_end = right_end + skip[text [right_end]];
//模式向右移skip[text [right_end]]位
}
Return NULL;
}
检测功能主要由match(const struct sk_buff *skb,const struct net_device *in, const struct net_device *out, const void *match info, int offset, const void *hdr,u_int16_t datalen,int *hotdrop)函数实现,该函数从缓冲区skb读取网络数据包,使用match info接受来自用户空间的匹配内容,从skb中计算出数据包的大小tlen,从match info中获取匹配内容的大小mlen,如果数据包内容为空或mlen>tlen则返回0不能进行比较;否则将网络数据包内容和大小tlen、match info中数据及大小mlen作为参数调用ids_match进行匹配,然后返回匹配结果。
填充用户空间的数据结构时,要保证name与核心对应的Match名相同,并且为了提供命令行附加选项需要填充extra_opts数据结构为{"ids",1,0,'1'},它表示ids带参数值,如果出现“—ids “匹配值””就会返回’1’用于parse()的参数来对附加信息进行处理如检查附加选项中是否有非(!)号存在,从命令行解析得到匹配内容并将其填充到传入到内核模块的数据结构中。