iptables指令详解
1 iptables 的概念
什么是iptables
iptables
是一个配置Linux 内核防火墙
的命令行工具,是 netfilter
项目的一部分。netfilter
位于内核空间,用于管理网络数据包,具有NAT、数据包修改、数据包过滤,等防火墙功能。
iptables 链
链是数据包在主机上的传播途径;链由众多规则组成防火墙根据这些规则判断数据包的流向。数据包在主机上的流向如下图所示:

链的类别
PREOUTING
:路由前FOWARD
:转发POSTROUTING
:路由后INPUT
:输入链;输入本机的数据包OUTPUT
:输出链;由本机输出的数据包
iptables 表
表是链上相同类型的规则的集合,不同的表对应不同的功能。iptables
提供了4种表
filter
:负责过滤功能;内核模块:iptables_filter
nat
:网络地址转换功能;内核模块:iptable_nat
mangle
:拆解报文,做出修改,并重新封装 ;内核模块:iptable_mangle
raw
:关闭nat表上启用的连接追踪机制;内核模块:iptable_raw
表链关系
不同的链上依据功能上的不同拥有不同种类的表,而且表之间具有不同的优先级。
同一条链上表的优先级为:raw > mangle > nat > filter
表在不同链上的分布如图所示:

不同表所属的链关系如下图:

