在 Linux 中,最核心的防火墙管理工具是 Netfilter 框架,Netfilter 是 Linux 内核中的一个框架,它允许在网络数据包通过协议栈的不同阶段时进行截取、检查、修改和丢弃,而与它交互的主要命令行工具是 iptablesnftables

许多 Linux 发行版还提供了更高级、更易于使用的前端工具,来简化防火墙的配置。 Ubuntu 及其衍生版本上默认的防火墙管理工具UFW, Red Hat 系列发行版(如 CentOS, RHEL, Fedora)上默认的动态防火墙管理工具Firewalld。

1. iptables

iptables 是一个非常强大且灵活的命令行工具,用于配置 Linux 内核中的 Netfilter 数据包过滤规则。它通过定义一系列的规则来决定如何处理网络流量。

工作原理: iptables 组织规则成**表 (tables),每个表包含多个链 (chains)**。数据包根据其类型(例如,传入、传出、转发)经过不同的链,并根据链中的规则进行匹配和处理。

表(Tables)

iptables 的规则被组织成不同的“表”,每个表处理特定类型的流量。主要的表有:

  • filter 表(默认):这是最常用的表,用于过滤数据包,决定是否允许数据包通过(ACCEPT)、丢弃(DROP)或拒绝(REJECT)。
  • nat 表(网络地址转换):用于修改数据包的源 IP 或目标 IP/端口。常用于端口转发、共享互联网连接(NAT)。
  • mangle 表(数据包修改):用于修改数据包的某些部分(如 TOS 字段),以便进行流量整形或 QoS。
  • raw:用于在数据包被连接跟踪(conntrack)处理之前进行操作,主要用于排除某些流量不被连接跟踪。
  • security表:用于 SELinux 安全策略(较少用)

链(Chains)

每个表都包含一些内置的“链”,它们代表数据包在通过 Netfilter 框架时可能经过的不同点。用户也可以创建自定义链。

  • INPUT:处理进入本机的数据包(目标是本机)。
  • OUTPUT:处理从本机发出的数据包。
  • FORWARD:处理经过本机转发到其他目的地的数据包(例如路由器或网关)。
  • PREROUTING:在数据包到达路由决策点之前处理(主要在 natmangle 表中使用)。
  • POSTROUTING:在数据包离开路由决策点之后处理(主要在 natmangle 表中使用)。

规则(Rules)

每条规则都定义了匹配数据包的条件和满足条件时要执行的动作(Target/Action)。规则是按顺序处理的,一旦数据包匹配了某条规则,并且该规则的动作是终结性的(如 ACCEPT, DROP, REJECT),那么数据包就不会再匹配同一链中的后续规则。

动作/目标(Targets/Actions)

当一个数据包匹配到一条规则时,就会执行一个动作。用 -j--jump

  • **ACCEPT**:允许数据包通过。
  • **DROP**:默默地丢弃数据包,不给发送方任何响应。发送方会超时。
  • **REJECT**:拒绝数据包,并向发送方返回一个错误信息(例如 ICMP “Port Unreachable”)。发送方会立即知道被拒绝。
  • **LOG**:记录匹配数据包的信息到系统日志,然后继续匹配下一条规则。
  • SNAT (Source NAT):修改数据包的源 IP 地址(在 nat 表的 POSTROUTING 链中使用)。
  • DNAT (Destination NAT):修改数据包的目标 IP 地址(在 nat 表的 PREROUTING 链中使用)。
  • **MASQUERADE**:SNAT 的特殊形式,自动使用传出接口的 IP 地址(常用于动态 IP 地址的 NAT)。
  • **RETURN**:停止在当前链中处理,返回到调用它的上一个链。
  • **JUMP (跳转到自定义链)**:将数据包的处理权转移到用户自定义的链中。

iptables 命令基本语法

1
iptables [-t table] <command> [chain] [rule-specification] [target]
  • -t table: 指定要操作的表(filternatmangleraw)。如果省略,默认为 filter

  • command: 要执行的操作,如添加规则、删除规则、列出规则等。

  • chain: 要操作的链(INPUTOUTPUTFORWARD 等)。

  • rule-specification: 匹配数据包的条件。

  • target: 匹配成功后要执行的动作

