前言
防火墙,就是用于实现访问控制的功能的,它分为硬件的和软件的防火墙两种。无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作,这就是防火墙的策略-规则,以达到让它对出入网络的IP
、数据进行检测。
目前市面上比较常见的有3、4层的防火墙,叫网络层的防火墙,还有7层的防火墙,其实是代理层的网关。
对于TCP/IP
的七层模型来讲,我们知道第三层是网络层,三层的防火墙会在这层对源地址和目标地址进行检测。但是对于七层的防火墙,不管你源端口或者目标端口,源地址或者目标地址是什么,都将对你所有的内容进行检查。所以,对于设计原理来讲,七层防火墙更加安全,但是这却带来了效率更低。所以市面上通常的防火墙方案,都是两者结合的。而又由于我们都需要从防火墙所控制的这个口来访问,所以防火墙的工作效率就成了用户能够访问数据多少的一个最重要的控制,配置的不好甚至有可能成为流量的瓶颈。
netfilter
与iptables
Netfilter
是由Rusty Russell
提出的Linux 2.4
内核防火墙框架,该框架既简洁又灵活,可实现安全策略应用中的许多功能,如数据包过滤、数据包处理、地址伪装、透明代理、动态网络地址转换,以及基于用户及媒体MAC
地址的过滤和基于状态的过滤、包速率限制等。iptables
是为用户提供的Netfilter
管理工具,用于实现对内核中网络防火墙的管理
防火墙策略
防火墙策略一般分为两种,一种叫通
策略,一种叫堵
策略。通策略,默认门是关着的,必须要定义谁能进;堵策略则是,大门是洞开的,但是你必须有身份认证,否则不能进。所以我们要定义,让进来的进来,让出去的出去,所以通,是要全通,而堵,则是要选择。当我们定义的策略的时候,要分别定义多条功能。其中:定义数据包中允许或者不允许的策略,filter
过滤的功能,而定义地址转换的功能的则是nat
选项。为了让这些功能交替工作,我们制定出了表
这个定义,来定义、区分各种不同的工作功能和处理方式。
表(Table)
描述了iptables
功能的大类,如包过滤或网络地址转换(NAT)。共定义了5个表。
- raw 用于配置数据包,raw中的数据包不会被系统跟踪
- filter(过滤)用于过滤本机流入、流出的数据包。是
iptables
默认使用的表。 - nat(网络地址转换)用于五元组的转换
- mangle(变更)主要用于修改数据包中的路由标记。如
TTL
TOS
MARK
等。 - security用于强制访问控制网络规则(例如: SELinux – 详细信息参考 该文章)
大部分情况仅需要使用filter
和nat
iptables
是工作在用户空间的,它可以让规则进行生效的,本身不是一种服务,而且规则是立即生效的。而我们iptables
现在被做成了一个服务,可以进行启动,停止的。启动,则将规则直接生效,停止,则将规则撤销。iptables
还支持自己定义链。但是自己定义的链,必须是跟某种特定的链关联起来的。
注意:规则的次序非常关键,检查规则的时候,是按照从上往下的方式进行检查,如果匹配到对应规则,则执行动作,不再往下匹配。
链(Chain)
每个表都有自己的一组内置链,用户还可以自定义链,这样用户就可以建立一组规则,它们都关联都一个共同的标签如MYCHAIN
。默认定义了五个链
PREROUTING
路由前,数据包进入本机,进入路由表之前INPUT
数据包通过路由表后,目的地为本机FORWARD
数据包通过路由表后,目的地不为本机OUTPUT
由本机发出的数据包POSTROUTING
数据包通过路由表后,发送至网卡前
表跟链的关系图
详细的数据包流经图