iptables 规则
规则由匹配条件和动作构成;防火墙根据匹配条件来匹配数据包,满足条件则执行相应的动作;否则继续匹配下一条规则。
匹配条件
匹配条件分为基本匹配条件和扩展匹配条件;
- 基本匹配条件:源IP、目的IP
- 扩展匹配条件,扩展匹配条件是
netfilter
的一部分,以模块的形式存在;要使用这些条件需要依赖于相应的扩展模块;常见扩展条件有:源端口、目的端口
动作
动作被称为target
(这样说并不准确,我们暂且这样称呼),动作也可以分为基本动作和扩展动作
- ACCEPT:允许数据包通过。
- DROP:直接丢弃数据包,不给任何回应信息。
- REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息。
- REDIRECT:在本机做端口映射。
- SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
- DNAT:目标地址转换。
- MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
- LOG:在
/var/log/messages
文件中记录日志信息,然后将数据包传递给下一条规则
2 iptables 的增删查改
查看 iptables 的规则
# 查看某一张表
iptables -t 表名 -L
# 查看某一条链
iptables -L 链名
# 查看某张表中一条链
iptables -t 表名 -L 链名
# 参数含义
-n : numeric 数字化显示IP和port
-v : verbose 显示详细信息
-x : expand 显示计数器精确值
--line : 显示规则的序号
-t : table 后跟表名
-L : list 后跟链名
# 常见用法
iptables -t 表名 -nvxL
iptables -nvxL 链名
iptables --line -t 表名 -nvxL 链名
增加 iptables 的规则
添加规则必须同时指定表和链
# 在 指定表 的 指定链 的尾部添加一条规则
iptables -t 表名 -A 链名 匹配条件 -j 动作
# 示例
iptables -t filter -A INPUT -s 192.168.1.146 -j DROP
# 在 指定表 的 指定链 的首部添加一条规则
iptables -t 表名 -I 链名 匹配条件 -j 动作
# 示例
iptables -t filter -I INPUT -s 192.168.1.146 -j ACCEPT
# 在 指定表 的 指定链 的指定位置添加一条规则
iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作
# 示例
iptables -t filter -I INPUT 5 -s 192.168.1.146 -j REJECT
# 设置 指定表 的 指定链 的默认策略(默认动作)
iptables -t 表名 -P 链名 动作
# 参数含义
-A : append 在链的末尾追加一条规则
-I : insert 在链的头部插入一条规则
-j : targe 指定相应的动作
-P : policy 指定链的默认策略
删除 iptables 的规则
# 删除 指定表 的 指定链 中特定序号的规则
iptables -t 表名 -D 链名 规则序号
# 示例
iptables -t filter -D INPUT 3
# 删除 指定表 的 指定链 的指定规则
iptables -t 表名 -D 链名 匹配条件 -j 动作
# 示例
iptables -t filter -D INPUT -s 192.168.1.146 -j DROP
# 删除 指定表 的 指定链 的所有规则
iptables -t 表名 -F 链名
# 删除 指定表 的所有规则
iptables -t 表名 -F
# 参数含义
-D : delete 删除
-F : flush 清空
修改 iptables 的规则
# 修改指定表中指定链的指定规则
iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
# 示例
iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT
# 修改指定表的指定链的默认策略(默认动作)
iptables -t 表名 -P 链名 动作
# 参数含义
-R : replace 修改规则
-P : policy 默认策略
保存规则
# 保存规则
service iptables save
# 保存规则到文件
iptables-save > file
# 从文件载入规则
iptables-restore < file
3 iptables 的匹配条件
IP 地址
-s : source 源IP地址
-d : destination 目的IP地址
指定单个地址
-s ip
指定多个地址
-s ip1,ip2,ip3 # 逗号两侧不能添加空格
指定网段
-s 网络地址/掩码
# 示例
-s 10.1.2.0/24
取反
! -s ip # 指定多个ip时不能用取反
协议类型
-p : protocol 协议
-p 协议类型 # tcp udp udplite icmp esp ah stcp ...
-p all # 匹配所有协议(默认)
网卡接口
-i : in-interface 数据流入的网卡接口
-o : out-interface 数据流出接口
-i 网卡名 # 可通过 ifconfig 或 ip addr 查看
扩展匹配条件
要使用扩展条件则需要需要依赖特定的模块,需要使用 -m 模块名
引入
指定端口
-m : module 指定相应模块, eg. tcp
--sport : 源端口
--dport : 目的端口
指定单个端口
-m tcp --sport 端口号
指定端口范围
# 指定端口1 到 端口2的范围
-m tcp --sport 端口1:端口2
# 指定端口1后所有(到65535)
-m tcp --sport 端口1:
# 指定1到端口2之间所有端口
-m tcp --sport :端口2
指定多个离散端口
# 需要用到扩展模块 multiport
-m multiport --dport port1,port2,port3
# 混合使用,离散端口和范围端口同时使用
-m multiport --dport port1,port2:port3
指定IP范围——iprange模块
# 指定 目的ip 或 源ip
-m iprange --src-range ip1-ip2
-m iprange --dst-range ip1-ip2
# 支持取反符号
-m iprange ! --src-range ip1-ip2
匹配字符串——string模块
# string 支持过滤数据包中的字符串
-m string --algo bm --string "xxxx"
# 参数含义
--algo : algorithm 指定字符串匹配算法,有bm、kmp等
匹配时间——time模块
# 按小时指定
-m time --time-start time1 --time-stop time2
# 时间格式
h:minutes:s # 指定时分秒
# 按周指定时间
-m time --weekdays 6,7
# 按月指定时间
-m time --monthdays 23,24
# 指定日期范围
-m time --datestarttime date1 --datestop date2
# 日期格式
y-month-d # 指定年月日
# 取反
# 只有--monthdays 和 --weekdays 可以取反
匹配连接数量——connlimit模块
# 限制每个 ip的连接上限数
-m connlimit --connlimit-above 连接上限数
# 限制某个网段中每个 ip的连接上限数
-m connlimit --connlimit-above 连接上限数 --connlimit-mask 子网掩码
匹配流量速率——limit
# 限制包的数量
-m limit --limit 包数量/时间单位
# 时间单位
/second
/minute
/hour
/day
# 指定桶令牌的容量
-m limit --limit-burst 令牌数
桶令牌算法
我们可以这样想象,有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。
icmp扩展
# 匹配特定的icmp报文类型
-p icmp --icmp-type 协议类型号
4 iptables 自定义链
为什么需要自定义链
当默认链中的规则非常多时,不方便管理。例如,INPUT链
中存放了200条规则,这200条规则有针对httpd服务
的,有针对sshd服务
的,有针对私网IP
的,有针对公网IP
的。假如,需要修改针对httpd服务
的相关规则,就需要从头看一遍这200条规则,找出针对httpd
的规则,不便于管理。
因此,iptables
中可以自定义链,通过自定义链即可解决上述问题。例如,自定义一条链,链名叫IN_WEB
,我们可以将所有针对80端口的入站规则都写入到这条自定义链中;也可以将针对sshd
的出站规则放入到OUT_SSH
自定义链中。
创建自定义链
iptables -t 表名 -N 自定义链名
# 参数含义
-N : new 新建自定义链
引用自定义链
iptables -t 表名 -A 链名 匹配条件 -j 自定义链名
# 参数含义
-j : target target除了可以跟动作还可以接自定义链
重命名自定义链
iptables -E 自定义链名 新链名
# 参数含义
-E : rename-chain 重命名自定义链
删除自定义链
删除自定义链要满足两个条件:
- 自定义链没有被任何默认链引用;需要在默认链中删除对应规则
- 自定义链中没有任何规则;需要使用
-F
清空自定义链
iptables -X 自定义链
# 参数含义
-X : delete-chain 删除自定义链
5 iptables 的动作
REJECT
REJECT可添加参数 --reject-with
REJECT --reject-with 拒绝参数
# 参数选项
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-pro-hibited
icmp-admin-prohibited
SNAT
# 指定修改后的源地址
SNAT --to-source ip
DNAT
# 指定修改后的目的地址
SNAT --to-destination ip:port
MASQUERADE
当使用动态IP时,SNAT会很麻烦,因为每次IP地址发生变化以后,都要重新配置SNAT规则;可以通过MASQUERADE即可解决这个问题,MASQUERADE会动态的将源地址转换为可用的IP地址
# 自动选择修改后的源地址
-j MASQUERADE
REDIRECT
# 在本机进行端口映射
-j REJECT --to-ports port