强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

iptables 完全指南 / 第 01 章:Netfilter 架构与 iptables 历史

第 01 章:Netfilter 架构与 iptables 历史

本章目标:理解 Linux 数据包过滤的内核基础,掌握 iptables 的定位,了解 nftables 的演进方向。


1.1 Netfilter 框架概述

Netfilter 是 Linux 内核中的一个包过滤框架,它在内核网络协议栈的多个位置插入了钩子点(Hook Points),允许模块化的代码对经过的数据包进行检查、修改或丢弃。

1.1.1 Netfilter 的设计哲学

Netfilter 的核心设计理念是可扩展性。它不直接提供防火墙功能,而是提供一套基础设施:

用户态工具(iptables / nft)
        │
        ▼
┌─────────────────────────────────────┐
│          Netfilter 框架              │
│  ┌──────────────────────────────┐   │
│  │  钩子点 (Hook Points)        │   │
│  │  ┌──────┐ ┌──────┐ ┌──────┐ │   │
│  │  │ PRER │ │FORWD│ │ POST │ │   │
│  │  │OUTING│ │      │ │ROUTNG│ │   │
│  │  └──────┘ └──────┘ └──────┘ │   │
│  │  ┌──────┐ ┌──────┐          │   │
│  │  │INPUT │ │OUTPUT│          │   │
│  │  └──────┘ └──────┘          │   │
│  └──────────────────────────────┘   │
│  ┌──────────────────────────────┐   │
│  │  表 (Tables)                 │   │
│  │  raw → mangle → nat → filter │   │
│  └──────────────────────────────┘   │
└─────────────────────────────────────┘
        │
        ▼
   网络协议栈继续处理

1.1.2 五个钩子点

Netfilter 定义了五个标准钩子点,数据包在内核协议栈中流经这些点时,会触发注册在该钩子上的处理函数:

钩子点 触发时机 典型用途
NF_INET_PRE_ROUTING 数据包进入路由决策之前 DNAT、连接跟踪入口
NF_INET_LOCAL_IN 数据包目的是本机 INPUT 链过滤
NF_INET_FORWARD 数据包需要转发 FORWARD 链过滤
NF_INET_LOCAL_OUT 本机产生的数据包 OUTPUT 链过滤
NF_INET_POST_ROUTING 数据包离开路由决策之后 SNAT、MASQUERADE

1.1.3 数据包流向图

                        ┌─────────────────────────────────────────────┐
                        │                本机进程                      │
                        │          ┌──────────────┐                   │
                        │          │  应用程序     │                   │
                        │          └──────┬───────┘                   │
                        │                 │ OUTPUT                    │
                        │                 ▼                           │
                        │          ┌──────────────┐                   │
                        │          │  路由决策     │                   │
                        │          └──────┬───────┘                   │
                        │                 │                           │
                        │                 ▼                           │
 ┌────────┐     ┌───────┴──────┐   ┌──────────────┐   ┌──────────┐ │
 │ 网络   │────→│PRE_ROUTING   │──→│  路由决策     │──→│POST_ROUTING│─→│ 网络
 │ 接口   │     └──────────────┘   └──────┬───────┘   └──────────┘ │ │ 接口
 └────────┘                               │                         │
                                          ▼                         │
                                   ┌──────────────┐                 │
                                   │   INPUT       │                 │
                                   └──────┬───────┘                 │
                                          │                         │
                                          ▼                         │
                                   ┌──────────────┐                 │
                                   │  本机进程     │                 │
                                   └──────────────┘                 │
                                                                    │
                        ┌───────────────────────────────────────────┘
                        │
                        │  FORWARD(转发)
                        ▼
                 ┌──────────────┐
                 │  路由决策     │──→ POST_ROUTING → 网络接口
                 └──────────────┘

关键理解:数据包的"命运"在路由决策那一刻确定——是发给本机(INPUT),还是转发给其他主机(FORWARD),还是由本机发出(OUTPUT)。


1.2 iptables 的历史演进

1.2.1 从 ipchains 到 iptables

