一、iptables补充与回顾
1、iptables修改链接跟踪表最大容量大小的方式
iptables的链接跟踪表最大容量为/proc/sys/net/ipv4/ip_conntrack_max(有的地方可能叫nf_conntrack_max),链接碰到各种状态的超时后就会从表中删除。
所以解決方法一般有两个:
(1)、加大 ip_conntrack_max 值
vi /etc/sysctl.conf net.ipv4.ip_conntrack_max = 393216 net.ipv4.netfilter.ip_conntrack_max = 393216
(2)、降低 ip_conntrack timeout时间
vi /etc/sysctl.conf net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120
iptables -t nat -L -n
2、iptables练习
练习:INPUT和OUTPUT默认策略为DROP;
1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机;
2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.16.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个;
3、开放本机的ssh服务给172.16.x.1-172.16.x.100中的主机,x为你的座位号,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机;
4、拒绝TCP标志位全部为1及全部为0的报文访问本机;
5、允许本机ping别的主机;但不开放别的主机ping本机;
练习:判断下述规则的意义:
# iptables -N clean_in(自定义规则链) # iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP # iptables -A clean_in -d 172.16.255.255 -p icmp -j DROP # iptables -A clean_in -p tcp ! --syn -m state --state NEW -j DROP(拒绝非法(可能是别人经过巧妙伪装的视图发起攻击的)报文) # iptables -A clean_in -p tcp --tcp-flags ALL ALL -j DROP # iptables -A clean_in -p tcp --tcp-flags ALL NONE -j DROP # iptables -A clean_in -d 172.16.100.7 -j RETURN (调用自定义规则链并从自定义规则链中返回的) # iptables -A INPUT -d 172.16.100.7 -j clean_in # iptables -A INPUT -i lo -j ACCEPT # iptables -A OUTPUT -o lo -j ACCEPT # iptables -A INPUT -i eth0 -m multiport -p tcp --dports 53,113,135,137,139,445 -j DROP # iptables -A INPUT -i eth0 -m multiport -p udp --dports 53,113,135,137,139,445 -j DROP # iptables -A INPUT -i eth0 -p udp --dport 1026 -j DROP # iptables -A INPUT -i eth0 -m multiport -p tcp --dports 1433,4899 -j DROP # iptables -A INPUT -p icmp -m limit --limit 10/second -j ACCEPT
3、课外扩展
recent模块
补充:利用iptables的recent模块来抵御DOS攻击: 22,建立一个列表,保存有所有访问过指定的服务的客户端IP;
recent模块能够实现对于某一个服务的请求频率满足以后做后续拒绝一段时间访问的;
ssh: 远程连接:
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSH Attach: "
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP
1.利用connlimit模块将单IP的并发设置为3;会误杀使用NAT上网的用户,可以根据实际情况增大该值;
2.利用recent和state模块限制单IP在300s内只能与本机建立2个新连接。被限制五分钟后即可恢复访问。
下面对最后两句做一个说明:
1.第二句是记录访问tcp 22端口的新连接,记录名称为SSH
--set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。
--update 是指每次建立连接都更新列表;
--seconds必须与--rcheck或者--update同时使用
--hitcount必须与--rcheck或者--update同时使用
3.iptables的记录:/proc/net/xt_recent/SSH
也可以使用下面的这句记录日志:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSH Attack"
4、iptables实现七层访问过滤
(学习向内核打补丁编译使用)
iptables直接访问应用层协议,根据应用层协议做控制,比如访问http协议没有问题,但是访问ftp协议就拒绝。再比如qq协议就拒绝。
模块:layer7
用于识别应用层协议;
注意:layer7是一个扩展,不过这个扩展iptables没有自带,所以要想实现七层访问过滤,得为iptables补上layer7这一模块,而layer7模块需要内核的netfilter框架的支持也需要用户空间iptables命令在写规则能支持,所以如果我们要想使用layer7,第一,得对内核打补丁,重新编译升级内核;第二,得对iptables打补丁,重新编译升级iptables。layer7提供的补丁包只适用于较老版本的内核和较老版本的iptables,所以从互联网上直接下载的补丁包用起来可能会有一定的问题。
iptables/netfilter
iptables -m state,
netfilter state
对内核中的netfilter,打补丁layer7,重新编译内核
对iptables打补丁,补上layer7模块,重新iptables
diff/patch:文本操作工具
diff是Unix系统的一个很重要的工具程序。它用来比较两个文本文件的差异,是代码版本管理的核心工具之一。其用法非常简单:
diff <变动前的文件> <变动后的文件>
由于历史原因,diff有三种格式:
* 正常格式(normal diff)
* 上下文格式(context diff)
* 合并格式(unified diff)
1、正常格式的diff
例如,对file1(变动前的文件)和file2(变动后的文件)进行比较可使用如下命令:
diff file1 file2
显示结果中,第一行是一个提示,用来说明变动位置。它分成三个部分:前面的数字,表示file1的第n行有变化;中间的"c"表示变动的模式是内容改变(change),其他模式还有"增加"(a,代表addition)和"删除"(d,代表deletion);
2、上下文格式的diff
上个世纪80年代初,加州大学伯克利分校推出BSD版本的Unix时,觉得diff的显示结果太简单,最好加入上下文,便于了解发生的变动。因此,推出了上下文格式的diff。它的使用方法是加入-c选项(即context)。
diff -c f1 f2
结果分成四个部分。第一部分的两行,显示两个文件的基本情况:文件名和时间信息,"***"表示变动前的文件,"---"表示变动后的文件。第二部分是15个星号,将文件的基本情况与变动内容分割开。第三部分显示变动前的文件,即file1。
另外,文件内容的每一行最前面,还有一个标记位。如果为空,表示该行无变化;如果是感叹号(!),表示该行有改动;如果是减号(-),表示该行被删除;如果是加号(+),表示该行为新增。
第四部分显示变动后的文件,即file2。
3、合并格式的diff
如果两个文件相似度很高,那么上下文格式的diff,将显示大量重复的内容,很浪费空间。1990年,GNU diff率先推出了"合并格式"的diff,将f1和f2的上下文合并在一起显示。
它的使用方法是加入u参数(代表unified)。
diff -u f1 f2
其结果的第一部分,也是文件的基本信息。"---"表示变动前的文件,"+++"表示变动后的文件。第二部分,变动的位置用两个@作为起首和结束。第三部分是变动的具体内容。
除了有变动的那些行以外,也是上下文各显示3行。它将两个文件的上下文,合并显示在一起,所以叫做"合并格式"。每一行最前面的标志位,空表示无变动,减号表示第一个文件删除的行,加号表示第二个文件新增的行。
diff
-u
patch
尽管并没有指定patch和diff的关系,但通常patch都使用diff的结果来完成打补丁的工作,这和patch本身支持多种diff输出文件格式有很大关系。patch通过读入patch命令文件(可以从标准输入),对目标文件进行修改。通常先用diff命令比较新老版本,patch命令文件则采用diff的输出文件,从而保持原版本与新版本一致。
patch的标准格式为
patch [options] [originalfile] [patchfile]
如果patchfile为空则从标准输入读取patchfile内容;如果originalfile也为空,则从patchfile(肯定来自标准输入)中读取需要打补丁的文件名。因此,如果需要修改的是目录,一般都必须在patchfile中记录目录下的各个文件名。绝大多数情况下,patch都用以下这种简单的方式使用:
patch命令可以忽略文件中的冗余信息,从中取出diff的格式以及所需要patch的文件名,文件名按照diff参数中的"源文件"、"目标文件"以及冗余信息中的"Index:"行中所指定的文件的顺序来决定。
-p参数决定了是否使用读出的源文件名的前缀目录信息,不提供-p参数,则忽略所有目录信息,-p0(或者-p 0)表示使用全部的路径信息,-p1将忽略第一个"/"以前的目录,依此类推。如/usr/src/linux-2.4.15/Makefile这样的文件名,在提供-p3参数时将使用linux-2.4.15/Makefile作为所要patch的文件。
patch
-p
-R
mockbuild
总结:操作步骤
1、获取并编译内核
# useradd mockbuild # rpm -ivh kernel-2.6.32-431.5.1.x86_64.el6.src.rpm # cd rpmbuild/SOURCES # tar linux-2.6.32-*.tar.gz -C /usr/src
# cd /usr/src # ln -sv
2、给内核打补丁
# tar xf netfilter-layer7-v2.23.tar.bz2 # cd /usr/src/linux # patch -p1 < /root/netfilter-layer7-v2.23/kernel-2.6.32-layer7-2.23.patch # cp /boot/config-* .config # make menuconfig
按如下步骤启用layer7模块
Networking support → Networking Options →Network packet filtering framework → Core Netfilter Configuration
<M> “layer7” match support
3、编译并安装内核
# make
# make modules_install
# make install
4、重启系统,启用新内核
5、编译iptables
# tar xf iptables-1.4.20.tar.gz
# cp /root/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/* /root/iptables-1.4.20/extensions/
# cp /etc/rc.d/init.d/iptales /root
# cp /etc/sysconfig/iptables-config /root
# rpm -e iptables iptables-ipv6 --nodeps
# ./configure --prefix=/usr --with-ksource=/usr/src/linux
# make && make install
# cp /root/iptables /etc/rc.d/init.d
# cp /root/iptables-config /etc/sysconfig
6、为layer7模块提供其所识别的协议的特征码
# tar zxvf l7-protocols-2009-05-28.tar.gz # cd l7-protocols-2009-05-28 # make install
7、如何使用layer7模块
ACCT的功能已经可以在内核参数中按需启用或禁用。此参数需要装载nf_conntrack模块后方能生效。
net.netfilter.nf_conntrack_acct = 1
l7-filter uses the standard iptables extension syntax
# iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j [action]
# iptables -A FORWARD -m layer7 --l7proto qq -j REJECT
编译内核:
make menuconfig
make -j #
make modules_install
make install
清理内核源码树:
提示:xt_layer7.ko依赖于nf_conntrack.ko模块
二、tcp_wrapper
tcp_wrapper:tcp包装器
是一个类似于iptables的实现访问控制工具。但是,只是对基于TCP协议开发并提供服务的应用程序,提供的一层访问控制工具;
iptables是工作在内核中的,所以只要是一个网络服务经由经由内核中的TCP/IP协议栈就能够收到netfilter的控制,那tcp_wrapper也需要在用户请求的报文所必经的路上实现对于某个服务的访问控制的功能,但是tcp_wrapper不像netfilter是在内核中实现而是基于库调用来实现其功能的。这就意味着只有那些在开发时不光是TCP协议还必须是基于TCP协议开发提供服务并且在开发时调用了tcp_wrapper相关库的(这个库叫libwrap)的应用tcp_wrapper的应用才能生效。
很显然,tcp_wrapper比起netfilter的适用范围要窄的多了,那我们怎么知道哪一个应用程序调用了tcp_wrapper并且支持对于tcp_wrapper进行控制呢?
判断服务是否能够由tcp_wrapper进行访问控制:
此前说过,一个程序在开发时如果调用了某个接口,但是它在编译时却有两种方式编译,第一,动态编译,第二,静态编译。动态编译表示基于动态链接库的方式使用库,静态编译表示把调用的库文件直接编译进应用程序内部,所以这有两种情形,它的判断方式不一样:
- (1) 动态编译:ldd命令(ldd命令显示出链接至libwrap即可);
- (2) 静态编译:strings命令查看应用程序文件,其结果中如果出现下述两个文件:
- hosts.allow
- hosts.deny
则表示支持tcp_wrapper控制,否则则表示不支持;
由此,我们看看系统上有哪些应用程序能够支持这样的访问控制机制,以CentOS 7为例:
先清空iptables规则:
查看sshd是否支持tcp_wrapper规则:
说明它是接受tcp_wrapper控制的。
再看httpd:
未链接至libwrap库,说明httpd不接受tcp_wrapper控制。
再看vsftpd:
因此它接受tcp_wrapper控制
通过这种方式查看的结果当中,但凡那些链接当中出现了libwrapper的才表示它能够受tcp_wrapper控制。
那么如果收tcp_wrapper控制,我们如何实现基于tcp_wrapper对服务做访问控制呢?其实tcp_wrapper比iptables要简单太多了,非常容易实现。
要想实现服务访问控制,它是通过在配置文件中为各服务分别定义访问控制规则实现访问控制:
配置文件:
- /etc/hosts.allow
- /etc/hosts.deny
所以我们写在allow或deny文件中就能实现某个服务能够允许能够有哪些客户端主机进行访问了,在此直接定义即可。
配置文件语法:
daemon_list(指定是哪一个服务,可以是单个服务也可以是服务列表,若有多个使用逗号隔开):client_list(允许或拒绝哪些客户端主机)[:options(其它选项)](此项如果写在allow文件中表示允许,写在deny文件中表示拒绝,仅此而已)
如果在两个文件中写了同一个条目,事实上,这两个文件有其检查次序的概念的。首先我们检查hosts.allow,其次才是hosts.deny,也就是说当一个客户端来访问某个服务时,先检查在allow文件中是否有与之匹配的规则,如果有匹配的规则,就允许访问即放行。如果allow文件中没有,则检查deny文件,如果deny文件中有匹配的,则拒绝访问,如果hosts.deny也没有匹配的,那就要取决于默认策略了。
流程大致如下图所示:
所以说如果我们仅放行某一个网络对服务访问,怎么办呢?在allow中allow这个网络,在deny中deny all即可。所以这就是为什么当前主机上这么多受libwrap控制的服务默认都没有拒绝的原因,因为在这两个文件中什么都没有定义。默认情况下这两个文件是空的。那两个文件是空的就意味着我们的服务即便是受tcp_wrapper控制它也是被允许的,因为第一个文件匹配第二个文件也没匹配,那默认是allow的。
可以看出,上述文件默认都是注释的,即规则为空。
接下来,我们就来试试让它们来控制服务的访问了。
我们先来说一说我们怎么在配置文件中去写这些规则,也就是说我们给出daemon_list规则的格式是什么。
daemon_list格式:
- 应用程序的文件名称,而非服务名
一定是应用程序的文件的名字,因为我们说过它是文件通过链接至libwrap库文件来完成访问控制的,所以说应用程序列表中的应用程序给的必须是文件名而不能是服务名,比如我们要控制named,应用程序叫named而不能写成DNS;
- 应用程序文件名称列表,彼此之间使用逗号分隔
例如:想要vsftpd和ssh基于同样法则控制
编写格式为:sshd,vsftpd;
ALL表示所有受tcp_wrapper控制的应用程序服务;
client_list格式:
- IP地址;表示单个主机;
- 主机名;表示单个主机;
- 网络地址;必须使用完整格式的掩码,不能使用前缀格式掩码,所以类似于172.16.0.0/16不合法;表示此网络中的所有主机;
- 简短格式的网络地址;我们在讲到httpd的allow、from时说过172.16网络可以使用172.16表示,不过这不能那样写,因为最后那个点不能省略,例如:172.16.表示172.16.0.0/255.255.0.0;
- ALL;表示所有来源主机;
- KNOW;表示所有可以解析到的主机;
- UNKNOWN;表示所有无法解析的主机;
- PARANOID;(瘫痪、麻痹)表示主机名的正反解结果不匹配;
例如:
vsftpd服务不允许192.168.241.1访问:
注意:这不是一个服务,而是一个库,而库在应用程序自己运行时就可能会调用的库的,因此这也不用重启任何服务;
192.168.241.6这台主机上的ftp服务仅允许192.168.241.0网络访问的实现:
换一个主机测试:
但是对于telnet服务来说有些特殊:
telnet的服务叫做telnet-server:(在CentOS6上telnet是受超级守护进程控制的,因为超级守护进程是接受tcp_wrapper控制的,所以telnet也受tcp_wrapper控制,但在CentOS7上telnet是作为一个独立的进程的,不受tcp_wrapper控制了。因此此处在CentOS 6上实验)
启动telnet要先启动超级守护进程,但是在此之前需要先修改配置文件
它是受xinet.d控制的
改为disable no相当于checkconfig telnet on。
telnet只能使用普通用户登录,因此添加用户:
先在本地连接一下:
现在我们对telnet做访问控制:
安装的应用程序名叫in.telnetd。
在本地测试:
再找一台主机:
这就是如何使用tcp_wrapper来做访问控制的。
此外,在众多options中有一个特殊的应用,这种用法就是EXCEPT。
EXCEPT:意为除了;如在hosts.allow文件中定义:
vsftpd:172.16. EXCEPT 172.16.100.1
表示这个网络开放给172.16访问但是这个172.16.100.1不能访问。另一个例子:
vsftpd:172.16. EXCEPT 172.16.100.0/255.255.255.0 EXCEPT 172.16.100.1
表示vsftpd开放给172.16.这个网络,但是不包括172.16.100.0这个网络,但是又包含172.16.100.1这个主机。
如:
自行测试!
[:options]:
- deny:表示拒绝,主要用于host.allow文件中;在允许的文件中实现拒绝的功能;
- allow:表示允许,用于hosts.deny文件,实现allow的功能;
举例:
/etc/hosts.allow文件中:
vsftpd:192.168.241. :deny
再如,/etc/hosts.allow:
vsftpd:192.168.241. EXCEPT 192.168.241.6 :deny
表示匹配192.168.241.6之外的192.168.241.0网络中的主机都拒绝(注意:这里只是不包含192.168.241.6这个主机即未匹配到,这条规则能够匹配到192.168.241.0网络中的所有主机但是不包含192.168.241.6)。
/etc/hosts.deny:
vsftpd:ALL
(此处拒绝所有,所以刚才未匹配到的192.168.241.6也被拒绝了,最终的规则表示所有主机都不能访问)
- spawn:
表示启动额外应用程序;一旦被匹配到的话它可以启动,不做拒绝允许了,意思是你本来是拒绝的文件一样是拒绝,本来是允许的文件一样是允许,但额外它还可以启动其它应用程序。可以完成一部分的管理或其它功能。
如在定义某一个服务时,如果说不允许访问的主机访问了,或者允许访问的主机访问了,都可以将其记录到日志里边来。
举例:本地开放了ftp服务,但是不允许任何人访问,一旦有人访问了,将其记录到日志中:
%c表示client ip,客户端地址,%s表示server ip,服务器端地址,%d为daomon name即访问的是服务器上的哪个守护进程;
iptables到此就告一段落了,期望把iptables中的网络防火墙和nat规则当做重点,nat转换和地址转换后,哪些允许访问哪些不允许访问呢?所以还可以把filter和nat结合起来使用。所以应该把nat当做重点。