1 iptables 用法说明

格式

iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X  [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name

rule-specification = [matches...]  [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]
# man 8 iptables
iptables -t 表 命令 链名 规则 -j 动作

iptables comment 有什么用 iptables -m time_端口号

2. 命令格式

iptables命令格式详解

iptables   [-t table]   SUBCOMMAND   chain   [-m matchname [per-match-options]] -j targetname [per-target-options]

2.1 -t table:指定表

filter(默认)
nat
mangle
raw
security

2.2 SUBCOMMAND:子命令

header 1

header 2

-N:new

自定义一条新的规则链

-E

重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除

-X:delete

删除自定义的空的规则链

-P:Policy

设置默认策略;对filter表中的链而言,其默认策略有:ACCEPT:接受, DROP:丢弃

-A 或 --append

在规则列表的最后增加一条规则

-I 或 --insert

在指定的位置插入一条规则,要指明插入至的规则编号,默认为第一条

-D 或–delete

删除一个规则

(1)指明规则序号

(2)指明规则本身

-R 或 --replace

替换规则列表中的某个规则

-F 或 --flush

删除表中所有规则

-Z:zero

置零

iptables的每条规则都有两个计数器

(1)匹配到的报文的个数

(2)匹配到的所有报文的大小之和

-L:list

列出指定鏈上的所有规则,本选项须置后

-n:numberic

以数字格式显示地址和端口号

-v:verbose

详细信息

-vv

更详细

-x:exactly

显示计数器结果的精确值,而非单位转换后的易读值

–line-numbers

显示规则的序号

-S selected

以iptables-save 命令格式显示链上规则

示例

[root@centos8 ~]#iptables -N test_chain             # -N:new, 自定义一条新的规则链
[root@centos8 ~]#iptables -N test_chain -t nat      # 在 nat 表自定义一条心的规则链
[root@centos8 ~]#iptables -X test_chain -t nat      # -X:delete,删除自定义的空的规则链
[root@centos8 ~]#iptables -E test_chain TEST_CHAIN  # 重命名自定义链
[root@centos8 ~]#iptables -A TEST_CHAIN -s 10.0.0.12 -p tcp -m multiport  --dports 80,443 -j REJECT
[root@centos8 ~]#iptables -R TEST_CHAIN 1  -s 10.0.0.12 -p tcp -m multiport  --dports 80,443,8080 -j REJECT
[root@centos8 ~]#iptables -vnL  TEST_CHAIN          # 查看自定的链
Chain TEST_CHAIN (0 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     tcp  --  *      *       10.0.0.12            0.0.0.0/0            multiport dports 80,443,8080 reject-with icmp-port-unreachable
[root@centos8 ~]#iptables -A INPUT -j TEST_CHAIN

# 无法直接删除自定义链,删除自定议链和创建的顺序相反
[root@centos8 ~]#iptables -X TEST_CHAIN
iptables v1.8.4 (nf_tables):  CHAIN_USER_DEL failed (Device or resource busy): chain TEST_CHAIN

[root@centos8 ~]#iptables -F TEST_CHAIN
[root@centos8 ~]#iptables -X TEST_CHAIN
iptables v1.8.4 (nf_tables):  CHAIN_USER_DEL failed (Device or resource busy): chain TEST_CHAIN
[root@centos8 ~]#iptables -D INPUT 1
[root@centos8 ~]#iptables -X TEST_CHAIN
[root@centos8 ~]#

-P 或 --policy:定义默认策略

# 更改 FORWARD 默认策略为 DROP
iptables -t filter --policy FORWARD DROP

# 更改 FORWARD 默认策略是 ACCEPT
iptables -t filter -P FORWARD ACCEPT

-A 或 --append:在规则列表的最后增加一条规则

[root@centos8 ~]#systemctl disable --now firewalld.service
[root@centos8 ~]#systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)
[root@centos8 ~]#iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 
# 拒绝源地址是 10.0.0.16 的任意数据包
[root@centos8 ~]#iptables -t filter -A INPUT -s 10.0.0.16 -j DROP
[root@centos8 ~]#

-I 或 --insert:在指定的位置插入一条规则

#拒绝 icmp 协议数据包进入linux,禁ping ,不指定位置,默认放置在第一条
iptables -t filter -I INPUT -p icmp -j DROP

#示例:插入一条规则成为 filter 表 INPUT 链第三条规则,即第二条的后面
iptables -t filter -l INPUT 3 -p icmp -j DROP

-D 或–delete:删除一个规则

#示例:删除 filter 表 INPUT 链第一条规则
iptables -t filter -D INPUT 1
[root@centos8 ~]#iptables -t filter -I INPUT -s 10.0.0.10 -j ACCEPT
[root@centos8 ~]#iptables -t filter -A INPUT -s 10.0.0.0/24 -j REJECT
[root@centos8 ~]#iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1       16  1152 ACCEPT     all  --  *      *       10.0.0.10            0.0.0.0/0
2        0     0 REJECT     all  --  *      *       10.0.0.0/24          0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
[root@centos8 ~]#iptables -t filter -D INPUT 2
[root@centos8 ~]#iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1       45  3168 ACCEPT     all  --  *      *       10.0.0.10            0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
[root@centos8 ~]#

-R 或 --replace:替换规则列表中的某个规则

#示例:将第二条规则改成DROP
iptables -t filter -R INPUT 2 -p icmp -j DROP

-F 或 --flush:删除表中所有规则

#示例:删除INPUT链中所有的规则,如果不指定链,则删除表中所有的规则
iptables -t filter -F INPUT

2.3 chain(链)

PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING

2.4 匹配条件

  • 基本:通用的,PARAMETERS
  • 扩展:需加载模块,MATCH EXTENTIONS

2.5 规则(匹配)

基本匹配条件:无需加载模块,由iptables/netfilter自行提供

[!] -s, --source address[/mask][,...]:源IP地址或者不连续的IP地址
[!] -d, --destination address[/mask][,...]:目标IP地址或者不连续的IP地址
[!] -p, --protocol protocol:指定协议,可使用数字如0(all)
    protocol: tcp, udp, icmp, icmpv6, udplite,esp, ah, sctp, mh or "all"
    参看:/etc/protocols
[!] -i, --in-interface name:报文流入的接口;只能应用于数据报文流入环节,只应用于INPUT、 FORWARD、PREROUTING链
[!] -o, --out-interface name:报文流出的接口;只能应用于数据报文流出的环节,只应用于 FORWARD、OUTPUT、POSTROUTING链

-i 或 --in-interface:指定数据包从哪个网络接口进入,如ppp0、eth0和eth1等

#示例:拒绝从eth1网卡进入ICMP协议数据包
iptables -t filter -I INPUT -i eth1 -p icmp -j DROP

-o 或–out-interface:指定数据包从那块网络接口输出,如ppp0、eth0和eth1等

-p 或 --protocol:协议类型,指定数据包匹配的协议,如TCP、UDP和ICMP等

-s 或 --source:指定数据包匹配的源地址

-d 或 --destination:指定数据包匹配的目标地址

–sport:源端口号,指定数据包匹配的源端口号,可以使用“起始端口号:结束端口号”的格式指定一个范围的端口

–dport:目标端口号,指定数据包匹配的目标端口号,可以使用“起始端口号:结束端口号”的格式指定一个范围的端口

# 语法规则:iptables -t 表 命令 链名 规则 -j 动作
# 示例:禁止源地址192.168.80.123访问目标地址192.168.10.123的3389端口(远程桌面)
# 在中间路由器上操作
iptables -t filter -I FORWARD -p tcp -s 192.168.80.123/32 -d 192.168.10.123/32 -dport 3389 -j DROP

iptables -t filter -A FORWARD -s 192.168.80.0/24 -d 192.168.10.0/24 -j ACCEPT

2.6 扩展匹配选项(加-m引用模块的显示扩展)

扩展匹配条件:需要加载扩展模块(/usr/lib64/xtables/*.so),方可生效

扩展模块的查看帮助:man iptables-extensions

扩展匹配条件:

  • 隐式扩展
  • 显式扩展

2.6.1 隐式扩展

iptables 在使用-p选项指明了特定的协议时,无需再用-m选项指明扩展模块的扩展机制,不需要手动加载扩展模块

tcp 协议的扩展选项

[!] --source-port, --sport port[:port]:匹配报文源端口,可为端口连续范围

[!] --destination-port,--dport port[:port]:匹配报文目标端口,可为连续范围

[!] --tcp-flags mask comp
    mask 需检查的标志位列表,用,分隔 , 例如 SYN,ACK,FIN,RST
    comp 在mask列表中必须为1的标志位列表,无指定则必须为0,用,分隔tcp协议的扩展选项

示例

--tcp-flags SYN,ACK,FIN,RST SYN       # 表示要检查的标志位为SYN,ACK,FIN,RST四个,其中SYN必 须为1,余下的必须为0,第一次握手

--tcp-flags SYN,ACK,FIN,RST    SYN,ACK 第二次握手


# 错误包(四个包全部为 1 或者全部为 0 是错误的数据包)
--tcp-flags ALL ALL 
--tcp_flags ALL NONE

[!] --syn:用于匹配第一次握手, 相当于:–tcp-flags SYN,ACK,FIN,RST SYN

[root@centos8 ~]#iptables -A INPUT -p tcp --syn  -j REJECT

udp 协议的扩展选项

[!] --source-port, --sport port[:port]:匹配报文的源端口或端口范围
[!] --destination-port,--dport port[:port]:匹配报文的目标端口或端口范围

icmp 协议的扩展选项(-m icmp --icmp-type)

[!] --icmp-type {type[/code]|typename}
    type/code
        0/0 echo-reply icmp应答 
        8/0 echo-request icmp请求

ping命令使用icmp协议测试网络是否畅通,icmp有两种常用类型的数据包即icmp-type,常用的类型为echo-reply和
echo-request,如下如所有PC1 ping PC2,发出去的数据包是icmp协议的echo-request类型的数据包,PC2返回的数据包
是icmp协议的echo-reply类型的数据包

sequenceDiagram
PC1(192.168.10.10)->>PC2(192.168.10.20): echo-request
PC2(192.168.10.20)->>PC1(192.168.10.10): echo-reply

示例:禁止其他计算机ping本地linux

# 在linux上设置
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type echo-request -j DROP

示例:10.0.0.100 ping 不通我,我可以 ping 通 10.0.0.100

iptables -A INPUT -s 10.0.0.100 -p icmp --icmp-type 8 -j REJECT

或者

iptables -A OUTPUT -d 10.0.0.100 -p icmp --icmp-type 0 -j REJECT(不建议)

icmp数据包的类型也可以使用数字表示,如

  • 类型8:echo-request
  • 类型0:echo-reply

也可以写成:

iptables -t filter -F INPUT       # 清除原有规则
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8 -j DROP

示例:禁止192.168.10.0/24 ping通 192.168.80.0/24,允许192.168.80.0/24 ping通 192.168.10.0/24

# 在路由器上设置
iptables -t filter -I FORWARD -s  192.168.10.0/24 -d 192.168.80.0/24 -p icmp -m icmp --icmp-type echo-request -j DROP

2.6.2 显式扩展及相关模块

显示扩展即必须使用-m选项指明要调用的扩展模块名称,需要手动加载扩展模块

[-m matchname [per-match-options]]

扩展模块的使用帮助

  • CentOS 7,8: man iptables-extensions
  • CentOS 6: man iptables
2.6.2.1 -m state

state 扩展模块,可以根据”连接追踪机制“去检查连接的状态,较耗资源

conntrack机制:追踪本机上的请求和响应之间的关系

--state {NEW,ESTABLISHED,INVALID,RELATED,UNTRACKED}

说明:用来比对连接状态,连接状态共有四种:INVALID,ESTABLISHED,NEW和RELATED

  • INVALID:无效的连接,如flag标记不正确,即,表示该封包的连接编号(Session ID) 无法辨识或编号不正确
  • ESTABLISHED:NEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通信状态,即,表示该封包属于某个已经建立的连接
  • NEW:NEW:新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别为第一次发 出的请求,即,表示该封包想要起始一个连接(重设连接或将连接重导向)
  • RELATED:表示该封包是属于某个已经建立的连接所建立的新连接,例如FTP-DATA连接必定是源自某个FTP连接
  • UNTRACKED:未进行追踪的连接,如:raw表中关闭追踪

已经追踪到的并记录下来的连接信息库

[root@centos8 ~]#cat /proc/net/nf_conntrack

调整连接追踪功能所能够容纳的最大连接数量

[root@centos8 ~]#cat /proc/sys/net/netfilter/nf_conntrack_max
65536
[root@centos8 ~]#cat /proc/sys/net/nf_conntrack_max
65536
[root@centos8 ~]#

查看连接跟踪有多少条目

[root@centos8 ~]#cat /proc/sys/net/netfilter/nf_conntrack_count
0
[root@centos8 ~]#

不同的协议的连接追踪时长

[root@centos8 ~]#ll /proc/sys/net/netfilter/
total 0
dr-xr-xr-x 1 root root 0 May 11 16:57 ./
dr-xr-xr-x 1 root root 0 May 11 09:14 ../
-rw-r--r-- 1 root root 0 May 11 16:58 nf_conntrack_acct
-rw-r--r-- 1 root root 0 May 11 16:58 nf_conntrack_buckets
-rw-r--r-- 1 root root 0 May 11 16:58 nf_conntrack_checksum
-r--r--r-- 1 root root 0 May 11 16:57 nf_conntrack_count
-rw-r--r-- 1 root root 0 May 11 16:58 nf_conntrack_dccp_loose
... 省略部分 ...
[root@centos8 ~]#

说明

  • 连接跟踪,需要加载模块: modprobe nf_conntrack_ipv4
  • 当服务器连接多于最大连接数时dmesg 可以观察到 :kernel: ip_conntrack: table full, dropping packet错误,并且导致建立TCP连接很慢。
  • 各种状态的超时后,链接会从表中删除

面试题:

[root@centos8 ~]#echo 1 > /proc/sys/net/netfilter/nf_conntrack_max

[root@centos8 ~]#tail /var/log/messages
Jul  8 10:03:53 centos8 kernel: nf_conntrack: nf_conntrack: table full, dropping
packet

[root@centos6 ~]#tail /var/log/messages
Jul  8 09:51:16 centos6 kernel: nf_conntrack: table full, dropping packet.

连接过多的解决方法两个

(1) 加大nf_conntrack_max 值

vi /etc/sysctl.conf
net.nf_conntrack_max = 393216
net.netfilter.nf_conntrack_max = 393216

(2) 降低 nf_conntrack timeout时间

vi /etc/sysctl.conf
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
iptables -t nat -L -n

格式

[!] --state state

示例:不允许远程主机 10.0.0.12 访问本机,但本机可以访问10.0.0.12

[root@centos8 ~]#iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 10.0.0.1/32 -j ACCEPT
-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT ! -s 10.0.0.12/32 -m state --state NEW -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -m state --state RELATED,ESTABLISHED

示例:单方向建立会话,保护服务器安全

# 在中间路由器上设置,禁止源192.168.10.0/24和目的192.168.80.0/24之间建立新的连接,反向建立连接不受影响
iptables -t filter -F FORWARD # 清除filter链上FORWARD的规则
iptables -t filter -L
iptables -t filter -I FORWARD -s 192.168.10.0/24 -d 192.168.80.0/24 -m state --state NEW -j DROP

示例:允许外界访问linux的80,但是,禁止linux服务器主动向外界发起会话

iptables -t filter -I OUTPUT -m state --state NEW -j DROP

示例:建立会话以后的数据包都可以进来

iptables -A INPUT -m state RELATED,ESTABLISHED

2.6.2.2 -m multiport

以离散方式定义多端口匹配,最多指定15个端口

指定多端口号

-m multiport
    --sport
    --dport
    --ports
# 指定多个源端口
[!] --source-ports,--sports port[,port|,port:port]...

# 指定多个目标端口
[!] --destination-ports,--dports port[,port|,port:port]...

# 多个源或目标端
[!] --ports port[,port|,port:port]...

示例:拒绝 192.168.80.0/24 访问 192.168.10.0/24 的 1-1024 和 3389端口

# 在路由器上设置
iptables -t filter -I FORWARD -p tcp -d 192.168.10.0/24 -s 192.168.80.0/24 -m multiport --dport 1:1024,3389 -j DROP

示例:禁止 10.0.0.7 访问本机的80和6739端口

iptables -A INPUT -s 10.0.0.7 -p tcp -m multiport --dport 80,6379 -j REJECT

2.6.2.3 -m iprange

指明连续的(但一般不是整个网络)ip地址范围

-m iprange
    [!] --src-range from[-to]    # 源IP地址范围 
    [!] --dst-range from[-to]    # 目标IP地址范围

示例:禁止192.168.80.1-100 地址段访问192.168.10.0/24

iptables -t filter -I FORWARD -m iprange --src-range 192.168.80.1-192.168.80.100 -j DROP

示例

iptables -A INPUT -m iprange --src-range 10.0.0.1-10.0.0.7 -j DROP

2.6.2.4 -m connlimit

根据每客户端IP做并发连接数数量匹配

可防止Dos(Denial of Service,拒绝服务)攻击

-m connlimit
    --connlimit-upto N       # 连接的数量小于等于N时匹配
    --connlimit-above N      # 连接的数量大于N时匹配

示例:只允许 192.168.80.0/24 使用远程桌面连接 192.169.10.123/32 最多两个会话

iptables -t filter -F
iptables -t filter -L
iptables -I FORWARD -s 192.168.80.0/24 -d 192.169.10.123/32 -p tcp --dport 3389 -m connlimit --connlimit-above 2 -j DROP

2.6.2.5 -m limit --limit

限速

-m limit --limit
iptables -A INPUT -m limit --limit 3/hour
#说明:用来比对某段时间内封包的平均流量,上面的例子用来比对,每小时平均流量是否超过一次3个封包
#除了每个小时平均一次外,也可以每秒钟、每分钟、每小时或每天平均一次,默认值为每小时平均一次,参数如后/second /minute  /hour  /day

示例:192.168.10.0/24 网段每秒钟向 192.168.80.0/24 发送数据包不能超过 300 个,在以太网中,一个数据包最大1500字节,300个数据包是:300*1500=450000=450K

iptables -F
iptables -t filter -I FORWARD -s 192.168.10.0/24 -d 192.168.80.0/24 -m limit --limit 300/second -j ACCEPT
# 超过每秒 300 个数据包之后拒绝
iptables -t filter -A FORWARD -s 192.168.10.0/24 -d 192.168.80.0/24 -j DROP
# 注意:限速的设置后面一定要跟一个“拒绝”的语句,也可以将默认策略设置为“拒绝”
# 验证:iperf

公司使用linux服务器来当网关,配置iptables NAT上网,虽然公司光纤带宽30MB,但只要有一个人使用迅雷等P2P软件下载资料时,会把带宽跑满,如何使用iptables来对每个用户进行带宽限速呢,参见如下脚本即可

cat /etc/sysconfig/limit.sh
for((i=2;i<254;i++))
do
    iptables -t filter -I FORWARD -s 192.168.10.$i -j DROP
    iptables -t filter -I FORWARD -s 192.168.10.$i -m limit --limit 300/sec --limit-burst 1000 -j ACCEPT
done
# 注:对192.168.1.2-254,前1000个数据包都允许通过(不管它的速度如何),超过1000个以后的数据包,控制在每秒只允许最多300个数据包通过限制

2.6.2.6 --limit-burst

基于收发报文的速率做匹配 , 令牌桶过滤器

瞬间流量限速(通常结合上面的限速(-m limit --limit)一起使用)

--limit-burst number       # 前多少个包不限制 
--limit                    # [/second|/minute|/hour|/day]

说明:用来比对瞬间大量封包的数量,上面的例子是用来比对一次同时涌入的封包是否超过5个(这是默认值)超过此上限的封包将被直接丢弃,使用效果同上

示例:允许 192.168.10.123/32 ping 192.168.80.123/32 4 个包

# 在路由器上设置,就是 FORWARD 链
# 前 4 个数据包通过,第 5 个数据包就不满足第一条规则了,然后应用第二条规则,第二条是拒绝,然后就无法 ping 通了
iptables -t filter -I FORWARD -s 192.168.10.123/32 -d 192.168.80.123/32 -p icmp -m limit --limit-burst 4 -j ACCEPT
iptables -t filter -A FORWARD -s 192.168.10.123/32 -d 192.168.80.123/32 -p icmp -j DROP 
iptables -vnL

# 开一个窗口验证,前4个数据包可以ping通,第5个就无法再ping通了,再开一个窗口也是无法ping通的
# 清空计数
iptables -t filter -Z
# 清空计数之后就有可以ping通 4 个数据包了

2.6.2.7 -m mac --mac-source

基于MAC地址过滤流量

用来对比封包来源网路接口的硬件地址,这个参数不能用在 OUTPUT 和 POSTROUTING 规则链上(因为–mac-source要检查数据帧的源mac地址,OUTPUT是自己发出的数据包,不是接收的数据包,所以没有源mac地址, POSTROUTING是要路由出去了,源mac要换成自己的了,也不是接收到的数据包),这是因为封包要送出网卡后,才能由网卡驱动程序透过 ARP 通讯协议查出目的地的 MAC 地址,所以 iptables 在进行封包对比时,并不知道封包会送到那个网络接口去

PRE_ROUTING 和 LOCAL_IN 、FORWARD 可以使用基于MAC地址过滤流量

[!] --mac-source XX:XX:XX:XX:XX:XX

示例:拒绝2003计算机的MAC(00-0C-29-DB-32-6F) 能够访问 VMNet8 这个网段

# 在路由器上设置,就是 FORWARD 链了
iptables -t filter -I FORWARD -d 192.168.80.0/24 -m mac --mac-source 00-0C-29-DB-32-6F -j DROP

2.6.2.8 --mark

用来比对封包是否被表示某个号码,当封包被比对成功时,我们可以通过 MARK 处理动作,将该封包标示一个号码,号码最大不可以超过 4294967296

iptables -t managle -A INPUT -m mark --mark 1

2.6.2.9 string扩展

对报文中的应用层数据做字符串模式匹配检测

--algo {bm|kmp} 字符串匹配检测算法
    bm:Boyer-Moore
    kmp:Knuth-Pratt-Morris
--from offset 开始偏移
--to offset 结束偏移
[!] --string pattern 要检测的字符串模式
[!] --hex-string pattern要检测字符串模式,16进制格式

示例

cat index.html
www.google.com

cat index2.html
www.baidu.com

# 返回包中带google的都拒绝掉(tcp20字节+ip20字节+frame22字节,所以至少从62开始就是应用层数据了)

iptables -A OUTPUT -p tcp --sport 80 -m string --algo bm --from 62 --string "google" -j REJECT

# 测试
curl 10.0.0.8/index.html
Crul 10.0.0.8/index.html

2.6.2.10 time扩展

注意:CentOS 8 此模块有问题

根据将报文到达的时间与指定的时间范围进行匹配

--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...]   每个月的几号

[!] --weekdays day[,day...]   星期几,1 - 7 分别代表星期一到星期日

--kerneltz:内核时区(当地时间),不建议使用,CentOS 7版本以上系统默认为 UTC 

注意: centos6 不支持kerneltz ,--localtz指定本地时区(默认)

CentOS 8 的 time模块问题

[root@centos8 ~]#rpm -ql iptables  |grep time
/usr/lib64/xtables/libxt_time.so
[root@centos8 ~]#iptables -A INPUT -m time --timestart 12:30 --timestop 13:30 -j ACCEPT
iptables v1.8.4 (nf_tables): Couldn't load match `time':No such file or directory

Try `iptables -h' or 'iptables --help' for more information.
[root@centos8 ~]#

示例:关于 --kerneltz 选项

[root@centos8 ~]#man iptables-extensions
The caveat with the kernel timezone is that Linux distributions may ignore to
set the kernel timezone,and instead only set the system time. Even if a
particular distribution does set the timezone at boot,it  is  usually  does not
keep the kernel timezone offset - which is what changes on DST - up to date.
ntpd will not touch the kernel timezone, so running it will not resolve the
issue. As such,one  may       encounter a timezone that is always +0000, or one
that is wrong half of the time of the year. As such,using --kerneltz is highly
discouraged.

示例

[root@centos7 ~]#iptables -A INPUT -s 172.18.0.0/16 -d 172.18.10.100 -p tcp --dport 80 -m time \
--timestart 14:30 --timestop 18:30 --weekdays Sat,Sun --kerneltz -j DROP

3. 处理动作

-j targetname [per-target-options]

-j 参数用来指定要进行的处理动作,常用的处理动作有:ACCEPT、REJECT、DROP、REDIRECT、MASQUERADE、LOG、DNAT、SNAT、MIRROR、QUEUE、RETURE、MARK

简单动作

ACCEPT
DROP

扩展动作

REJECT:--reject-with:icmp-port-unreachable默认
RETURN:返回调用链
REDIRECT:端口重定向
LOG:记录日志,dmesg
MARK:做防火墙标记
DNAT:目标地址转换
SNAT:源地址转换
MASQUERADE:地址伪装 
自定义链

filter 表能使用的主要动作

  • ACCEPT:将封包放行,进行完此处理动作后,将不再匹配其他规则,直接跳往下一个规则链
  • REJECT:拦阻该封包,并传送封包通知对方,可以传送的封包有几个选择:ICMP port-unreachable、ICMP echo-reply 或是 tcp-reset(这个封包会要求对方关闭连接)进行完此处理动作后,将不再匹配其他规则,直接中断过滤程序
  • DROP:丢弃封包不予处理,进行完此处理动作后,将不再匹配其他规则,直接中断过滤程序
  • LOG:将封包相关讯息记录在 /var/log 中,详细位置请查阅 /etc/rsyslog.conf 配置文件,进行完此处理动作后,将会继续匹配其规则
LOG:非中断target,本身不拒绝和允许,放在拒绝和允许规则前,并将日志记录在/var/log/messages系 统日志中

--log-level level 级别: debug,info,notice, warning, error, crit, alert,emerg 
--log-prefix prefix   日志前缀,用于区别不同的日志,最多29个字符

REJECT示例:

# 在路由器上设置,就是 FORWARD 链了
iptables -t filter -I FORWARD -s 192.168.10.0/24 -p icmp -j REJECT
# ping测试会被拒绝,即:Destination port unreachable

# 再加一条
iptables -t filter -I FORWARD -s 192.168.10.0/24 -p icmp -j DROP
# ping测试就是超时:Request timed out

# 记录 iptables 日志,-j LOG要放在规则的第一条
iptables -t filter -I FORWARD -s 192.168.10.0/24 -p tcp --dport 3389 -j DROP
iptables -t filter -I FORWARD -s 192.168.10.0/24 -p tcp --dport 3389 -j LOG --log-prefix "iptables-rdp"

# 记录ping我的日志,--log-prefix表示增加一个标记
iptables -t filter -I INPUT -p icmp -j LOG --log-prefix "iptables-icmp"

# 查看日志
tail -fn 5 /var/log/messages
grep "iptables-icmp" /var/log/messages
grep "iptables-rdp" /var/log/messages

更改日志的存放路径

vim  /etc/rsyslog.conf
# 需要注释掉原来的日志路径
kern.warning /var/log/iptables.log

service rsyslog restart

4 规则优化最佳实践

  • 安全放行所有入站和出站的状态为ESTABLISHED状态连接,建议放在第一条,效率更高
  • 谨慎放行入站的新请求
  • 有特殊目的限制访问功能,要在放行规则之前加以拒绝
  • 同类规则(访问同一应用,比如:http ),匹配范围小的放在前面,用于特殊处理
  • 不同类的规则(访问不同应用,一个是http,另一个是mysql ),匹配范围大的放在前面,效率更 高
-s 10.0.0.6 -p tcp --dport 3306  -j REJECT
-s 172.16.0.0/16 -p tcp --dport 80  -j REJECT
  • 应该将那些可由一条规则能够描述的多个规则合并为一条,减少规则数量,提高检查效率
  • 设置默认策略,建议白名单(只放行特定连接)
  • iptables -P,不建议,容易出现“自杀现象”
  • 规则的最后定义规则做为默认策略,推荐使用,放在最后一条

5 iptables规则保存

使用iptables命令定义的规则,手动删除之前,其生效期限为kernel存活期限

持久保存规则

# CentOS 7+
iptables-save  >  /PATH/TO/SOME_RULES_FILE

# CentOS 6
# 将规则覆盖保存至/etc/sysconfig/iptables文件中 service iptables save

加载规则

CentOS 7+ 重新载入预存规则文件中规则:

iptables-restore <  /PATH/FROM/SOME_RULES_FILE

iptables-restore选项

-n, --noflush:不清除原有规则
-t, --test:仅分析生成规则集,但不提交

CentOS 6

# 会自动从/etc/sysconfig/iptables 重新载入规则 
service iptables restart

开机自动重载规则

  • 用脚本保存各个iptables命令;让此脚本开机后自动运行 /etc/rc.d/rc.local文件中添加脚本路径/PATH/TO/SOME_SCRIPT_FILE
  • 用规则文件保存各个规则,开机时自动载入此规则文件中的规则
    在/etc/rc.d/rc.local文件添加
iptables-restore < /PATH/FROM/IPTABLES_RULES_FILE
  • 定义Unit File, CentOS 7,8 可以安装 iptables-services 实现iptables.service

示例:CentOS 7+ 使用 iptables-services

[root@centos8 ~]#yum  -y install iptables-services
[root@centos8 ~]#cp /etc/sysconfig/iptables{,.bak}

# 保存现在的规则到文件中方法1
[root@centos8 ~]#/usr/libexec/iptables/iptables.init save

# 保存现在的规则到文件中方法2
[root@centos8 ~]#iptables-save > /etc/sysconfig/iptables

# 开机启动
[root@centos8 ~]#systemctl enable iptables.service
[root@centos8 ~]#systemctl mask firewalld.service nftables.service