只关注filter
和nat
表的数据包流经图
语法格式
iptables [-t 表]
<命令> -<A I R P D L Z F N E X>
[链]
[规则号码]
[匹配条件]
[-j 匹配后的动作]
拒绝来自192.168.2.0/24
的icmp
包
1 | iptables -t filter -A INPUT -s 192.168.2.0/24 -p icmp -j DROP |
详解命令
查看管理命令-L
附加子命令
- -t 接表名,如果不加-t,默认是-t filter
- -n 以数字的方式显示ip port
- -v 显示详细信息
- -x 在计数器上显示精确值,不做单位换算
- –line-numbers 显示规则的行号
查看 filter 表所有规则
1 | iptables -vnL # 等价于iptables -t filter -vnL |
查看nat表所有规则
1 | iptables -t nat -vnL |
查看filter表的INPUT链规则
1 | iptables -vnL INPUT |
查看 filter 表所有规则并显示行号
1 | iptables -vnL --line-numbers |
链管理命令(这都是立即生效的)
-P 设置默认策略
当数据包不在我们设置的规则之内时,则该数据包的通过与否,是以策略的设置为准。
默认策略一般只有两种:
1 | iptables -P INPUT <DROP|ACCEPT> |
这就把默认规则给拒绝了。并且没有定义哪个动作,所以远程连接ssh
都被拒绝了。
-F 清空规则链的(注意每个链的管理权限)
1 | iptables -F # 清空 filter 表的所有链 |
-N 新建自定义链
1 | iptables -N MYCHAIN |
-E 给用户自定义的链重命名
1 | iptables -E MYCHAIN MYNEWCHAIN |
-X 用于删除自定义的空链,但是在删除之前必须要将里面的链给清空了
1 | iptables -X MYNEWCHAIN |
-Z 清空链,及链中默认规则的计数器的(有两个计数器,被匹配到的数据包数、字节数,使用iptales -vnL
查看)
1 | iptables -Z # 默认只清空 filter 链 |
规则管理命令
-A chain 追加,在当前链的最后新增一个规则
1 | iptables -A INPUT -p tcp --dport 80 -j ACCEPT |
-I chain [num]: 插入,把当前规则插入为第几条,默认第一条
1 | iptables -I INPUT -p tcp --dport 80 -j DROP |
-R chain num:Replays替换/修改第几条规则
1 | iptables -R INPUT 1 -p tcp --dport 81 -j DROP |
-D chain num:删除,指定删除第几条规则
1 | iptables -t filter -D INPUT 1 |
匹配
每个iptables
规则都包含一组匹配以及一个目标,后者告诉iptables
对于符合规则的数据包应该采取什么动作。iptables
匹配指的是数据包必须匹配的条件,只有当数据包满足所有的匹配条件时,iptables
才能根据由该规则的目标所指定的动作来处理该数据包。
每个匹配都在iptables
命令行中指定。常用的iptables
匹配如下:
通用匹配(地址/协议/匹配等)
- -s(–source) 匹配源地址或网络,这里不能指定主机名称,必须是 IP|IP/MASK|0.0.0.0/0.0.0.0,地址可以取反,加一个
!
- -d(–destination) 匹配目标地址或网络
- -p(–protocol) 匹配上层协议(TCP/UDP/ICMP/ALL)
- -i(–in-interface) 匹配流入接口,一般用在
INPUT
和PREROUTING
上 - -o(–out-interface) 流出接口,一般在
OUTPUT
和POSTROUTING
上 - -f(–fragment) 匹配 分片的包的第二片或及以后的部分
扩展匹配
隐含扩展:对协议的扩展
- tcp
- udp
- icmp
- all
TCP协议的扩展(-p tcp)
–sport(–source-port)、–dport(–destination-port)
指定端口,不能指定多个非连续端口,只能指定单个端口或多个连续的端口。不指定此项,则默认所有端口。
从80
到90
目的端口全部DROP
iptables -A INPUT -p tcp --dport 80:90 -j DROP
从0
到80
的所有目的端口端口全部DROP
iptables -A INPUT -p tcp --dport :80 -j DROP
从80
到65535
的所有目的端口全部DROP
iptables -A INPUT -p tcp --dport 80: -j DROP
–tcp-flags
TCP的标志位(SYN
ACK
FIN
PSH
RST
URG
)
匹配SYN
标记被设置而FIN
和ACK
标记没有设置的包
iptables -p tcp --tcp-flags SYN,FIN,ACK SYN -j ACCEPT
匹配所有标记都未置的包
iptables -p tcp --tcp-flags ALL NONE -j DROP
–syn
匹配SYN
标记被设置而ACK
和RST
标记没有设置的包,等同于下命令
iptables -p tcp --tcp-flags SYN,RST,ACK SYN
–tcp-option
根据选项匹配包
UDP协议的扩展(-p udp)
–dport –sport
与tcp
一样
icmp数据报文的扩展(-p icmp)
–icmp-type
根据ICMP类型匹配包
echo-request
(请求数据包)一般用8
来表示
echo-reply
(响应数据包)一般用0
来表示
显式扩展(-m)
state 按包状态匹配
- NEW: 第一次握手,我们就叫 NEW 连接,有别于 tcp 的 syn
- ESTABLISHED: 第二次握手完成的 ack 都为1,这是正常的数据传输,和 tcp 的第二次第三次握手,为已建立的连接
- INVALID: 不能被识别属于哪个连接或没有任何状态,例如:SYN=1 ACK=1 RST=1,对于这种数据包是无法识别的,都称之为
INVALID
无法识别的 - RELATED: 正在建立一个新的连接,这个连接是和一个已建立的连接相关的,例如:FTP这种古老的拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为RELATED
格式
1 | -m state --state 状态 |
示例
1 | iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT |
比如进来的只允许状态为NEW
和ESTABLISHED
的进来,出去只允许ESTABLISHED
状态的出去,这就可以将比较常见的反弹式木马有很好的控制。
mac 按源mac
匹配
1 | iptables -A INPUT -m mac --mac-source 00:0c:29:a7:bb:99 -j DROP |
limit 按包速率匹配
格式
单位时间连接控制,使用/second
/minute
/hour
/day
等单位为后缀,默认是3/hour
--limit RATE
间的连接的并发连接控制,默认为5
--limit-burst N
示例
限制目的ip为192.168.2.201
每秒3个包
1 | iptables -A INPUT -d 192.168.2.201 -m limit --limit 3/s -j ACCEPT |
limit
英语上看是限制的意思,但实际上只是按一定速率去匹配而已,要想限制的话后面要再跟一条DROP
iprange IP地址范围匹配
格式
-m iprange [!] <--src-range|--dst-range> IPADDR-IPADDR
来自从 192.168.2.202 到 192.168.2.220 的 tcp 包全部DROP
iptables -A INPUT -p tcp -m iprange --src-range 192.168.2.202-192.168.2.220 -j DROP
multiport 多端口匹配
用来匹配多个不连续的端口,最多能够匹配 15 个不连续的源端口。必须与-p
参数一起使用。
格式
1 | -m multiport [!] <--sports|--dports|--ports> port1[,port2,..,portn] |
拒绝 tcp 目的端口为80
和90
1 | iptables -A INPUT -p tcp -m multiport --dports 80,90 -j DROP |
TTL 匹配
根据 IP 头里的 TTL (Time To Live,即生存期)字段来匹配包
- –ttl-eq
- –ttl-gt
- –ttl-lt
拒绝ttl 为 64的流量
1 | iptables -A INPUT -p icmp -m ttl --ttl-eq 64 -j DROP |
time 基于时间的控制
匹配起始时间与结束时间
1 | -m time --datestart YYYY[-MM[[-DD[Thh[:mm[:ss]]]]] --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] |
根据时间和星期几来匹配
--timestart hh:mm[:ss] --timestop hh:mm[:ss] [!] --monthdays day[,day...]
--timestart hh:mm[:ss] --timestop hh:mm[:ss] [!] --weekdays day[,day...]
每周的周六日拒绝ping
1 | iptables -A INPUT -p icmp -m time --timestart 00:00:01 --timestop 23:59:59 --weekdays Sat,Sun -j DROP |
-j 动作和跳转
iptables
支持一组目标和跳转,它们告诉一条规则当报文完全匹配该条规则的时候,应该怎么处理此报文。
常用的目标如下:
ACCEPT
允许数据包通过
DROP
丢弃数据包,不对该数据包做进一步处理,对接受栈而言,就好像该数据包从来没有被接收一样
LOG
将数据包信息记录到rsyslog
中
- –log-level
- debug
- info
- notice
- warning
- warn
- err
- error
- crit
- alert
- emerg
- panic
- –log-prefix 在记录的信息之前加上指定的前缀,前缀最多能有
29
个英文字符 - –log-tcp-sequence
- –log-tcp-options
- –log-ip-options
需要在/etc/rsyslog.conf
添加一条配置kern.=info /var/log/firewall.log
,然后重启rsyslog
服务
1 | iptables -A INPUT -p icmp -j LOG --log-prefix ICMP_ --log-level info |
REJECT
丢弃数据包,同时发生适当的响应报文(如:针对TCP
连接的RST
包或针对UDP
的ICMP
端口不可达消息)
--reject-with
指定返回什么样的信息
- icmp-net-unreachable
- icmp-host-unreachable
- icmp-port-unreachable
- icmp-proto-unreachable
- mp-net-prohibited
- mp-host-prohibited
- port-unreachable (默认选项)
示例
1 | iptables -A INPUT -p tcp --dport 80 -j REJECT --reject-with tcp-reset |
DNAT
对于目标地址转换,数据流向是从外向内的,外面的是客户端,里面的是服务器端通过目标地址转换,我们可以让外面的IP
通过我们对外的外网IP
来访问我们服务器不同的服务器,而我们的服务却放在内网服务器的不同的服务器上。
–to-destination
1 | iptables -t nat -A PREROUTING -d 192.168.2.201 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.202 |
注意:目标地址转换要做在到达网卡之前进行转换,所以要做在 PREROUTING 这个位置上
SNAT
基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将内网地址转换为一个外网的IP
,我们就可以实现连接公网的功能。
--to-source
指定源地址和端口,可以是单独的 ip 也可以是 ip 段
将 192.168.2.0/24 段的 ip 在经过的时候全都转换成 172.16.100.1 这个外网地址
1 | iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j SNAT --to-source 172.16.100.1 |
MASQUERADE
动态源地址伪装。如果上网 ip 不固定,可以使用该参数。系统会自动将私有源 ip 转换成可以上网的公网 ip。适用于那些 ip 不固定的场景,比如拨号上网或通过 dhcp 分配 ip 的情况。
--to-ports
设置外出包能使用的端口
1 | iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j MASQUERADE |
REDIRECT
转发包或流到另一个端口
–to-ports
将外网访问 80 端口的数据转发到本机的 8080 端口
1 | iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 81 |
将访问 80 端口的数据转发到本机的 81-89 端口
1 | iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 81-89 |
MARK
对报文打防火墙标记。将封包标上某个代号,以便提供作为后续过滤的条件判断依据。
1 | iptables -t mangle -A PREROUTING -p tcp --dport 1111 -j MARK --set-mark 1111 |
RETURN
如果作用在主链则停止匹配;如果应用于自定义链上,则将返回父链继续匹配
控制规则的存放以及开启
注意:定义的所有内容,当重启的时候都会失效
在开机的时候,会自动加载/etc/sysconfig/iptabels
1 | iptables-save > iptabels.txt |
调试
通过 raw 表和 TRACE 扩展
- 我们知道从系统进出的网络包,不管其最终目的地为何,都要经过 raw 表的 PREROUTING 和 OUTPUT 链。
man iptables-extensions
可知,TRACE 扩展目标能够记录 iptables 处理一个网络包时经过的表、链和规则。
1 | for mod in ipt_LOG nf_log_ipv4;do\ |
1 | iptables -t raw -A PREROUTING -p icmp -j TRACE |
调试 network namespace iptables
kernel >= 4.11
在通过 raw 表和 TRACE 扩展调试的基础上执行如下命令
1 | echo 1 >/proc/sys/net/netfilter/nf_log_all_netns |
kernel < 4.11
使用 ulog
1 | mkdir -p /tmp/ulogd-rpms |
1 | iptables -A OUTPUT -p icmp -j NFLOG --nflog-prefix="IPT_FILTER_OUTPUT"` |
总结
iptables
是一个非常重要的工具,它是每一个防火墙上几乎必备的设置,也是我们在做大型网络的时候,为了很多原因而必须要设置的。学好iptables
,可以让我们对整个网络的结构有一个比较深刻的了解,同时,我们还能够将内核空间中数据的走向以及Linux
的安全给掌握的非常透彻。我们在学习的时候,尽量能结合着各种各样的项目,实验来完成,这样对你加深iptables
的配置,以及各种技巧有非常大的帮助。