基础操作命令(command)

  • -A--append:追加规则到链末尾
  • -I--insert:插入规则(默认在首位)
  • -D--delete:删除规则
  • -R--replace:替换已有规则
  • -L--list:列出规则
  • -F--flush:清空链中所有规则
  • -X--delete-chain:删除自定义链
  • -N--new-chain:新建自定义链
  • -P--policy:设置默认策略(ACCEPT / DROP)
  • -Z--zero:清空计数器

常用命令操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 列出所有规则(默认filter表)
iptables -L

# 列出指定表的规则
iptables -t nat -L -v # -v显示更详细信息,--line-numbers 显示行号

# 添加规则(追加到链的末尾)
iptables -A INPUT -s 192.168.31.10 -j DROP

# 插入规则(指定位置)
iptables -I INPUT 1 -s 192.168.31.10 -j ACCEPT # 在INPUT链的第一行插入

# 删除规则
iptables -D INPUT -s 192.168.31.10 -j DROP
iptables -D INPUT 5 # 可iptables -L --line-numbers查看行号

# 清空指定链的所有规则
iptables -F INPUT
# 清空所有表的所有规则
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t raw -F

# 一次性清空所有表
iptables -F # 清空 filter
iptables -X # 删除所有自定义链
iptables -Z # 清空所有链的计数器
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X

# 设置链的默认策略(非常重要)
iptables -P INPUT DROP # 默认丢弃所有进入的数据包
iptables -P FORWARD DROP # 默认丢弃所有转发的数据包
iptables -P OUTPUT ACCEPT # 默认允许所有发出的数据包

注意: 在设置 DROP 策略之前,请确保你已经添加了允许 SSH 连接的规则,否则你可能会将自己锁在服务器之外!最佳实践是先设置允许 SSH,再设置 DROP 策略。

匹配条件(Match Conditions)

网络地址/端口相关:

  • -s--source:指定源 IP 地址

  • -d--destination:指定目标 IP 地址

  • -p--protocol:协议(如 tcp、udp、icmp、all.)

    • iptables -A INPUT -p tcp -j ACCEPT
  • --sport--source-port:指定源端口

  • --dport--destination-port:指定目标端口

    • iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许ssh端
  • --icmp-type type: 指定 ICMP 类型(例如 echo-request for ping)。

    • iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # 允许 ping

接口相关:

  • -i--in-interface:入接口名(如 eth0)

    • iptables -A INPUT -i eth0 -j DROP
  • -o--out-interface:出接口名(如 wlan0)

扩展模块调用:

iptables 中,-m 选项用于加载扩展匹配模块(Extension Matching Modules)。Netfilter 框架的强大之处在于其模块化设计。核心的 iptables 命令和内置的匹配条件(如 -p 协议、-s 源IP、--dport 目标端口等)是基础,但如果需要更复杂的匹配逻辑,就需要加载特定的模块。

这些模块允许你根据各种网络流量特性进行匹配,而这些特性是基本 iptables 规则无法直接识别的。当你使用 -m 选项时,你实际上是在告诉 iptables 加载一个特定的内核模块,该模块包含了额外的匹配条件。

1
iptables ... -m <module_name> [module_options] ...
  • -m <module_name>: 指定要加载的扩展匹配模块的名称。

  • [module_options]: 该模块特有的匹配选项。不同的模块会有不同的选项。

常用扩展匹配模块及其应用:

1. state 模块(连接跟踪)

这是最常用和最重要的模块之一,用于基于数据包的连接状态进行匹配。Netfilter 的连接跟踪(conntrack)机制会追踪所有网络连接的状态。

  • 核心选项: --state <state1>[,<state2>,...]
  • 状态类型:
    • NEW: 数据包是新连接的第一个数据包。
    • ESTABLISHED: 数据包属于已经建立的连接。
    • RELATED: 数据包是与现有连接相关的新连接(例如,FTP 数据传输连接,或 nf_conntrack_irc 等辅助模块识别的协议)。
    • INVALID: 数据包无法识别或无效,可能包含错误或无法跟踪。
  • 典型应用场景: 允许所有已建立和相关连接,只对新连接进行严格限制。这是构建安全防火墙的基础,因为你通常希望允许服务器已经主动发起的连接(例如,服务器访问外部数据库或下载更新)的响应流量返回。
