防火墙分类

从逻辑上:

  • 主机防火墙:针对于单个主机进行防护
  • 网络防火墙:针对于网络入口进行防护,服务于防火墙背后的本地局域网

从物理上:

  • 硬件防火墙:在硬件级别实现一部分防火墙功能,另一部分基于软件实现,性能高,成本高
  • 软件防火墙:在软件级别实现防火墙功能,性能低,成本低

netfilter、iptables

iptables实质上是一个代理,用户通过Iptables这个代理,运行命令将用户的安全设定执行到对应的安全框架中,这个安全框架--netfilter才是真正的防火墙。netfilter+iptables组成linux平台的包过滤防火墙,其中netfilter是linux操作系统核心层内部的一个数据包处理模块,可以完成封包过滤、封包重定向、网络地址转换等功能的实现。

安装启动iptables服务

# yum install iptables-services -y
# systemctl start iptables && systemctl enable iptables

规则

规则其实就是网络管理员预定义的条件,规则一般的定义为”如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。

如下图所示当客户端访问服务器的web服务时,客户端发送报文到网卡,而tcp/ip协议栈是属于内核的一部分,客户端的信息会通过内核的TCP协议传输到用户空间中的web服务中,客户端报文的目标终点为web服务所监听的套接字(IP:Port)上,当web服务需要响应客户端请求时,web服务发出的响应报文的目标终点则为客户端,这个时候,web服务所监听的IP与端口反而变成了原点。因为netfilter处于内核中,所以需要在内核中设置关卡,所有进出的报文都要通过这些关卡,经过检查后,符合放行条件的才能放行,符合阻拦条件的则需要被阻止,于是,就出现了input关卡和output关卡,而这些关卡被称为链。

防火墙的作用在于对经过的报文匹配规则,然后执行对应动作,当报文经过这些关卡的时候,则必须匹配这个关卡上的规则,但关卡上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一个链条上的时候,就形成了”链”。

iptables中有以下链:

PREROUTING:路由前

input:输入

output:输出

FORWARD:转发,当本机内核支持IP_FORWARD,可以将报文转发给其他服务器

POSTROUTING:路由后

由上图所示,报文可能的链流向有:

  • 到本机某进程的报文:PREROUTING –> INPUT
  • 由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING
  • 由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING

把具有相同功能的规则的集合叫做”表”,iptables内置四种表,每种表对应不同的功能:

  • filter表:负责过滤功能,防火墙。内核模块:iptables_filter
  • nat表:network address translation,网络地址转换功能。内核模块:iptable_nat
  • mangle表:拆解报文,做出修改,并重新封装 的功能。内核模块:iptable_mangle
  • raw表:关闭nat表上启用的连接追踪机制。内核模块:iptable_raw

表的优先级(由高到低):raw –> mangle –> nat –> filter

表链关系

存在的链
rawPREROUTING,OUTPUT
manglePREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
natPREROUTING,OUTPUT,POSTROUTING,INPUT(centos6中的INPUT链无nat表)
filterINPUT,FORWARD,OUTPUT

可以在某个表里面创建自定义链,将针对某个应用程序所设置的规则放置在这个自定义链中,但是自定义链接不能直接使用,只能被某个默认的链当做动作去调用才能起作用,

匹配条件

基本匹配条件和扩展匹配条件(以模块的形式存在,如果想要使用这些条件,则需要依赖对应的扩展模块)。

处理动作

  • ACCEPT:允许数据包通过。
  • DROP:直接丢弃数据包,不给任何回应信息。
  • REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
  • SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
  • MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
  • DNAT:目标地址转换。
  • REDIRECT:本机端口映射。
  • LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。

查询规则

查询filter表中的规则(-t参数指定表,-L参数列出规则):

# iptables -t filter -L
Chain INPUT (policy ACCEPT)   #INPUT链
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)   #FORWARD链
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)   #OUTPUT链
target     prot opt source               destination  

#以上的规则都是默认生成的规则

查询filter表中的INPUT链的规则:

# iptables -t filter -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

查看更详细的规则(参数v):

# iptables -t filter -vL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  134  8292 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere            
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:ssh
    6   601 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited

