Linux防火墙iptables(二)
上一篇文章我们说了一些iptables/netfilter的基础知识,本文我们来介绍一下iptables的规则编写。Iptables的规则可以概括的分为两个方面:1、报文的匹配条件;2、匹配到后的处理动作。其中匹配条件分为基本匹配条件和扩展匹配条件,处理动作分为内建处理机制和自定义处理机制。这里需要注意的一点是,自定义处理机制(自定义链)不在内核中所以报文是不会经过自定义链的,它只能被内建机制引用即当做处理的子目标。
Iptables说白了就是一个规则管理工具,用于生成、检查和自动实现规则。规则和链都有自己的计数器,用于统计被匹配到的报文数。一般链上都有默认策略,默认的默认策略是允许所有,如果我们要阻挡某报文就定义阻止策略就可以,类似黑名单;也可以更改默认默认策略,改为拒绝所有,然后开放我们想要开放的内容,类似白名单。因为5个链工作在内核之上所以策略一旦启用将立即生效,但不会永久有效,想要永久有效需要写到配置文件之中。接下来我们看看iptables的命令结构:
iptables的基本语法格式:
iptables [-t 表名] 命令选项 [链名] [条件匹配] [-j 目标动作或跳转]
说明:表名、链名用于指定 iptables命令所操作的表和链(我们上篇博客中提到的四表五链),命令选项用于指定管理iptables规则的方式(比如:插入、增加、删除、查看等;条件匹配用于指定对符合什么样 条件的数据包进行处理;目标动作或跳转用于指定数据包的处理方式(比如允许通过、拒绝、丢弃、跳转(Jump)给其它链处理。
iptables命令的管理控制选项:
-A 在指定链的末尾添加(append)一条新的规则
-D 删除(delete)指定链中的某一条规则,可以按规则序号和内容删除
-I 在指定链中插入(insert)一条新的规则,默认在第一行添加
-R 修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换
-L 列出(list)指定链中所有的规则进行查看
-E 重命名用户定义的链,不改变链本身
-F 清空(flush)
-N 新建(new-chain)一条用户自己定义的规则链
-X 删除指定表中用户自定义的规则链(delete-chain)
-P 设置指定链的默认策略(policy)
-Z 将所有表的所有链的字节和数据包计数器清零
-n 使用数字形式(numeric)显示输出结果
-v 查看规则表详细信息(verbose)的信息
-V 查看版本(version)
-h 获取帮助(help)
防火墙处理数据包的四种方式:
ACCEPT 允许数据包通过
DROP 直接丢弃数据包,不给任何回应信息
REJECT 拒绝数据包通过,必要时会给数据发送端一个响应的信息。
LOG在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则
上文也提到iptables写的规则无法永久生效,以下两种方法可以解决这个问题:
iptables-save > /etc/sysconfig/iptables
service iptables save
它能把规则自动保存在/etc/sysconfig/iptables中。
当计算机启动时,rc.d下的脚本将用命令iptables-restore调用这个文件,从而就自动恢复了规则。
接下来我们看通过一些具体案例深入了解一下iptables的使用:
-L:list,列出指定链上的所有规则;
-n: numeric,以数字格式显示地址和端口号,即不反解;
-v: verbose,详细格式,显示规则的详细信息,包括规则计数器等;
-vv:
-vvv:
--line-numbers: 显示规则编号;
-x: exactly,显示计数器的精确值
pkts bytes target prot opt in out source destination
pkts: 被本规则所匹配到的包个数;
bytes:被本规则所匹配到的所包的大小之和;
target: 处理目标 (目标可以为用户自定义的链)
prot: 协议 {tcp, udp, icmp}
opt: 可选项
in: 数据包流入接口
out: 数据包流出接口
source: 源地址
destination: 目标地址;
在规则匹配中分为:
通用匹配
[!] -s, --src, --source IP|Network:检查报文中的源IP地址;叹号表示取反,以下几个都可以使用
-d, --dst, --destination:检查报文中的目标IP地址;
-p, --protocol:检查报文中的协议,即ip首部中的protocols所标识的协议;tcp、udp或icmp三者之一;
-i, --in-interface:数据报文的流入接口;通常只用于PREROUTING, INPUT, FORWARD链上的规则;
-o, --out-interface:检查报文的流出接口;通常只用于FORWARD, OUTPUT, POSTROUTING链上的规则;
扩展匹配:使用iptables模块实现的进一步检查
隐式扩展:就是在通用匹配的基础上使用-p指定了协议类型,则-m选项指明模块就可以省略
tcp:
--dport PORT[-PORT] #可以指定连续端口,但不能指定离散端口,UDP也一样
--sport
--tcp-flags LIST1 LIST2
LIST1: 要检查的标志位;
LIST2:在LIST1中出现过的,且必须为1标记位;而余下的则必须为0;
例如:--tcp-flags syn,ack,fin,rst syn
--syn:用于匹配tcp会话三次握手的第一次;
udp:
--sport
--dport
icmp:
--icmp-types
8: echo request
0:echo reply
[root@bogon ~]# iptables -I INPUT 1 -s 192.168.1.103 -d 192.168.1.109 -p tcp -m tcp --dport 80 -j DROP #这里的-m tcp可以省略所以就叫做隐式扩展
[root@bogon ~]# iptables -I INPUT 1 -s 192.168.1.103 -d 192.168.1.109 -p tcp --dport 22 -j ACCEPT
显式扩展:必须使用-m指明了扩展模块,使用rpm -ql iptables查看到的诸如/lib64/xtables/libxt_iprange.so的模块完成的功能
multiport: 多个离散端口的同时匹配;--dports, --sports, --ports,最多同时指定15个端口
iprange:地址范围的匹配(不适于写为网络地址);--src-range, --dst-range
string: 字符串匹配;--string, --algo {kmp|bm}, --hex-string "HEX_STRING":HEX_STRING为编码成16进制格式的字串;#algorithms是算法的意思,kmp|bm是两种编码算法
time: 基于时间进行匹配;--datestart, --datestop, --timestart, --timestop, --weekdays
connlimit: 做连接数限制,对每IP能够发起并发连接数作匹配;--limit-above
limit: 做速率匹配,令牌桶算法;--limit, --limit-burst#空闲突发访问量的限制
这是我对以上几种扩展的演示结果,大家看看能否从中看出对应的iptables命令是什么呢。
附ICMP类型表:
在讲接下来的扩展匹配条件之前我们有必要说一下TCP的有限状态机,有限状态机是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
以上这三幅图已经详细的描述了TCP三次握手和四次挥手以及有限状态机,我就不再进行解释了。我们知道IP协议是无状态的,当有很多个IP与我们的主机连接时我们如何判断某个连接来自哪个IP呢?这就需要netfilter在内存中保存一张表记录跟踪了每个连接的信息,不过这个空间如果被打满那么之后的请求就会被拒绝,所以高并发的时候慎用。
connection template:连接追踪模板,用于记录各连接及相关状态;基于IP实现,与是否为TCP协议无关;通过倒计时的方式删除条目;
记录连接的状态:
NEW: 新建立的连接,连接追踪模板中无相应的条目时,客户端第一次发出的请求;
ESTABLISHED:NEW状态之后,边距追踪模板中的条目删除之前所进行的通信过程,都称为ESTABLISHED;
RELATED:相关联的连接,如ftp协议的命令连接与数据连接即为相关联的连接;
INVALIED: 无法识别的状态;
我们说了这么多的原理,是为了说明iptables中state扩展的,这个扩展有一个大大用处就是阻止反弹式木马,反弹式木马是什么大家可以自行去了解,我们简单的说一下就是它可以从主机防火墙某个以开放的监听端口当做Client端口去连接远程主机以实现控制被攻陷的肉鸡。比如80端口的出去的连接必须是对Client请求的响应而不能是NEW连接。
这个是我使用state模块完成的功能:能够使用ssh登录和yum功能的网络epel源,开放http、https、ftp服务(被动连接,需要安装一个ftp模块)。就这几个启用连接追踪功能,带状态检测的包过滤防火墙就完成了一大堆功能。
好了我们的filter表就说到这里了,接下来我们说一下nat表。NAT叫做网络地址转换,说白了就是把IP首部中的原地址或者目标地址更改一下以达到通往目的地的效果。早期发明NAT是为了在网络中隐藏自己真实的IP,以实现一定的安全保护功能,后来当IPv4地址耗尽时,无心插柳,解决了IPv4地址紧缺的问题。NAT大致分为四种情况:源地址转换、目标地址转换、端口转换,全地址转换。
源地址转换:将内网地址通过NAT Server转换为公网地址访问互联网
目标地址转换:将互联网访问NAT Server的公网地址转换内部Server的私有地址
端口转换:在目标地址转换的基础上将互联网访问NAT Server的端口转换成内部Server真正监听的端口
全地址转换:就是同时做源地址和目标地址转换,类似于代理服务器,但与之又不相同。
上面的拓扑图中192.168.1.0/24网段是外网地址,192.168.80.0/24网段是内网地址。
源地址转换测试:
目标地址转换测试:
如果我们的NAT Server的外网IP是自动获取的那么可以使用[root@web2 ~]# iptables -t nat -R POSTROUTING 1 -s 192.168.80/24 -j MASQUERADE 地址伪装功能自动识别应该转换成哪个地址;如果我们的Web Server监听的端口为8080,那么可以使用[root@web2 ~]# iptables -t nat -R PREROUTING 1 -d 192.168.1.108 -p tcp --dport 80 -j DNAT --to-destination 192.168.80.130:8080 直接在目标IP上添加端口就可以了。
OK,我们的iptables/netfilter的基础应用就说到这里了,iptables主要是工作在网络层,那么在linux中还有有个叫tcp_wrapper的控制工具组件,它他利用一些tcp_wrapper的库完成在传输层对数据的过滤,有兴趣的朋友可以去了解一些,我就不再过多的介绍了。如有错误敬请指正。
练习:INPUT和OUTPUT默认策略为DROP;
Watch –n1 “iptables –L –n –v” #随时观察变化
关闭NetManager
##iptables -t filter -P INPUT DROP
##iptables -P OUTPUT DROP
1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机;
##iptables -A INPUT -d 192.168.19.134 -p tcp --dport 80 -m time ! --weekdays Mon -m limit --limit 100/second -j ACCEPT
##iptables -I OUTPUT 2 -s 192.168.19.134 -p tcp --sport 80 -m string --string "admin" --algo kmp -j REJECT
##iptables -R OUTPUT 1 -s 192.168.19.134 -m state --state ESTABLISHED,RELATED -j ACCEPT
2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.16.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个;
##iptables -A INPUT -d 192.168.19.134 -p tcp --dport 21 -m time --timestart 08:30 --timestop 18:00 -m limit --limit 5/minute -j ACCEPT
3、开放本机的ssh服务给172.16.x.1-172.16.x.100中的主机,x为你的座位号,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机;
##iptables -I INPUT 1 -d 192.168.19.134 -p tcp --dport 22 -m iprange --src-range 192.168.19.100-192.168.19.200 -j ACCEPT#这个是错的
4、拒绝TCP标志位全部为1及全部为0的报文访问本机;
##iptables -I INPUT 1 -p tcp --tcp-flags all all -j REJECT
##iptables -I INPUT 1 -p tcp --tcp-flags all none -j REJECT
5、允许本机ping别的主机;但不开放别的主机ping本机;
##iptables -I OUTPUT 1 -s 192.168.19.134 -p icmp --icmp-type 8 -j ACCEPT
##iptables -I INPUT 1 -d 192.168.19.134 -p icmp --icmp-type 0 -j ACCEPT
Tcp_wrapper:
tcp_wrapper:tcp包装器,tcp库
(1) 访问控制工具组件;
(2) 仅对使用tcp协议且在开发时调用了libwrap相关库的服务程序有效;
判断服务是否能够由tcp_wrapper进行访问控制:
(2) 静态编译:strings命令查看其结果中是否包含
hosts.allow
hosts.deny
tcp_wrapper通过读取配置文件中的访问控制规则来判断某服务是否可被访问
hosts.allow
hosts.deny
先匹配allow,再匹配deny,如果都没有默认放行
配置文件语法:
daemon_list: client_list [:options]
daemon_list:
应用程序的文件名称,而非服务名;
应用程序的文件列表,使用逗号分隔;
例如:vsftpd, in.telnetd: 172.16.0.0/255.255.0.0
ALL: 所有受tcp_wrapper控制的应用程序;
client_list:
IP地址;
主机名;
网络地址:必须使用完整格式掩码,不能使用长度格式的掩码;所以172.16.0.0/16是不合法的;
简短格式的网络地址:172.16.表示172.16.0.0/255.255.0.0
ALL: 所有客户端地址;
KNOWN: 所有已知的主机,主机名能被解析
UNKNOWN:主机名不能被解析
PARANOID: 正反解不匹配的
特殊的变量:EXCEPT
in.telnetd: 172.16. EXCEPT 172.16.100.3
[:options]
deny: 用于在hosts.allow文件中实现拒绝访问的规则
allow:用于在hosts.deny文件中实现允许访问的规则
spawn: 启动一个额外程序;
in.telnetd: ALL: spawn /bin/echo `date` login attempt from %c to %s, %d >> /var/log/telnet.log
练习:控制vsftpd仅允许172.16.0.0/255.255.0.0网络中的主机访问,但172.16.100.3除外;对所被被拒绝的访问尝试都记录在/var/log/tcp_wrapper.log日志文件中;
hosts.allow:
vsftpd: 172.16. EXCEPT 172.16.100.3
hosts.deny:
vsftpd: ALL : spawn /bin/echo