1
2
3
4
5
6
7
# 允许所有已建立和相关连接进入和离开
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# 允许特定端口的新连接(例如SSH)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
# 如果 INPUT 链默认策略是 DROP,则所有其他 NEW 连接都会被丢弃
1
2
3
4
# 允许新连接和建立连接的用户,防止SYN flood攻击
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# 出站回应
iptables -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
2. limit 模块(速率限制)

用于限制匹配到的数据包的速率,防止某些类型的洪水攻击或资源滥用。

  • 核心选项:

    • --limit <rate>: 平均速率,例如 5/minute(每分钟 5 个包),1/s(每秒 1 个包)。
    • --limit-burst <number>: 初始峰值,允许短时间内超过平均速率的包数。默认是 5。
  • 典型应用场景: 防止 SSH 暴力破解尝试:限制来自同一源 IP 的 SSH 连接尝试速率。

1
2
3
4
5
# 限制每分钟最多 5 个新的 SSH 连接尝试,峰值允许 10 个
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m limit --limit 5/minute --limit-burst 10 -j ACCEPT
# 丢弃超过限制的 SSH 连接尝试
iptables -A INPUT -p tcp --dport 22 -j DROP

3. multiport 模块(多端口匹配)

允许你在一跳规则中匹配多个不连续的端口。

  • 核心选项:
    • --dports <port1>[,<port2>,...]: 匹配多个目标端口。
    • --sports <port1>[,<port2>,...]: 匹配多个源端口。
  • 典型应用场景: 开放常用 Web 服务端口:一次性允许 HTTP 和 HTTPS 流量。
1
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
4. mac 模块(MAC 地址匹配)

根据数据包的源 MAC 地址进行匹配。通常用于局域网内部的访问控制。

  • 核心选项: --mac-source <MAC_address>
  • 典型应用场景: 只允许特定设备访问本机
1
2
iptables -A INPUT -m mac --mac-source 00:11:22:33:44:55 -j ACCEPT
iptables -A INPUT -j DROP # 拒绝其他所有MAC地址
5. time 模块(时间匹配)

根据一天中的时间或一周中的某天匹配数据包。

  • 核心选项:
    • --timestart HH:MM:SS
    • --timestop HH:MM:SS
    • --weekdays <Day1>[,<Day2>,...] (Mon, Tue, Wed, Thu, Fri, Sat, Sun)
    • --monthdays <Day1>[,<Day2>,...] (1-31)
  • 典型应用场景: 只允许在工作时间访问管理端口
1
2
3
iptables -A INPUT -p tcp --dport 2222 -m time --timestart 09:00:00 --timestop 17:00:00 --weekdays Mon,Tue,Wed,Thu,Fri -j ACCEPT
# 拒绝在非工作时间访问
iptables -A INPUT -p tcp --dport 2222 -j DROP
6. iprange 模块(IP 范围匹配)

允许你匹配一个 IP 地址范围,而不是单个 IP 或 CIDR。

  • 核心选项:
    • --src-range <IP-IP>: 源 IP 范围。
    • --dst-range <IP-IP>: 目标 IP 范围。
  • 典型应用场景: 允许一个连续 IP 范围访问服务
1
iptables -A INPUT -p tcp --dport 80 -m iprange --src-range 192.168.1.100-192.168.1.150 -j ACCEPT
7. comment模块 规则注释

在管理复杂的 iptables 规则集时,规则的可读性和维护性变得至关重要。comment 模块允许你为每条 iptables 规则添加一段描述性的文本注释。这些注释不会影响规则的匹配逻辑或性能,但它们对于理解规则的目的、创建者和修改日期等信息极其有用。

  • -m comment: 加载 comment 扩展匹配模块。

  • --comment "<your_comment_text>": 指定要添加到规则的注释文本。注释文本必须用引号括起来,以防包含空格或其他特殊字符。

当你添加一条新规则时,立即为其添加注释是一个好习惯。

1
2
3
4
5
6
7
8
# 允许来自特定IP的SSH连接
iptables -A INPUT -p tcp --dport 22 -s 203.0.113.100 -m comment --comment "Allow SSH from trusted_admin_ip" -j ACCEPT

# 允许Web服务HTTP和HTTPS流量
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m comment --comment "Allow HTTP/HTTPS traffic" -j ACCEPT