时间 事件 说明
1995 年 ipfwadm Linux 2.0 时代的防火墙工具
1999 年 ipchains Linux 2.2,引入链的概念,但不支持有状态过滤
2000 年 iptables Linux 2.4,引入表的概念、有状态过滤、NAT
2001 年 Netfilter 子系统 正式并入内核主线
2008 年 conntrack 改进 连接跟踪性能大幅优化
2014 年 nftables Linux 3.13,新一代包过滤框架进入内核
2018 年 iptables 标记为 “legacy” nftables 成为推荐方案
2020 年+ 并存期 大多数发行版同时支持两者

1.2.2 iptables 的版本和变体

变体 说明 使用场景
iptables 经典版本,操作 IPv4 传统服务器
ip6tables 操作 IPv6 IPv6 防火墙
arptables 操作 ARP 协议 ARP 过滤
ebtables 操作以太网帧 桥接网络过滤
iptables-nft nftables 后端 + iptables 语法 过渡期兼容

注意:在较新的发行版(如 Debian 10+、Ubuntu 20.04+、RHEL 8+)中,iptables 命令实际上是 iptables-nft,底层使用 nftables 内核 API。


1.3 iptables vs nftables 对比

1.3.1 架构差异

iptables 架构:
┌─────────────────────────────────────────┐
│  iptables  │ ip6tables │ arptables │ ebtables │  ← 用户态工具
├─────────────────────────────────────────┤
│  ip_tables │ ip6_tables │ arp_tables │ bridge │  ← 内核模块
├─────────────────────────────────────────┤
│              Netfilter 钩子               │
└─────────────────────────────────────────┘

nftables 架构:
┌─────────────────────────────────────────┐
│              nft 命令行工具               │  ← 统一用户态工具
├─────────────────────────────────────────┤
│           nf_tables 内核模块              │  ← 统一内核模块
├─────────────────────────────────────────┤
│              Netfilter 钩子               │
└─────────────────────────────────────────┘

1.3.2 功能对比

特性 iptables nftables
内核模块数量 多个(ip_tables、iptable_filter 等) 单一(nf_tables)
规则匹配 线性扫描 支持集合(set)和字典
原子操作 不支持(需逐条操作) 支持(整表替换)
自定义链 有限支持 原生支持
IPv4/IPv6 需要两套工具 统一处理
性能 规则多时性能下降明显 集合查找 O(1)
语法 命令行参数 类编程语言语法
调试 有限 内置追踪功能
生态成熟度 非常成熟 快速成熟中

1.3.3 语法对比示例

iptables 语法

# 允许 SSH 访问
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 默认拒绝
iptables -P INPUT DROP

等价的 nftables 语法

# 创建表和链
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

# 允许已建立的连接
nft add rule inet filter input ct state established,related accept

# 允许 SSH 访问
nft add rule inet filter input tcp dport 22 accept

1.4 适用场景分析

1.4.1 iptables 适用场景

场景 说明 推荐度
传统服务器运维 现有规则体系成熟,文档丰富 ⭐⭐⭐⭐⭐
Docker/Kubernetes 环境 容器平台深度依赖 iptables ⭐⭐⭐⭐⭐
嵌入式设备 内核较老,可能不支持 nftables ⭐⭐⭐⭐
教学与学习 概念清晰,资料多 ⭐⭐⭐⭐⭐
简单防火墙需求 规则少、逻辑简单 ⭐⭐⭐⭐

1.4.2 nftables 适用场景

场景 说明 推荐度
新项目部署 从零开始,无历史包袱 ⭐⭐⭐⭐⭐
大规模规则集 集合查找性能优势明显 ⭐⭐⭐⭐⭐
多协议环境 IPv4/IPv6 统一管理 ⭐⭐⭐⭐⭐
复杂策略 需要编程式逻辑 ⭐⭐⭐⭐
高频规则变更 原子操作,避免规则闪烁 ⭐⭐⭐⭐⭐

1.4.3 企业场景:如何选择?

                    ┌──────────────────┐
                    │  是否有现有 iptables │
                    │  规则需要维护?      │
                    └────────┬─────────┘
                       是 │        │ 否
                          ▼        ▼
                  ┌──────────┐  ┌──────────────┐
                  │ 保持      │  │ 内核版本 ≥3.13?│
                  │ iptables  │  └──────┬───────┘
                  └──────────┘     是 │      │ 否
                                     ▼      ▼
                              ┌────────┐  ┌──────────┐
                              │ 使用    │  │ 使用      │
                              │nftables│  │ iptables  │
                              └────────┘  └──────────┘

