一、前言
本文,接着上篇《Linux下Netfilter/IPTables防火墙案例分析》来说说七层过滤。
iptables等防火墙工作在四层及四层以下,都是通过数据包过滤或能够基于传输层状态检测的。
但是一般企业应用的时候,很多场景下,需要提供屏蔽不良内容、封堵某些应用层软件的功能。
QQ是一款最常用的即时通讯软件,但是很多情况下,它的使用会影响工作效率,所以有需求要把QQ屏蔽掉。
如果识别QQ的特征?
-
IP检查,不行。因为它的服务器IP地址段有可能变化。
-
端口检查,不行。局域网必须放行向外的TCP 80、UDP 53等端口,局域网主机可以访问对外网的80端口的以访问正常的网页,访问53端口以进行DNS解析。
-
状态检测,不行,由内向外发起连接建立请求,这是合法的。
-
字符串检测,不行,误伤太多,正常出现的某些特征字符串被过滤了,而且QQ数据可能被编码了。况且侦测每一个数据包进行字符串匹配效率也不高。
那么,就需要一款七层工作的工具,能够识别这些数据包的特征,进行封堵。
L7-filter就是这样的一款软件。
L7-filter要工作需要结合工作在内核中Netfilter,所以需要向内核打补丁,其实说白了就是修改源码。
二、实验
(一)规划
几点说明:
1、上图只是画出实验环境的拓扑,生产环境拓扑应该和这个有很大差别
2、网关处在网络边缘,应该加装防火墙
3、如果内网向外提供服务,网络边缘主机应该具有公网IP,否则要通过其他技术建立连接
4、如果DMZ存在,应该网络边缘网关主机还需开放相应的端口,其拓扑位置也需调整
(二)实验准备
官方下载2.6.35内核,点击这里。
官方下载 netfilter-layer7-v2.23.tar.gz。下载 l7-protocols-2009-05-28.tar.gz 。
官方下载iptables源码rpm包,iptables-1.4.7-11.el6.src.rpm。
(三)为kernel打补丁
# tar xf linux-2.6.35.9.tar.bz2 -C /usr/src/
# tar xf netfilter-layer7-v2.23.tar.gz
# cd /usr/src
# ln -sn linux-2.6.35.9/ linux
# ll linux* -d
lrwxrwxrwx 1 root root 15 Aug 26 10:55 linux -> linux-2.6.35.9/
drwxrwxr-x 23 root root 4096 Nov 23 2010 linux-2.6.35.9
[root@localhost linux]# patch -p1 < /root/netfilter-layer7-v2.23/kernel-2.6.35-layer7-2.23.patch
patching file include/linux/netfilter/xt_layer7.h
patching file include/net/netfilter/nf_conntrack.h
patching file net/netfilter/Kconfig
patching file net/netfilter/Makefile
patching file net/netfilter/nf_conntrack_core.c
patching file net/netfilter/nf_conntrack_standalone.c
patching file net/netfilter/regexp/regexp.c
patching file net/netfilter/regexp/regexp.h
patching file net/netfilter/regexp/regmagic.h
patching file net/netfilter/regexp/regsub.c
patching file net/netfilter/xt_layer7.c
(四)编译安装内核
需要依赖gcc和ncurses-devel包
# cp /boot/config-2.6.32-431.el6.x86_64 .config
# yum install gcc ncurses-devel -y
# make menuconfig
在 Networking support ---> Networking Options ---> Network Packet filtering framework (Netfilter) 下
注意两个地方:
[ IP: Netfilter Configuration ]下
保证除proc/sysctrl compatibility with old connection tracking为空外,其他都选择为M
注意IPv4 connection tracking support选择为M,连接追踪要启用。
[ Core Netfilter Configuration ]下
Layer 7 match support为M
注意:上面的Netfilter connection tracking support也应该为M
# make
# make modules_install && make install
编译过程非常耗时,可是使用make –j 4等加速编译过程,视虚拟机或者物理机的硬件性能而定。
(五)使用新版内核
首先修改下/boot/grub/grub.conf,让default=0。让系统重启后,从新版内核启动。
(六)制作iptables升级包
新建mockbuild用户,将l7-protocols-2009-05-28.tar.gz解压后的用于iptables 1.4.3和内核2.6.20之后的文件复制过来。注意目录层次。
[root@localhost ~]# useradd mockbuild
[root@localhost ~]# rpm -ivh iptables-1.4.7-11.el6.src.rpm
warning: iptables-1.4.7-11.el6.src.rpm: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
1:iptables ########################################### [100%]
[root@localhost ~]# cd rpmbuild/SOURCES/
[root@localhost SOURCES]# tar xf iptables-1.4.7.tar.bz2
[root@localhost SOURCES]# cd iptables-1.4.7
[root@localhost iptables-1.4.7]# cp /root/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/* ./extensions/
[root@localhost iptables-1.4.7]# cd ..
[root@localhost SOURCES]# tar -jcf iptables-1.4.7.tar.bz2 iptables-1.4.7/*
[root@localhost SOURCES]# mv iptables-1.4.7/ /tmp/
[root@localhost SOURCES]# cd ../SPECS/
[root@localhost SPECS]# vim iptables.spec
[root@localhost SPECS]# yum install rpm-build libselinux-devel -y
[root@localhost SPECS]# rpmbuild -ba iptables.spec
完成后,生成很多目录和文件。查看包信息
开始升级iptables。
[root@localhost SPECS]# cd ../RPMS/x86_64/
[root@localhost x86_64]# rpm -Uvh iptables-1.4.7-11.5.el6.x86_64.rpm iptables-ipv6-1.4.7-11.5.el6.x86_64.rpm
Preparing... ########################################### [100%]
1:iptables ########################################### [ 50%]
2:iptables-ipv6 ########################################### [100%]
[root@localhost x86_64]# rpm -qa | grep iptables
iptables-1.4.7-11.5.el6.x86_64
iptables-ipv6-1.4.7-11.5.el6.x86_64
[root@localhost x86_64]# rpm -ql iptables | grep layer7
/lib64/xtables/libxt_layer7.so
(七)安装L7-filter协议包
这些就是各种应用程序通讯的特征码
[root@localhost ~]# tar xf l7-protocols-2009-05-28.tar.gz
[root@localhost ~]# cd l7-protocols-2009-05-28
[root@localhost l7-protocols-2009-05-28]# make install
mkdir -p /etc/l7-protocols
cp -R * /etc/l7-protocols
(八)测试
《Linux下Netfilter/IPTables防火墙案例分析》中的防火墙设置,直接导入
[root@localhost ~]# iptables-restore < /etc/sysconfig/iptables
[root@localhost ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Tue Aug 26 11:30:34 2014
*nat
:PREROUTING ACCEPT [178:16945]
:POSTROUTING ACCEPT [2:104]
:OUTPUT ACCEPT [6:426]
-A PREROUTING -d 172.16.23.200/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.23.80
-A POSTROUTING -s 192.168.23.0/24 -j SNAT --to-source 172.16.23.200
COMMIT
# Completed on Tue Aug 26 11:30:34 2014
# Generated by iptables-save v1.4.7 on Tue Aug 26 11:30:34 2014
*filter
:INPUT DROP [173:16649]
:FORWARD DROP [0:0]
:OUTPUT DROP [6:426]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
-A FORWARD -s 192.168.23.80/32 -p tcp -m tcp --sport 80 -j ACCEPT
-A FORWARD -d 192.168.23.80/32 -p tcp -m tcp --dport 80 -j ACCEPT
-A FORWARD -d 192.168.23.0/24 -p udp -m udp --sport 53 -m state --state ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.23.0/24 -p udp -m udp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
-A FORWARD -d 192.168.23.0/24 -p tcp -m tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.23.0/24 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -d 192.168.23.0/24 -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
COMMIT
# Completed on Tue Aug 26 11:30:34 2014
导入上面的规则后,上网不受影响,而且QQ也可以通讯。
那QQ是怎么突破防线的呢?
原来它利用了TCP的80端口,而且还是个TCP的长连接,不断开。
(八)启用七层过滤
# modprobe xt_layer7
查看并开启内核参数,确保net.netfilter.nf_conntrack_acct等于1
# sysctl -a | grep conntrack_acct
net.netfilter.nf_conntrack_acct = 1
在FORWARD上增加规则
# iptables -A FORWARD -m layer7 --l7proto qq -j REJECT
测试QQ登录
[ 分析 ]
从上图中可以看出,QQ大量的对外部IP的80端口处于FIN_WAIT1状态,这是因为它和这些服务器都可以三次握手成功,但是一旦发起特制的HTTP请求,就被拦截,QQ客户端收不到服务器响应,就会尝试断开连接,发出FIN请求,但是无人回应。QQ客户端还在尝试新的连接请求。例如最下面的SYN_SENT。
至此,使用2.6.35内核,使用L7-filter结合Netfilter/IPTables,实现七层控制的实验完成。
三、QQ协议分析
(一)特征码分析
L7-filter中的QQ的特征码
^.?.?\x02.+\x03$
多么熟悉的表达式,我来解释一下:
十六进制数2(也就是十进制的2了)出现在第一或第二或第三字节,中间任意字节,最后一个字节以3结尾。
注意这里我没有用字符,这里的字符指的就是单字节字符,用字节描述,是为了分析包方便。
(二)抓包验证
我们把QQ的抓包打开看一下
果然是第三字节0x02,最后一个字节0x03,所以QQ服务器的数据包被抓住了,登录不能成功,自然就用不了了。
(三)简单分析一下上图中QQ的登录过程
1、QQ客户端对多个服务器的TCP 80发起TCP连接请求
2、当其中一个服务器响应
3、客户端收到后,立即回应。完成三次握手
4、客户端立即向握手的服务器发起特制的HTTP请求
这一个请求,如上图所示,符合特征码,就被拦截。
5、又有一个服务器响应到达
6、客户端立即返回对这个服务器的响应。完成三次握手
7、客户端再次向新握手的服务器发起特制HTTP请求,又被特征码匹配拦截。
QQ客户端就反复尝试,直到超时,只好报告客户端无法登陆
如果再深入的了解L7-filter,甚至可以自己编写特征码,来扩展对其他应用层程序的控制。但前提是要抓包分析各种软件的通讯协议,而且像QQ这种软件还在变化。
通过两篇博文,简单的阐述了Netfilter/IPTables框架在多种案例中的应用,通过抓包分析,简单的分析了其外在表现,并没有从内部剖析、深入分析其实现,但是只有掌握其内在原理才能真正用好防火墙,否则使用这把双刃剑可能会伤着自己。