# 默认拒绝所有其他入站连接,以增强安全性
iptables -A INPUT -j DROP -m comment --comment "Default DROP for all other INPUT traffic"
1
2
3
# 使用 -L 选项列出规则时,如果规则包含注释,注释信息会自动显示。
iptables -L -v
iptables -L -v --line-numbers

不同版本的 iptables 或内核可能对注释的长度有隐式或显式限制。通常,保持注释简洁明了是最佳实践。在部署任何新规则时,始终附带清晰的注释,说明规则的用途、相关的服务或应用程序、以及创建者/日期。

1
2
# 允许公司内部子网访问Jenkins管理端口
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/24 -m comment --comment "Allow Jenkins from internal dev network (Added by John Doe 2025-07-01)" -j ACCEPT

可以使用 man iptables-extensions 命令来查看所有可用的 iptables 扩展模块及其详细选项。

NAT表

natiptables 中专门用于执行网络地址转换(Network Address Translation, NAT)操作。NAT 是一种网络技术,用于修改 IP 数据包的源 IP 地址目标 IP 地址(有时也包括端口号),从而实现 IP 地址的复用、隐藏内部网络结构或进行服务重定向。尤其在内网设备访问外网、透明代理、端口转发、负载均衡等场景中扮演极为关键的角色。

不会过滤或阻止数据包,只会在特定阶段修改数据包头部信息。

nat 表的核心功能

nat 表的主要功能就是修改数据包的 IP 地址和/或端口。它通常用于以下场景:

  1. 共享互联网连接(MASQUERADE/SNAT):

    让多个内部私有 IP 地址的设备通过一个公共 IP 地址访问互联网。这是家庭路由器和小型办公室网络中最常见的 NAT 用途。

  2. 端口转发/端口映射(DNAT):

    将来自外部网络的特定端口请求重定向到内部网络的特定主机和端口。这允许外部用户访问内部服务器(如 Web 服务器、SSH 服务器),即使这些服务器没有公共 IP 地址。

  3. 负载均衡(LVS/HAProxy 等通常也会用到 NAT 模式):

    虽然 iptables 本身不提供完整的负载均衡功能,但 DNAT 可以作为底层机制之一,将请求分发到后端服务器。

nat 表的链(Chains)

nat 表有三条内置链,它们在数据包生命周期的不同阶段执行 NAT 操作:

  1. PREROUTING

    • 何时处理? 在数据包到达防火墙并进行路由决策之前
    • 主要用途:用于目标地址转换(DNAT)。它在数据包被路由到本地进程或转发到其他网络之前,修改数据包的目标 IP 地址和/或端口。这意味着数据包的目标在进入防火墙后立即被改变,后续的路由决策将基于这个新的目标地址。
  2. OUTPUT

    • 何时处理? 处理由本机生成的数据包。
    • 主要用途:用于修改本机进程发出的数据包的目标 IP 地址和/或端口。例如,如果本机上的服务需要连接到某个外部地址,但希望连接到另一个地址,可以在这里进行 DNAT。这个链相对不那么常用,因为大部分 DNAT 都是针对外部入站流量的。
    1
    iptables -t nat -A OUTPUT -p tcp --dport 80 -d 1.1.1.1 -j DNAT --to-destination 127.0.0.1:8080
  3. POSTROUTING

    • 何时处理? 在数据包即将离开防火墙并经过路由决策之后
    • 主要用途:用于源地址转换(SNAT 或 MASQUERADE)。它在数据包被路由到传出接口之后,修改数据包的源 IP 地址和/或端口。这是实现内网共享外网的主要链,因为数据包离开防火墙时,其源 IP 已经被修改为防火墙的公共 IP。

nat 表的常用动作/目标(Targets/Actions)