实际建议:如果你的环境中有 Docker,短期内不要急于迁移到 nftables,因为 Docker 的网络驱动(如 docker0br-xxx 桥接)高度依赖 iptables 的 natfilter 表。


1.5 Netfilter 内核模块体系

1.5.1 核心模块

模块 功能
nf_tables nftables 核心框架
nf_tables_inet nftables IPv4/IPv6 混合支持
ip_tables iptables IPv4 核心
iptable_filter filter 表实现
iptable_nat nat 表实现
iptable_mangle mangle 表实现
iptable_raw raw 表实现
nf_conntrack 连接跟踪核心
nf_conntrack_ftp FTP 协议连接跟踪辅助

1.5.2 查看已加载模块

# 查看所有 Netfilter 相关模块
lsmod | grep -E "^(nf_|ipt_|xt_|ip6t_)"

# 典型输出示例:
# nf_conntrack          147456  4 xt_conntrack,nf_nat,nf_conntrack_netlink,xt_CHECKSUM
# nf_defrag_ipv6         16384  1 nf_conntrack
# nf_nat                 40960  2 nf_nat_masquerade_ipv4,nf_nat_ipv4
# ip_tables              28672  3 iptable_filter,iptable_mangle,iptable_raw
# xt_conntrack            16384  2
# xt_tcpudp              16384  8

1.5.3 加载必要的内核模块

# 手动加载连接跟踪模块
modprobe nf_conntrack
modprobe nf_conntrack_ipv4

# 加载 NAT 相关模块
modprobe nf_nat
modprobe nf_nat_masquerade_ipv4

# 开机自动加载
echo "nf_conntrack" >> /etc/modules-load.d/conntrack.conf
echo "nf_nat" >> /etc/modules-load.d/nat.conf

1.6 动手实验:观察 Netfilter 钩子

实验 1:用 tcpdump 观察数据包流向

# 终端 1:监听所有接口的 ICMP 包
sudo tcpdump -i any icmp -n

# 终端 2:ping 一个外部地址
ping -c 1 8.8.8.8

实验 2:查看当前内核的 Netfilter 配置

# 查看内核是否支持 Netfilter
grep CONFIG_NETFILTER /boot/config-$(uname -r) | head -20

# 查看当前运行的 conntrack 参数
sysctl -a | grep net.netfilter.nf_conntrack

实验 3:用 iptables -L 查看初始状态

# 查看所有链(初始状态应该是空的)
sudo iptables -L -n -v

# 典型输出:
# 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

解读:默认策略是 ACCEPT,没有任何规则,所有数据包都被接受——这是一个完全开放的防火墙状态,生产环境必须加固。


1.7 注意事项

⚠️ 远程操作防火墙的风险:如果你通过 SSH 远程管理服务器,在添加 DROP 策略前,务必先添加允许 SSH 的规则,否则会立即断开连接。

# ❌ 危险操作:直接设置默认 DROP(远程会话将断开)
iptables -P INPUT DROP

# ✅ 正确做法:先添加允许规则
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP

⚠️ 内核版本兼容性:某些高级功能(如 hashlimitconnlimit)需要较新的内核版本和对应的 xt_* 模块。在生产环境使用前,先在测试环境验证模块是否可用。

⚠️ 容器环境注意:Docker、Podman 等容器运行时会自动插入大量 iptables 规则,手动修改 iptables 可能导致容器网络异常。


1.8 扩展阅读

资源 链接 说明
Netfilter 官方文档 https://www.netfilter.org/documentation/ 权威参考
nftables Wiki https://wiki.nftables.org/ nftables 官方指南
Linux 内核源码 - Netfilter https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter 内核实现
《Linux 防火墙》(第4版) Michael Rash 著 经典教材
Red Hat - 使用 iptables https://docs.redhat.com/ RHEL 官方文档

本章小结

要点 说明
Netfilter 内核包过滤框架,提供 5 个钩子点
iptables Netfilter 的用户态管理工具,2000 年诞生
nftables iptables 的继任者,2014 年进入内核
共存 当前两者并存,iptables 仍广泛使用
核心模块 ip_tables、iptable_filter、nf_conntrack

下一章第 02 章:核心概念——四表五链,将深入讲解 iptables 的表、链、规则等核心概念。