1. 概念

iptables 是 Linux 系统中位于用户空间的防火墙管理工具,用于添加、删除和查看防火墙规则。它本身并不执行防火墙功能,而是将用户配置的规则传递给内核空间netfilter 框架。netfilter 负责在数据包的不同处理阶段对数据包进行实际的过滤、修改与转发处理。

image-20250513171316271

2. 功能

iptables/netfilter 具有如下功能

  • 基础的防火墙功能,对数据包放行/过滤;
  • 对数据的内容进行改写;
  • 网络地址转换(NAT)功能;

3. 四表五链

上面提到 iptables 是来操作管理规则的,然后再通过 netfilter 根据规则实际进行工作,而这个规则就是四表五链

是具有相同功能的规则的集合,主要有以下四种:

表名 作用说明
filter 默认表,用于控制数据包的“过滤”和“访问控制”,决定是否放行。
nat 网络地址转换表(Network Address Translation),如源地址/目标地址转换。
mangle 用于修改数据包的内容(如 TOS、TTL),做高级数据包调整。
raw 跳过连接跟踪(Connection Tracking),用于处理一些特殊流量。

本文主要学习实践 filter

是定义规则数据包在哪一个阶段的处理处理机制。主要有以下五个“系统链”:

链名 数据包处理阶段 说明
PREROUTING 数据包刚进入网络栈,尚未路由 适用于 natmangleraw
INPUT 目标是本机的数据包处理前 适用于 filtermangle
FORWARD 目标不是本机的数据包,中转处理阶段 适用于 filtermangle
OUTPUT 本机产生的数据包处理阶段 适用于 filternatmangleraw
POSTROUTING 路由完成、数据包即将离开本机前的最后处理阶段 适用于 natmangle

image-20250513173801872

除了 “系统链”,还可以创建一个 “自定义链”,需要注意的是 “自定义链”必须主动声明链接到 “系统链” 中,然后在 “系统链” 调用后再调用它。如果 “自定义链” 没有被任何链引用,那么相当于链条断裂了,就无法生效使用。

本文学习实践主要以 “自定义链” 为主。

是相互交叉的关系,不同上的相同的都是相互独立,并且不是所有链都有4张,不同阶段的链之间是有差异的。同时,表之间也存在优先级关系: raw –> mangle –> nat –> filter , raw 最高

表 / 链 PREROUTING INPUT FORWARD OUTPUT POSTROUTING
filter ✖️ ✖️
nat ✖️ ✖️
mangle
raw ✖️ ✖️

image-20250513173230446

查询自定义链 BLOCK_IP_ACCESS filter 表的规则

[root@centos7ait1 ~]# iptables -t filter -L BLOCK_IP_ACCESS
Chain BLOCK_IP_ACCESS (0 references)
target     prot opt source               destination         
DROP       tcp  --  192.168.21.0/24      anywhere             tcp dpt:webcache
DROP       tcp  --  192.168.1.1          anywhere             tcp dpt:http
DROP       tcp  --  public1.alidns.com   anywhere             tcp dpt:ircu-2
DROP       tcp  --  public2.alidns.com   anywhere             tcp dpt:http
DROP       tcp  --  223.5.5.0/24         anywhere             tcp dpt:http
DROP       tcp  --  45.95.59.0/24        anywhere             tcp dpt:http
DROP       tcp  --  45.95.5.16           anywhere             tcp dpt:http

参数说明:

--list    -L [chain [rulenum]] 列出指定链下的所有规则或指定序号的规则
--table -t table    table to manipulate (default: 'filter') 指定表名,默认为 `filter` 表

4. 规则

是具有相同功能的规则的集合,而规则主要包括匹配规则处理动作,根据指定规则进行条件匹配,如果匹配成功再进行相应的处理动作然后将处理后的数据交由下一流程。

4.1. 匹配规则

匹配规则分为通用规则扩展规则。通用匹配适用于所有的规则,无需依赖模块即可完成匹配检查;扩展匹配需要依赖模块来完成检查匹配。这里主要学习通用规则。

iptables 是命令行工具,下面结合参数命令进行学习:

匹配参数 说明
使用叹号对条件取反
-p,--protocol 指定协议(tcp,udp,icmp等),可使用all来指定所有协议
-s,--src,--source 指定数据包源地址,可使用IP地址、网络地址、主机名、CIDR
-d,--dst,--destination 指定目的地址
-i,--in-interface 指定数据报文流入接口,用于PREROUTING、INPUT、FORWARD
-o,--out-interface 指定数据报文流出接口,用于OUTPUT、POSTROUTING、FORWARD
--destination-port --dport 指定目的地址的端口

4.2. 处理动作

处理动作就是指定匹配大盘的数据包应该做什么动作,一般使用 -j 参数来使用。

--jump    -j target

常用的处理动作如下:

4.2.1. ACCEPT

对相匹配的数据包放行。(如果匹配到了 ACCPET 就不再匹配当前链当前表内的其他规则了)

# 表示放行目的地主机的 22 端口
iptables -I INPUT -p tcp --dport 22 -j ACCEPT

4.2.2. DROP

对相匹配的数据包直接丢弃而不返回响应。

# 表示对源地址 192.168.31.92 访问目的地址 9080 端口数据包直接丢弃
iptables -I INPUT -p tcp --dport 9080 -j DROP -s 192.168.31.92

