L7-filter
的工作原理
L7-filter
为我们实现了可以从应用层实现过滤的功能,它的实现原理仍然是基于特征的关键字匹配。但是它不是简单的匹配某个单字和词,它使用了更高级“正则”来进行匹配。
正则表达式
(regular expression)
描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(例如字符
a
到
z
)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
L7-filter
在默认情况下,将同一个连接中的10个数据包或者2KB的数据包内容放在缓存中。并将缓存中的内容作为一段普通的文本,用模板文件中的正则去搜索,如果发现有正则匹配的内容,就会在netfilter中将这几个数据包DROP掉或者给数据包打上标记。
以上就是L7-filter的实现原理
模板文件格式
文件的名字必须和匹配的协议要相同。 (如果你要匹配的协议是“ftp”, 那你的文件名必须是 “ftp.pat”) 文件的内容格式如下:
- 第一行是协议的名字,要和文件名相同。
- 第二行是这个协议正则表达式定义。
正则表达式
l7-filter
使用 Version 8 正则表达式。 使用这个版本的正则有很多限制,只能使用一些基本的正则表达式。例如, 你不能使用范围限制 ("foo{3}"), 字符分类 ("[[:punct:]]") 或者向后引用。
另外, 我们加入了perl-style hex 来匹配 \xHH 这样的16进制值。(例如匹配一个tab, 则使用 "\x09").如果要匹配以下的字符,应当这样:
\x24 == $ (only matters if it's the last character)
\x28 == (
\x29 == )
\x 2a == *
\x2b == +
\x2e == .
\x 3f == ?
\x5b == [
\x 5c == \
\x5e == ^ (only matters if it's the first character)
\x 7c == |
l7-filter
对大小写不敏感
。l7-filter 对网络数据包当然一段普通的字符串来进行处理,所以对网络数据包中的\x00这样的为零的值是视而不见的,因为00代表没有,所以你不能匹配数据包中为null的字符。例如:一个包中的数据部分为4字节,但是这4字节的内容的某一个或者多个字节的值可能为零。这样的话,在l7-filter看来,这个数据包的长度有可能是0,也可能是1,也可能是2或者3或者4。
例子:
[\x09-\x0d -~] ==
可打印字符, 包括空白字符 whitespace
[\x09-\x0d ] ==
任何空白字符
[!-~] == non-whitespace printable characters
怎样写一个好的模板
1)
一个模板既不要写得太详细,也不要写得太宽泛。太精细了,会导致效率降低,太宽泛了会导致误杀其它网络协议。
模板 "bear" 没有写得比较精确. 这样的话,凡是连接中包含有"bear" 的都会被匹配到。如,一个HTTP 请求[url]http://bear.com[/url] 也会被匹配到。
具体写模板的方法
一、
首先便是抓包了。用Ethereal抓包,观察数据包的内容的特征和规律。
以下以
QQ
的数据包为例:
我们看它数据包的数据内容部分(不管
IP
层,只看应用层),对比每一个数据包的内容,就可以发现一个规律,每一个包的第一个字节是
02
(
16
进制值),最后一个字节是
03
(
16
进制值)。
有了这个规律,我们就可以用正则表达式来表达它了。
一、
正则表达式的相关知识。
只讲最基本,如果不明白的,可以查一些相关的资料。
^
代表首字符,
$
代表末字符,.代表任意一个字符,.?代表零个或者一个字符,.+代表一个或者任意多个字符,\是代表转义字符(\x02这个表示匹配16进制的02值)。
二、
结合以上知识,因为
QQ
包的第一个字节是
16
进制
02
,所以正则是
^\x02
,最后一个字
节是
16
进制
03
,正则是
\x03$
,在
L7-filter
的缓存中的QQ数据包中
可能有任意个
字节,再将两个正则结合起来就应当是
^\x02.+ \x03$
三、
最后写一个pat文件,文件名就叫qq.pat,文件的内容如下:
qq
^\x02.+ \x03$
再将
qq.pat
放入
/etc/l7-protocols
这个目录中。执行
iptables
命令:
iptables -t mangle -A POSTROUTING -m layer7 --l7proto qq -j DROP
即可成功阻止
QQ
的通讯。
另一个迅雷的模板例子:
启动迅雷,双击种子文件开始下载后,通过种子文件推算出文件的直接的下载地址。然后直接到下载地址进行下载。再次连接资源服务器,相当于
bt
服务器:
hub4t.sandai.net
,
IP
是
219.134.132.81
向服务器发送
tcp
查询请求。
28
00 00 00 53 00 00 00 64 00 00 00 05 00 00 00 51 55 45 52 59 00 31 00 00 00
(
16
进制值)
第一字节不变
(以上四字节不变)
其中第
1
、
17
、
18
、
19
、
20
、
21
字节不变。实际上
ascii
值为:
query
服务器返回文件在其它地方的下载地址:
28
00 00 00 53 00 00 00 04 20 00 00 09 00 00 00 51 55 45 52 59 52 45 53 50 01 98
其中第
1
、
17
、
18
、
19
、
20
、
21
字节的值不变。实际上
ascii
值为:
query
最后迅雷根据服务器返回的文件的下载地址进行下载。
另外,如果返回的地址是另一迅雷用户本机上的文件,会使用以下命令进行下载
29
00 00 00 a 9 00 00 00 5d 00 00 00 03 00 00 00 47 45 54 22 00 00 00 47 3a
其中:
第
1
位可能值为
28
或者
29
,我觉得可能是迅雷的版本号,
17
、
18
、
19
不变。后四位的值
ascii
值为:
get
重要一点。迅雷每个命令间用
3
个
null
值填充。而
l7
对
null
不敏感。所以表达式为
:
^[\x28\x29]...(query|get)
特别注意:
L7-filter
不是匹配每一个包的内容,而是匹配N个包中的全部内容。所以例子中,缓存中可能有N个QQ的数据包,但是缓存中的第一个字节肯定是QQ包的第一字节,缓存中的最后个字节肯定是QQ包的最后一个字节。
软件路由论坛
[url]www.routerclub.com[/url]
想得太美
编写此文档
2006-6-4