#字段含义
#policy表示当前链的默认策略,policy ACCEPT表示上图中INPUT的链的默认动作为ACCEPT
#packets表示当前链默认策略匹配到的包的数量,0 packets表示默认策略匹配到0个包。
#bytes表示当前链默认策略匹配到的所有包的大小总和。
#pkts:对应规则匹配到的报文的个数。
#bytes:对应匹配到的报文包的大小总和。

#target:规则对应的target,往往表示规则对应的”动作”,即规则匹配成功后需要采取的措施。

#prot:表示规则对应的协议,是否只针对某些协议应用此规则。

#opt:表示规则对应的选项。

#in:表示数据包由哪个接口(网卡)流入,我们可以设置通过哪块网卡流入的报文需要匹配当前规则。

#out:表示数据包由哪个接口(网卡)流出,我们可以设置通过哪块网卡流出的报文需要匹配当前规则。

#source:表示规则对应的源头地址,可以是一个IP,也可以是一个网段。

#destination:表示规则对应的目标地址。可以是一个IP,也可以是一个网段。

不对IP地址进行解析(参数n):

# iptables -t filter -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  222 13608 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
    7   633 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

进行序列号输出(参数--line-number或者--line):

# iptables --line-number -t filter -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      280 17480 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
2        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
3        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
4        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
5        8   665 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

bytes显示精确的计数值,不让其自动转化为可读性高的数值单位(参数-x):

# iptables --line-number -t filter -vxL 
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num      pkts      bytes target     prot opt in     out     source               destination         
1         431    27168 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
2           0        0 ACCEPT     icmp --  any    any     anywhere             anywhere            
3           0        0 ACCEPT     all  --  lo     any     anywhere             anywhere            
4           0        0 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:ssh
5          11      958 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num      pkts      bytes target     prot opt in     out     source               destination         
1           0        0 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 267 packets, 35836 bytes)
num      pkts      bytes target     prot opt in     out     source               destination 

规则管理

清空filter表INPUT链的规则(参数F表示清空规则):

# iptables -F INPUT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 32 packets, 2032 bytes)
 pkts bytes target     prot opt in     out     source               destination  

INPUT链的默认策略是ACCEPT,会放行”所有发往本机的报文,当没有任何规则时,会接受所有报文,当报文没有被任何规则匹配到时,也会默认放行报文。

增加规则(-I参数是将规则插入到指定的链的首部,-A表示在指定的链中追加一条规则,-s参数表示指定匹配条件中的源地址,-j表示当匹配条件被满足时需要执行的动作):

# iptables -t filter -I INPUT -s 192.168.1.12 -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 40 packets, 2320 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0   
#上面的规则是拒绝来自192.168.1.12的报文
# iptables -t filter -A INPUT -s 192.168.1.12 -j ACCEPT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    2   168 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
    0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0   
#在filter表INPUT链中再追加一条放行规则,不会生效

报文如果被前面的规则匹配到立马执行动作,即使后面的规则也能匹配到报文也不会执行对应的规则。

在指定序列规则插入规则:

# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 75 packets, 4564 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
2        0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0           
# iptables -t filter -I INPUT 2 -s 192.168.1.13 -j DROP
# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
2        0     0 DROP       all  --  *      *       192.168.1.13         0.0.0.0/0           
3        0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0 

根据序列号删除规则(-D参数表示删除):

# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 25 packets, 1456 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
2        0     0 DROP       all  --  *      *       192.168.1.13         0.0.0.0/0           
3        0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0           
# iptables -t filter -D INPUT 2
# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
2        0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0 

根据具体的匹配条件与动作删除规则:

# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0           
2        0     0 ACCEPT     all  --  *      *       192.168.1.12         0.0.0.0/0           
# iptables -t filter -D INPUT -s 192.168.1.12 -j ACCEPT
# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0

修改规则(-R参数表示修改):

# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 6 packets, 364 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        3   252 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0 
# iptables -t filter -R INPUT 1 -s 192.168.1.12 -j REJECT
# iptables --line -vnL INPUT
Chain INPUT (policy ACCEPT 8 packets, 488 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 REJECT     all  --  *      *       192.168.1.12         0.0.0.0/0            reject-with icmp-port-unreachable

修改默认策略(-P参数指定修改默认策略的链):

# iptables -t filter -L FORWARD
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited
# iptables -t filter -P FORWARD DROP
# iptables -t filter -L FORWARD
Chain FORWARD (policy DROP)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

保存规则:

# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]
或者
#iptables-save > /etc/sysconfig/iptables

#规则文件路径
# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.21 on Thu Nov 18 02:47:00 2021
*filter
:INPUT ACCEPT [99:5900]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [52:5200]
-A INPUT -s 192.168.1.12/32 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Thu Nov 18 02:47:00 2021

从指定文件中重载规则(重载规则时,现有规则将会被覆盖):

iptables-restore < 文件

基本匹配条件用法

匹配多个源地址:

# iptables -t filter -I INPUT -s 192.168.1.12,192.168.1.13 -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 46 packets, 2736 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *       192.168.1.13         0.0.0.0/0           
    0     0 DROP       all  --  *      *       192.168.1.12         0.0.0.0/0  
#逗号两侧均不能包含空格,多个IP之间必须与逗号相连

匹配网段:

# iptables -t filter -I INPUT -s 172.25.0.0/16 -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 8 packets, 488 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *       172.25.0.0/16        0.0.0.0/0  

对匹配条件取反:

# iptables -t filter -I INPUT ! -s 192.168.1.12 -j ACCEPT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   14   860 ACCEPT     all  --  *      *      !192.168.1.12         0.0.0.0/0  
#取反前:当源IP为192.168.1.12则放行;取反后:当源IP不为192.168.1.12则放行
#注意:上面的规则说的是报文的源IP不是192.168.1.146时,会被接收,并没有任何一条规则指明源IP是192.168.1.12时,该执行怎样的动作,所以会采用默认规则(ACCEPT),所以192.168.1.12依旧可以与主机通信。
#取反操作与同时指定多个IP的操作不能同时使用!

匹配目标地址(-d参数表示目标地址):

# iptables -t filter -I INPUT -s 192.168.1.12 -d 192.168.1.11 -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 16 packets, 1020 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *       192.168.1.12         192.168.1.11  

#上面的命令表示拒绝192.168.1.12到192.168.1.11的通信
#当一条规则中有多个匹配条件时,匹配条件之间默认存在”与”的关系

匹配协议类型(-p参数指定协议类型,支持tcp, udp, udplite, icmp, icmpv6【centos6没有】,esp, ah, sctp, mh【centos6没有】,不适用-p参数将会匹配所有协议类型):

# iptables -I INPUT -s 192.168.1.12 -d 192.168.1.11 -p tcp -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 10 packets, 612 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       192.168.1.12         192.168.1.11         reject-with icmp-port-unreachable

匹配网卡接口(-i参数指定报文流入网卡,-o参数指定报文流出网卡):

# iptables -I INPUT -i enp0s3 -p icmp -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 14 packets, 860 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       icmp --  enp0s3 *       0.0.0.0/0            0.0.0.0/0  

#拒绝流入enp0s3网卡的ping请求报文
#-i参数只能用于上图中的PREROUTING链、INPUT链、FORWARD链
#-o参数只能用于FORWARD链、OUTPUT链、POSTROUTING链

扩展匹配条件用法

指定模块(-m参数指定模块):

# iptables -I INPUT -s 192.168.1.12  -p tcp -m tcp --dport 22 -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 16 packets, 984 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            tcp dpt:22 reject-with icmp-port-unreachable

# -m tcp表示使用tcp扩展模块,--dport表示tcp扩展模块中的一个扩展匹配条件,可用于匹配报文的目标端口,则--sport则匹配源端口。
#如果扩展匹配条件所依赖的扩展模块名正好与-p对应的协议名称相同,那么则可省略-m选项

匹配端口范围:

#表示22到25之间的端口
# iptables -I INPUT -s 192.168.1.12  -p tcp -m tcp --dport 22:25 -j REJECT
#表示0到22之间的端口
# iptables -I INPUT -s 192.168.1.12  -p tcp -m tcp --dport :22 -j REJECT
#表示22到65535之间的端口
# iptables -I INPUT -s 192.168.1.12  -p tcp -m tcp --dport 22: -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 18 packets, 1108 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            tcp dpts:22:65535 reject-with icmp-port-unreachable
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            tcp dpts:0:22 reject-with icmp-port-unreachable
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            tcp dpts:22:25 reject-with icmp-port-unreachable

指定多个离散的端口(multiport模块):

# iptables -I INPUT -s 192.168.1.12  -p tcp -m multiport --dport 22,80,8080 -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 10 packets, 612 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            multiport dports 22,80,8080 reject-with icmp-port-unreachable
#禁止192.168.1.12访问本机22,80,8080的端口
# iptables -I INPUT -s 192.168.1.12  -p tcp -m multiport --dport 22,80:88 -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 10 packets, 612 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       192.168.1.12         0.0.0.0/0            multiport dports 22,80:88 reject-with icmp-port-unreachable
#禁止192.168.1.12访问本机22,80到88之间的端口

指定一段连续的IP地址范围(iprange模块,--src-range表示源地址所在范围,--dst-range表示目标地址所在范围):

# iptables -t filter -I INPUT -m iprange --src-range 192.168.1.12-192.168.1.15 -j DROP
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 18 packets, 1108 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            source IP range 192.168.1.12-192.168.1.15
#当源IP范围在192.168.1.12到192.168.1.15之间则丢弃报文

匹配报文中的字符串(string模块,--algo bm表示使用bm算法去匹配指定的字符串,还有kmp可选;--string “OOXX” 表示要匹配的字符串为”OOXX”):

# curl 192.168.1.11
hello world
# curl 192.168.1.11/test/index.html
Hello World
# iptables -t filter -I INPUT -m string --algo bm --string "hello world" -j REJECT
# iptables -t filter -nvL INPUT
Chain INPUT (policy ACCEPT 74 packets, 4332 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            STRING match  "hello world" ALGO name bm TO 65535 reject-with icmp-port-unreachable
# curl 192.168.1.11
^Z
[6]+  Stopped                 curl 192.168.1.11
# curl 192.168.1.11/test/index.html
Hello World


#如果返回的报文中含有"hello world",则禁止进入INPUT链

指定时间范围(time模块,--timestart参数用于指定起始时间,--timestop参数用于指定结束时间,--weekdays参数指定周几,--monthdays参数指定每个月的那一天。):

# iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 00:00:00 --timestop 06:00:00 -j REJECT
 iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 23 packets, 2460 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 TIME from 00:00:00 to 06:00:00 UTC reject-with icmp-port-unreachabl
#指定每天零点到早上六点不能浏览网页,注意时区问题,time模块采用UTC时区

#iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j DROP

#  iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 8 packets, 1448 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 TIME on Sat,Sun UTC
#每周末不能浏览网页


# iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 23,24  -j DROP
# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 5 packets, 836 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 TIME on 23rd,24th UTC
#每月的23,24号不能浏览网页


#--monthdays与--weekdays可以取反,其他参数不能取反。

限制每个IP链接到服务端的链接数量(connlimit模块,--connlimit-above 2表示每个IP的链接数量上限为2,--connlimit-upto参数表示链接数量未达到指定的连接数量,相当于“! --connlimit-above”;--connlimit-mask参数表示掩码):

# iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT

# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 186 packets, 11392 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 #conn src/32 > 2 reject-with icmp-port-unreachable

# iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 --connlimit-mask 24 -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 22 packets, 1356 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 #conn src/24 > 2 reject-with icmp-port-unreachable
#--connlimit-mask 24表示限制C类网段

限制报文到达速率(limit模块,--limit-burst表示空闲时可放行的包的数量,默认值为5):

# iptables -t filter -I INPUT -p icmp -m limit --limit-burst 1 --limit 10/minute -j ACCEPT
# iptables -A INPUT -p icmp -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 12 packets, 736 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 10/min burst 1
    0     0 REJECT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
#每分钟最多放行10个包,就相当于每6秒钟最多放行一个包,因为默认策略是ACCEPT,所以需要追加第六秒之前的包的处理动作
#--limit单位可选:/sencond,/minute,/hour,/day

匹配tcp报文头部的标识位(--tcp-flags):

# iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 28 packets, 1728 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x3F/0x02 reject-with icmp-port-unreachable


#--tcp-flags第一个参数是匹配tcp报文头部的标志位,第二个参数是表示哪些标志位的值必须为1,其他标志位为0

#所以上面的命令代表匹配报文tcp头中的SYN、ACK、FIN、RST、URG、PSH这些标志位,SYN标志位为1,其他标志位为0

#可以简写成--tcp-flags ALL SYN

匹配报文状态(state模块,--state参数可选NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED):

# iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -t filter -A INPUT -j REJECT
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   34  2092 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

黑白名单机制

我们可以利用iptables的默认策略制作黑白名单:

  • 黑名单:默认策略为ACCEPT,增加的规则动作为DROP或者REJECT,只有匹配到的报文会被拒绝,其他放行
  • 白名单:默认策略为DROP,增加的动作为ACCEPT,只有匹配到的报文会被放行,其他会被拒绝(白名单误清除规则后会导致将自己所在外边)

自定义链

自定义链不能直接使用,需要被默认链引用

创建自定义链(-N参数):

# iptables -t filter -N WEB
# iptables -nvL
Chain INPUT (policy ACCEPT 48 packets, 2784 bytes)
 pkts bytes target     prot opt in     out     source               destination         

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

Chain OUTPUT (policy ACCEPT 25 packets, 1980 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination         

自定义链配置规则:

# iptables -t filter -I WEB -s 192.168.1.12 -j REJECT
# iptables -nvL WEB
Chain WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       192.168.1.12         0.0.0.0/0            reject-with icmp-port-unreachable

在INPUT链中引用自定义链(-j参数):

# iptables -I INPUT -p tcp --dport 80 -j WEB
# iptables -nvL
Chain INPUT (policy ACCEPT 40 packets, 2320 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 WEB        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

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

Chain OUTPUT (policy ACCEPT 21 packets, 1660 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain WEB (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       192.168.1.12         0.0.0.0/0            reject-with icmp-port-unreachable

#WEB自定义链信息显示被引用一次

重命名自定义链名称(-E参数):

# iptables -E WEB WEB_RENAME
# iptables -nvL
Chain INPUT (policy ACCEPT 22 packets, 1460 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 WEB_RENAME  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

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

Chain OUTPUT (policy ACCEPT 12 packets, 1204 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain WEB_RENAME (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 REJECT     all  --  *      *       192.168.1.12         0.0.0.0/0            reject-with icmp-port-unreachable

删除自定义链:

#删除引用链
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 62 packets, 3780 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 WEB_RENAME  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
# iptables -D INPUT 1
#清空自定义链
# iptables -F WEB_RENAME
#删除自定义链
# iptables -X WEB_RENAME


#不按照这个流程去删除会产生以下错误
# iptables -X WEB
iptables: Too many links.

# iptables -X WEB
iptables: Directory not empty.

动作用法

动作和匹配条件一样,也有基础和扩展的区别,但是扩展动作可以直接使用,不用像使用扩展匹配条件那样指定模块。

ACCEPT和DROP属于基础动作。

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。

# iptables -t filter -I INPUT -p icmp -j REJECT --reject-with icmp-host-unreachable
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 40 packets, 2320 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-unreachable

LOG动作记录报文信息(--log-level指定记录日志的日志级别,可用级别有emerg,alert,crit,error,warning,notice,info,debug;--log-prefix给记录到的相关信息添加标签之类的信息,以便区分各种记录到的报文信息,方便在分析时进行过滤,值不能超过29个字符。):

# iptables -I INPUT -p tcp --dport 22 -j LOG
# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 51 packets, 3144 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   50  2900 LOG        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 LOG flags 0 level 4
# tail -f /var/log/messages 
Nov 18 16:48:40 server01 kernel: IN=enp0s3 OUT= MAC=08:00:27:96:9e:12:80:fa:5b:2d:8a:ef:08:00 SRC=192.168.1.238 DST=192.168.1.11 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=17026 DF PROTO=TCP SPT=55664 DPT=22 WINDOW=4102 RES=0x00 ACK URGP=0 

SNAT动作将来自于内网网段(172.25.0.0/16)的报文源地址转为公网IP(192.168.1.12)

# iptables -t nat -A POSTROUTING -s 172.25.0.0/16 -j SNAT --to-source 192.168.1.12

DNAT动作将通过外网(192.168.1.12:99)访问内网主机(172.25.0.9:22)

# iptables -t nat -I PREROUTING -d 192.168.1.12 -p tcp --dport 99 -j DNAT --to-destination 172.25.0.9:22

MASQUERADE动作能够正常的、动态的将内部主机的报文的源IP映射为对应的公网IP:

# iptables -t nat -I POSTROUTING -s 172.25.0.0/16 -o enp0s3 -j MASQUERADE

REDIRECT动作可以在本机上进行端口映射

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

NAT功能需要开启Linux主机的核心转发功能

List of learning reference documents

  • https://www.zsythink.net/archives/tag/iptables/