未生效前效果:

root@xxcheng-dev:~# curl 192.168.31.178:9080 -I --connect-time 5
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1032
Connection: keep-alive
Date: Wed, 14 May 2025 01:36:31 GMT
Last-Modified: Fri, 09 May 2025 06:35:24 GMT
ETag: "681da22c-408"
Accept-Ranges: bytes
Server: APISIX/3.11.0

输入命令生效后效果:

root@xxcheng-dev:~# curl 192.168.31.178:9080 -I --connect-time 5
curl: (28) Failed to connect to 192.168.31.178 port 9080 after 5001 ms: Timeout was reached

这个时候再添加一个 ACCPET 放行,看看效果

目标主机上操作

[root@centos7ait1 ~]# iptables -I INPUT -p tcp --dport 9080 -j ACCEPT -s 192.168.31.0/24
[root@centos7ait1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  192.168.31.0/24      anywhere             tcp dpt:glrpc
DROP       tcp  --  192.168.31.92        anywhere             tcp dpt:glrpc

访问主机上访问操作

root@xxcheng-dev:~# curl 192.168.31.178:9080 -I --connect-time 5
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1032
Connection: keep-alive
Date: Wed, 14 May 2025 01:40:04 GMT
Last-Modified: Fri, 09 May 2025 06:35:24 GMT
ETag: "681da22c-408"
Accept-Ranges: bytes
Server: APISIX/3.11.0

4.2.3. REJECT

对相匹配的数据包拒绝通过,并且向请求者返回错误信息。这个处理动作只能在 INPUTFORWARDOUTPUT 链以及相关联的自定义链中进行定义。与 DROP 相比较,DROP 是直接丢弃不向请求者返回任何信息,而 REJECT 会向请求者返回错误信息。

避免上面创建的规则干扰,使用 iptables -F INPUT 命令清除 INPUT 表上的规则记录。

[root@centos7ait1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  192.168.31.0/24      anywhere             tcp dpt:glrpc
DROP       tcp  --  192.168.31.92        anywhere             tcp dpt:glrpc
[root@centos7ait1 ~]# iptables -F INPUT
[root@centos7ait1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination 

创建 REJECT 规则进行测试:

[root@centos7ait1 ~]# iptables -I INPUT -p tcp --dport 9080 -j REJECT -s 192.168.31.0/24
[root@centos7ait1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
REJECT     tcp  --  192.168.31.0/24      anywhere             tcp dpt:glrpc reject-with icmp-port-unreachable

访问效果:

root@xxcheng-dev:~# curl 192.168.31.178:9080 -I --connect-time 5
curl: (7) Failed to connect to 192.168.31.178 port 9080 after 1 ms: Couldn't connect to server

可以看到打印的规则中有一个 icmp-port-unreachable,这是表示响应的错误信息的类型,icmp-port-unreachable 是默认设置,可以通过 --reject-with 选项来自定义设置,可用类型有如下:

  • icmp-net-unreachable
  • icmp-host-unreachable
  • icmp-port-unreachable
  • icmp-proto-unreachable
  • icmp-net-prohibited
  • icmp-host-prohibited

5. 自定义链

5.1. 介绍

自定义链是指由用户手动创建的链(规则集合),不属于系统自带的 ”系统链“,但是必须被 ”系统链“ 显示声明调用才可以触发。使用自定义链有如下优点:

优点 说明
模块化管理 不同功能的规则放入不同链中,避免一条链太长。
提高可读性 每个链只处理某一类问题(如拦截 IP、开放端口等)。
易于维护与调试 修改逻辑时只需要处理某个链而非整个防火墙规则。
逻辑复用 一个自定义链可以被多个系统链引用,达到“写一次、用多次”的效果。

5.2. 命令

5.2.1. 创建自定义链

iptables -t filter -N MY_CHAIN

MY_CHAIN 表示自定义的链名,上述命令表示在 filter 表创建 MY_CHAIN 自定义链,其中 -t 可以省略,缺省值为 filter。下面操作省略 -t 操作

5.2.2. 添加规则到自定义链

iptables -A MY_CHAIN -s 192.168.1.100 -j DROP

将来源 IP 是 192.168.1.100,丢弃这个数据包。

5.2.3. 删除自定义链规则

添加规则时怎么自定义就是怎么写,然后把 -A 改成 -D 即可。

iptables -D MY_CHAIN -s 192.168.1.100 -j DROP

5.2.4. 在系统链中调用自定义链

在系统链中显示调用自定义链方法和在系统链中添加规则差不多,只是通过 -j 参数来指向自定义链

iptables -A INPUT -p tcp --dport 22 -j MY_CHAIN

所有进来的 SSH 请求(22端口)都会跳转到 MY_CHAIN 中判断是否要被拦截。

5.2.5. 清空和删除自定义链

iptables -F MY_CHAIN  # 清空规则
iptables -X MY_CHAIN  # 删除链(只能在没有其他链引用它时删除)

5.2.6. 命令总结

image-20250514104046847

操作 命令
创建链 iptables -N my_chain
添加规则 iptables -A my_chain ...
在其他链中引用 iptables -A INPUT -j my_chain
清空规则 iptables -F my_chain
删除链 iptables -X my_chain
显示规则 iptables -L my_chain --line-numbers

参考链接