nat 表中,最常用的动作是:

  • DNAT (Destination Network Address Translation):

    修改数据包的目标 IP 地址和/或端口。通常在 PREROUTING 链中使用。

    • 选项:--to-destination [ipaddr[-ipaddr]][:port[-port]]

    示例:将所有访问本机 80 端口的请求转发到内部服务器 192.168.1.100 的 8080 端口。

    1
    iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
  • SNAT (Source Network Address Translation):

    修改数据包的源 IP 地址和/或端口。通常在 POSTROUTING 链中使用。主要用于将私有 IP 地址转换为公共 IP 地址,以便访问外部网络。

    • 选项:--to-source [ipaddr[-ipaddr]][:port[-port]]

    示例:将所有从内部网络 192.168.1.0/24 发出的数据包的源 IP 修改为本机公共 IP 203.0.113.1

    1
    iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.1

    这里的 eth0 是连接到互联网的接口。

  • MASQUERADE:

    这是 SNAT 的一个特殊形式,当防火墙的公共 IP 地址是动态分配时(如 ADSL 拨号或 DHCP 获取 IP)使用。它会自动选择传出接口的当前 IP 地址作为源地址,现代更常用。

    • 没有 to-source 选项,因为它会自动获取 IP。

    示例:允许内部网络共享通过 eth0 接口的动态 IP 访问互联网。

    1
    iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

nat 表与 filter 表的关系(重要!)

理解 nat 表和 filter 表的工作顺序至关重要,因为它们处理数据包的阶段不同:

  1. PREROUTING (nat):在路由前进行 DNAT,改变数据包的目标
  2. 路由决策(Routing Decision):系统根据数据包的当前目标 IP(可能已被 DNAT 修改过)决定是将其转发到其他主机(经过 FORWARD 链)还是交付给本地进程(经过 INPUT 链)。
  3. **INPUT (filter)**:处理目标是本机的数据包。
  4. **FORWARD (filter)**:处理目标是其他主机的数据包。
  5. **OUTPUT (filter)**:处理本机发出的数据包。
  6. POSTROUTING (nat):在路由后进行 SNAT,改变数据包的

关键点:

  • DNAT 发生在路由之前:这意味着在 INPUTFORWARD 链中,数据包的目标 IP 已经是经过 DNAT 修改后的内部 IP。
  • SNAT 发生在路由之后:这意味着在 OUTPUTFORWARD 链中,数据包的源 IP 仍然是原始的内部 IP,只有在数据包即将离开时才被 SNAT 修改。

实际应用场景

场景 1:端口转发(Port Forwarding / DNAT)

你有一台 Web 服务器 192.168.1.100 在内网运行,希望外部用户通过你的公共 IP 203.0.113.1 访问它。

  1. 确保 IP 转发已启用:

    编辑 /etc/sysctl.conf 文件,将 net.ipv4.ip_forward 设置为 1。

    Code snippet

    1
    2
    # /etc/sysctl.conf
    net.ipv4.ip_forward = 1

    然后执行 sudo sysctl -p 使其生效。

  2. 添加 DNAT 规则(PREROUTING 链):

    将所有进入 eth0 接口(你的公共网络接口)的、目标端口为 80 的 TCP 请求,其目标 IP 修改为 192.168.1.100,端口修改为 80。

    1
    iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
  3. 添加 filter 规则(FORWARD 链):

    允许这些被 DNAT 后的数据包通过防火墙进行转发。

    1
    2
    iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    # 注意:如果 FORWARD 链的默认策略是 DROP,这条规则必不可少。
  4. 添加 SNAT/MASQUERADE 规则(POSTROUTING 链,可选但强烈推荐):

    确保内网服务器 192.168.1.100 返回的响应能够正确回到客户端。如果没有这条规则,Web 服务器可能会直接将响应发回给客户端,而客户端只知道公共 IP,导致连接中断。

    1
    2
    3
    4
    5
    # 使用 SNAT 如果你的公共IP是固定的
    iptables -t nat -A POSTROUTING -o eth0 -p tcp -d 192.168.1.100 --dport 80 -j SNAT --to-source 203.0.113.1

    # 或者使用 MASQUERADE 如果你的公共IP是动态的 (更常见)
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

    这里的 POSTROUTING 规则将内部 Web 服务器发出的响应包的源 IP 修改为防火墙的公共 IP,这样客户端就能正确接收到响应。

场景 2:共享互联网连接(MASQUERADE)

你有一台 Linux 服务器作为网关,内部网络 192.168.1.0/24 的机器需要通过它访问互联网。

  1. 确保 IP 转发已启用(同上)。

  2. 添加 MASQUERADE 规则(POSTROUTING 链):

    将所有从内部网络 192.168.1.0/24 发出,并准备通过 eth0 接口(连接外部网络的接口)的数据包,其源 IP 地址动态修改为 eth0 的当前 IP 地址。

    1
    iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
  3. 添加 filter 规则(FORWARD 链):

    允许内部网络的数据包通过防火墙进行转发。

    1
    2
    iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT # eth1 是内网接口
    iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT # 允许已建立和相关连接的回包

还可以透明代理(拦截 HTTP 到代理端口):

1
2
# 将所有 80 端口流量转发到本地 3128(Squid)
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128

查看规则:

1
iptables -t nat -L -v --line-number

iptables 配置是存储在内存中的,系统重启后会丢失。需要将规则保存到文件,并在系统启动时恢复。

  • iptables-save → 保存当前规则到 stdout(可重定向备份)
  • iptables-restore → 从文件中恢复规则
  • iptables -t nat -L → 指定 nat 表查看规则(-t--table
  • Ubuntu/Debian保存规则常用:
    • sudo netfilter-persistent save
    • sudo netfilter-persistent reload

保存路径可能因发行版而异。通常是 /etc/sysconfig/iptables (RHEL/CentOS) 或 /etc/iptables/rules.v4 (Debian/Ubuntu)。

mangle 表

iptablesmangle 表是用于修改网络包内容或标记网络包的高级功能表,专注于对数据包的深度处理,常用于 流量标记(mark)TOS/DSCP 设置TTL 修改丢弃流量等操作。

它不像 filter 表那样控制是否允许数据包通过,也不像 nat 表那样做地址转换,而是对包本身的某些字段做修改或添加信息(比如打标记),供后续内核模块(如 tc 流控、策略路由)使用。

mangle 表比 filternat 表拥有更多的内置链,因为它需要在数据包的整个生命周期中进行更细粒度的修改,它拥有所有 5 条内置链。

mangle 表的常用动作/目标(Targets/Actions)

mangle 表中,最常用的动作是:

  • TOS (Type of Service) / DSCP (Differentiated Services Code Point):

    修改 IP 头中的 TOS 字段(或更现代的 DSCP 字段)。

    • 选项:--set-tos <value>--set-dscp <value>

    • 示例:将 SSH 流量的 DSCP 值设置为 EF (Expedited Forwarding),以获得优先级。

      1
      iptables -t mangle -A PREROUTING -p tcp --dport 22 -j DSCP --set-dscp 46
  • TTL (Time To Live):

    修改 IP 头中的 TTL 值。

    • 选项:--ttl-set <value> (设置为特定值), --ttl-inc <value> (增加), --ttl-dec <value> (减少)

    • 示例:将所有出站数据包的 TTL 值设置为 64。

      1
      iptables -t mangle -A POSTROUTING -o eth0 -j TTL --ttl-set 64

      (这有时用于使服务器的流量看起来像来自普通的 Linux 桌面,而不是专业的路由器或服务器,因为它会将 TTL 重置到操作系统的默认出站 TTL。)

  • MARK:

    在数据包上设置一个 Netfilter 标记(一个整数值)。这个标记不会实际修改数据包的 IP 头,它只存在于内核内部,用于策略路由 (ip rule) 或 tc (Traffic Control) 等后续处理。

    • 选项:--set-mark <value> (设置标记), --and-mark <value> (按位与), --or-mark <value> (按位或)

    • 示例:标记所有来自特定内部 IP 的 Web 流量,以便后续策略路由将其路由到特定的出口。

      1
      2
      # 在 PREROUTING 链标记数据包
      iptables -t mangle -A PREROUTING -s 192.168.1.10 -p tcp --dport 80 -j MARK --set-mark 10

      然后,你可以在策略路由中使用这个标记:

      1
      2
      ip rule add fwmark 10 table 100
      ip route add default via <gateway_ip> dev <interface> table 100
  • CONNMARK:

    对整个连接设置一个标记,而不是仅仅针对单个数据包。一个连接中的所有数据包都会继承这个标记。这非常有用,因为它允许你根据连接的初始数据包来标记整个会话。

    • 选项:--set-mark <value>, --save-mark (从数据包标记保存到连接标记), --restore-mark (从连接标记恢复到数据包标记)

    • 示例:将所有来自某个源 IP 的新连接标记为 20,并对该连接的所有后续数据包都应用此标记。

      1
      2
      3
      4
      5
      6
      # 在 PREROUTING 链,对 NEW 状态的连接打上标记
      iptables -t mangle -A PREROUTING -s 192.168.1.20 -m state --state NEW -j CONNMARK --set-mark 20

      # 在后续的规则中,可以恢复这个标记到数据包,然后根据数据包标记进行处理
      iptables -t mangle -A PREROUTING -m connmark --mark 20 -j CONNMARK --restore-mark
      # 然后可以在策略路由中使用 mark 20

mangle 表的执行顺序

mangle 表的规则在数据包通过 Netfilter 框架时,会在 raw 表之后,nat 表和 filter 表之前或之后执行,具体取决于它们所在的链:

入站数据包顺序:

raw -> mangle (PREROUTING) -> nat (PREROUTING) -> 路由决策 -> mangle (INPUT) -> filter (INPUT) -> 本地进程

转发数据包顺序:

raw -> mangle (PREROUTING) -> nat (PREROUTING) -> 路由决策 -> mangle (FORWARD) -> filter (FORWARD) -> mangle (POSTROUTING) -> nat (POSTROUTING)

出站数据包顺序:

本地进程 -> raw -> mangle (OUTPUT) -> nat (OUTPUT) -> 路由决策 -> mangle (POSTROUTING) -> nat (POSTROUTING)

关键点:

  • **PREROUTING**:最先处理入站数据包,常用于标记或修改在路由或 NAT 前需要处理的数据包。
  • **POSTROUTING**:最晚处理出站数据包,常用于修改离开系统前的数据包(如 TTL)。
  • **MARKCONNMARK**:这些标记主要在内核内部使用,并不会改变数据包的物理内容,但在策略路由和流量控制中非常强大。

实际应用场景

  1. 为 VoIP 流量设置高优先级(QoS):

    如果你在服务器上运行 VoIP 服务,可以标记 SIP/RTP 流量,让路由器优先处理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
       # 标记SIP信令流量
    iptables -t mangle -A PREROUTING -p udp --dport 5060 -j DSCP --set-dscp 46
    # 标记RTP媒体流
    iptables -t mangle -A PREROUTING -p udp -m multiport --dports 10000:20000 -j DSCP --set-dscp 46

    (然后在路由器或其他 Qos 设备上配置根据 DSCP 值进行优先级转发)

    2. 实现策略路由:

    让来自特定源 IP 或特定服务的流量走不同的出口或路由表。



    ```bash
    # 在 mangle 表的 PREROUTING 链中为来自特定源 IP 的流量设置标记
    iptables -t mangle -A PREROUTING -s 192.168.1.50 -j MARK --set-mark 100

    # 将标记保存到连接,以便回包也能匹配(可选,但通常推荐)
    iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

    # 然后在 ip rule 中添加规则:
    sudo ip rule add fwmark 100 table 10
    # 定义路由表 10
    sudo ip route add default via <gateway_for_table_10> dev <interface_for_table_10> table 10



    3. 防止 TTL 泄漏/修改:

    在某些特定场景下,你可能不希望服务器的流量暴露其真实的操作系统类型(因为不同的操作系统有默认的 TTL 值),或者需要修改 TTL 以绕过某些网络设备。

    ```bash
    # 将所有出站TCP流量的TTL设置为64(Linux桌面默认值)
    iptables -t mangle -A POSTROUTING -p tcp -j TTL --ttl-set 64
  2. 负载均衡或连接亲和性(结合 ipvs 或 conntrack):

    mangle 表可以通过 MARK 和 CONNMARK 与 ipvs(IP Virtual Server)或更复杂的连接跟踪机制结合,实现更精细的负载均衡和会话保持。

查看 mangle 表规则

1
iptables -t mangle -L -v --line-numbers

iptablesmangle是一个高级且强大的工具,它允许你在数据包通过 Linux 内核协议栈的不同阶段时,对其 IP 头部进行细粒度的修改(如 TOS/DSCP、TTL)或内部标记(MARK/CONNMARK)。它本身不用于过滤或地址转换,而是作为流量控制和策略路由的预处理阶段。理解 mangle 表以及其与其他表和 Linux 网络子系统(如 ip ruletc)的交互,是实现复杂网络流量管理和 QoS 策略的关键。

2. nftables

nftables 是 Linux 内核中 Netfilter 的一个较新、更现代的包过滤框架,旨在最终取代 iptables。它提供了一个更统一和灵活的语法来处理 IPv4、IPv6、ARP 和桥接帧的规则。

  • 优点:
    • 统一的语法: 一个工具处理所有协议,简化了配置。
    • 性能提升: 更高效的规则处理。
    • 动态更新: 可以动态添加/删除规则,无需重新加载整个防火墙。
    • 更强大的集合: 支持更复杂的匹配条件。
  • 缺点: 相对较新,一些旧的教程或工具可能仍基于 iptables。

虽然 nftables 是推荐的未来方向,但由于 iptables 广泛存在且功能强大,许多系统仍然使用它或其前端。


3. 高级前端工具

为了简化防火墙管理,许多 Linux 发行版提供了更用户友好的工具,它们实际上在后台生成和管理 iptablesnftables 规则。

a. UFW (Uncomplicated Firewall)

UFW 是 Ubuntu 及其衍生版本上默认的防火墙管理工具,顾名思义,它旨在简化防火墙的配置。

  • 优点:
    • 非常简单: 命令行语法直观易懂。
    • 适合桌面和服务器: 对于常见的防火墙需求非常方便。
    • 集成应用配置文件: 许多应用(如 Apache, OpenSSH)提供 UFW 配置文件,方便一键开启/关闭端口。
  • 缺点: 对于非常复杂的定制规则,可能不如直接使用 iptablesnftables 灵活。

UFW 基本命令示例:

  • 启用 UFW: sudo ufw enable
  • 禁用 UFW: sudo ufw disable
  • 查看状态: sudo ufw status verbose
  • 允许 SSH (端口 22): sudo ufw allow sshsudo ufw allow 22/tcp
  • 允许 HTTP (端口 80): sudo ufw allow httpsudo ufw allow 80/tcp
  • 允许 HTTPS (端口 443): sudo ufw allow httpssudo ufw allow 443/tcp
  • 拒绝所有传入连接 (默认行为): sudo ufw default deny incoming
  • 删除规则: sudo ufw delete allow 22/tcp

b. Firewalld

Firewalld 是 Red Hat 系列发行版(如 CentOS, RHEL, Fedora)上默认的动态防火墙管理工具。它引入了“区域 (zones)”的概念,允许你根据网络连接的信任级别应用不同的规则集。

  • 优点:
    • 动态管理: 规则可以在不中断现有连接的情况下进行更改。
    • 区域 (Zones): 方便管理不同网络环境(例如,家庭、公共、内部)。
    • 服务和端口: 可以通过服务名(如 ssh, http)或端口号进行配置。
    • 富规则 (Rich Rules): 支持更复杂的规则定义。
  • 缺点: 比 UFW 稍微复杂一些,但比直接使用 iptables 简单。

Firewalld 基本命令示例:

  • 启动 Firewalld: sudo systemctl start firewalld
  • 启用 Firewalld (开机自启): sudo systemctl enable firewalld
  • 查看状态: sudo firewall-cmd --state
  • 查看所有区域和规则: sudo firewall-cmd --list-all-zones
  • 查看活动区域: sudo firewall-cmd --get-active-zones
  • 允许 SSH 服务 (在公共区域): sudo firewall-cmd --zone=public --add-service=ssh --permanent
  • 允许端口 80 (TCP) (在公共区域): sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
  • 重新加载 Firewalld 使规则生效: sudo firewall-cmd --reload
  • 删除规则: sudo firewall-cmd --zone=public --remove-service=ssh --permanent

如何选择?

  • 对于大多数桌面用户和简单的服务器: UFW 是一个很好的选择,因为它非常简单易用。
  • 对于 Red Hat/CentOS 用户或需要更灵活的“区域”管理: Firewalld 是推荐的。
  • 对于需要精细控制或处理复杂网络场景的资深用户/管理员: 直接使用 iptablesnftables 可能会更合适,但需要投入更多学习时间。

无论你选择哪种工具,防火墙都是保护你的 Linux 系统免受未经授权访问的关键一步。始终确保你的防火墙已启用并配置正确,只允许必要的流量通过。