## 文档概述
本文档旨在系统性地阐述 Ubuntu 24.04 系统中 iptables 防火墙的配置方法,重点分析 Docker 容器环境下 iptables 规则的自动生成机制,并提供系统策略与 Docker 策略分离管理的最佳实践方案。
首先明确一点:
即使 ufw、iptables、firewalld等这些管理防火墙的程序 是 inactive 状态,Docker 仍然能够正常管理 iptables 策略,这是因为 UFW 和 Docker 在 iptables 管理上是完全独立的两个系统。

---
## 第一部分:iptables 基础概念与配置
### 1.1 iptables 架构理解
iptables 是 Linux 内核中的防火墙管理工具,其核心架构分为三个层次:
| 层次 | 组件 | 说明 |
|------|------|------|
| 内核层 | Netfilter 框架 | Linux 内核中的包过滤子系统,负责实际的数据包处理 |
| 规则层 | iptables 规则集 | 加载到内核中的过滤规则,独立于任何用户空间进程运行 |
| 管理层 | iptables 命令 | 用户空间的配置工具,用于添加、删除、修改内核中的规则 |
**关键理解**:iptables 规则一旦加载到内核,就独立于任何用户空间进程(包括 iptables 命令本身、ufw、firewalld 等)运行,直到系统重启或规则被显式删除。
### 1.2 核心表和链
| 表名 | 功能 | 主要链 |
|------|------|--------|
| filter | 包过滤(默认表) | INPUT(入站)、FORWARD(转发)、OUTPUT(出站) |
| nat | 网络地址转换 | PREROUTING、POSTROUTING、OUTPUT |
| mangle | 包修改 | PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD |
| raw | 连接跟踪配置 | PREROUTING、OUTPUT |
### 1.3 Ubuntu 24.04 默认防火墙状态
Ubuntu 24.04 默认安装但不启用任何防火墙:
```bash
# 查看 ufw 状态(默认 inactive)
sudo ufw status
# Status: inactive
# 查看当前内核中的 iptables 规则(默认 ACCEPT 所有)
sudo iptables -L -n
# Chain INPUT (policy ACCEPT)
# Chain FORWARD (policy ACCEPT)
# Chain OUTPUT (policy ACCEPT)
```
### 1.4 基础规则配置示例
```bash
# 允许 SSH 连接
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许已建立连接的相关流量
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许本地回环
sudo iptables -A INPUT -i lo -j ACCEPT
# 默认拒绝所有入站流量(配置在允许规则之后)
sudo iptables -P INPUT DROP
```
### 1.5 规则持久化(Ubuntu 标准方法)
Ubuntu 使用 `iptables-persistent` 工具实现规则持久化:
```bash
# 安装持久化工具
sudo apt update
sudo apt install iptables-persistent -y
# 保存当前规则
sudo netfilter-persistent save
# 规则存储位置
# IPv4: /etc/iptables/rules.v4
# IPv6: /etc/iptables/rules.v6
# 重启后自动加载(服务已自动启用)
sudo systemctl status netfilter-persistent
```
---
## 第二部分:Docker 环境下的 iptables 规则生成原理
### 2.1 Docker 网络架构
Docker 守护进程(dockerd)在启动时会自动配置 iptables 规则,实现容器网络通信。其核心设计原则是:**默认隔离,按需开放**。
### 2.2 Docker 创建的规则链体系
Docker 创建以下自定义链来管理容器网络:
| 链名 | 所属表 | 作用 |
|------|--------|------|
| DOCKER | filter, nat | 存放容器端口映射和访问控制的具体规则 |
| DOCKER-USER | filter | **用户自定义规则的推荐位置**,优先级最高 |
| DOCKER-ISOLATION-STAGE-1 | filter | 识别需要隔离的跨网络流量 |
| DOCKER-ISOLATION-STAGE-2 | filter | 执行跨网络流量的丢弃操作 |
### 2.3 DOCKER-ISOLATION 链隔离机制
Docker 使用两阶段链实现不同网络间的隔离:
```
┌─────────────────────────────────────────────────────────────┐
│ FORWARD 链执行顺序 │
├─────────────────────────────────────────────────────────────┤
│ 1. DOCKER-USER (用户规则,优先级最高) │
│ 2. DOCKER-ISOLATION-STAGE-1 (识别跨网络流量) │
│ └── 匹配条件: 从网络A进来,出去到非网络A │
│ └── 跳转到 DOCKER-ISOLATION-STAGE-2 │
│ └── DROP 所有目标为其他网络的流量 │
│ 3. 已建立连接放行 │
│ 4. DOCKER 链 (容器具体规则) │
└─────────────────────────────────────────────────────────────┘
```
**隔离规则示例**:
```bash
# STAGE-1: 识别从 docker0 出去到其他网络的流量
DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
# STAGE-2: 丢弃目标为 docker0 的流量
DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
```
### 2.4 端口映射规则生成示例
当执行 `docker run -p 8080:80 nginx` 时,Docker 自动生成以下规则:
```bash
# nat 表:DNAT 规则(将宿主机端口映射到容器)
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
# filter 表:允许转发到容器
iptables -A FORWARD -o docker0 -j DOCKER
iptables -A DOCKER -d 172.17.0.2 -p tcp --dport 80 -j ACCEPT
```
### 2.5 容器访问外网的 SNAT 规则
```bash
# 将容器流量伪装成宿主机 IP 出去
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
```
---
## 第三部分:系统策略与 Docker 策略分离管理
### 3.1 核心原则
1. **系统规则使用 DOCKER-USER 链**:所有手动配置的系统级防火墙规则都应添加到 `DOCKER-USER` 链
2. **不保存 Docker 自动生成的规则**:避免因容器 IP 变化导致的规则冲突
3. **让 Docker 自主管理其规则**:Docker 服务启动时会自动重建所需规则
4. **规则优先级**:DOCKER-USER > DOCKER-ISOLATION > DOCKER
### 3.2 DOCKER-USER 链的优先级验证
```bash
# 查看 FORWARD 链的规则顺序
sudo iptables -L FORWARD -n --line-numbers
# 典型输出:
# Chain FORWARD (policy DROP)
# num target prot opt source destination
# 1 DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0 ← 用户规则最先执行
# 2 DOCKER-ISOLATION-STAGE-1 all -- 0.0.0.0/0 0.0.0.0/0
# 3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
# 4 DOCKER all -- 0.0.0.0/0 0.0.0.0/0
```
### 3.3 系统规则配置最佳实践
#### 3.3.1 创建规则管理脚本
```bash
sudo tee /usr/local/bin/apply-system-firewall.sh << 'EOF'
#!/bin/bash
# 系统防火墙规则管理脚本
# 所有规则添加到 DOCKER-USER 链,确保与 Docker 规则隔离
# 清空 DOCKER-USER 链(保留链本身)
iptables -F DOCKER-USER 2>/dev/null || iptables -N DOCKER-USER
# ========== 基础安全规则 ==========
# 允许已建立连接
iptables -I DOCKER-USER -m state --state ESTABLISHED,RELATED -j ACCEPT
# ========== SSH 访问控制 ==========
# 允许内网 SSH
iptables -I DOCKER-USER -i eth0 -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# 拒绝外网 SSH
iptables -I DOCKER-USER -i eth0 -p tcp --dport 22 -j DROP
# ========== 容器服务访问控制 ==========
# 示例:允许特定 IP 访问容器的 8080 端口
iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 -j DROP
# ========== 防攻击规则 ==========
# 限制 SYN 包速率
iptables -I DOCKER-USER -p tcp --syn -m limit --limit 1/second -j ACCEPT
iptables -I DOCKER-USER -p tcp --syn -j DROP
echo "系统防火墙规则已应用到 DOCKER-USER 链"
EOF
sudo chmod +x /usr/local/bin/apply-system-firewall.sh
```
#### 3.3.2 仅保存系统规则的持久化方案
```bash
# 创建仅保存系统规则的脚本
sudo tee /usr/local/bin/save-system-firewall.sh << 'EOF'
#!/bin/bash
# 只保存系统规则(DOCKER-USER 链),不保存 Docker 自动生成的规则
# 方法:提取 DOCKER-USER 链的规则
cat > /tmp/system-rules.v4 << 'RULES_HEADER'
*filter
:DOCKER-USER - [0:0]
RULES_HEADER
# 提取 DOCKER-USER 链的规则
iptables-save | grep -E "^-A DOCKER-USER" >> /tmp/system-rules.v4
echo "COMMIT" >> /tmp/system-rules.v4
# 备份原文件
sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.backup 2>/dev/null || true
# 合并到系统规则文件(保留其他系统链,但不包含 Docker 链)
# 注意:这个文件不应包含 DOCKER、DOCKER-ISOLATION 等链
sudo cp /tmp/system-rules.v4 /etc/iptables/rules.v4
echo "系统规则已保存到 /etc/iptables/rules.v4"
echo "Docker 规则将在服务启动时自动重建"
EOF
sudo chmod +x /usr/local/bin/save-system-firewall.sh
```
#### 3.3.3 创建 systemd 服务确保规则加载时机正确
```bash
sudo tee /etc/systemd/system/system-firewall.service << 'EOF'
[Unit]
Description=System Firewall Rules
After=docker.service network.target
Wants=docker.service
Before=netfilter-persistent.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/apply-system-firewall.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
# 启用服务
sudo systemctl daemon-reload
sudo systemctl enable system-firewall.service
sudo systemctl start system-firewall.service
```
### 3.4 完整的工作流程
```bash
# 1. 应用系统规则
sudo /usr/local/bin/apply-system-firewall.sh
# 2. 验证规则
sudo iptables -L DOCKER-USER -n -v
# 3. 仅保存系统规则
sudo /usr/local/bin/save-system-firewall.sh
# 4. 查看保存的文件(确认只包含系统规则)
sudo cat /etc/iptables/rules.v4
# 5. 重启测试
sudo reboot
# 6. 重启后验证
sudo iptables -L DOCKER-USER -n -v # 系统规则应存在
sudo iptables -L DOCKER -n | head # Docker 规则应自动重建
```
### 3.5 规则冲突排查
| 问题现象 | 可能原因 | 解决方法 |
|----------|----------|----------|
| Docker 容器无法访问 | 系统规则误拦截 | 检查 DOCKER-USER 链规则,确保允许容器相关流量 |
| 规则重复 | 保存了 Docker 规则 | 删除 `/etc/iptables/rules.v4` 中的 DOCKER 相关链 |
| 容器 IP 变化后无法访问 | 保存了含固定 IP 的规则 | 使用 `docker restart` 重建规则,避免保存容器 IP 相关规则 |
| 系统规则未加载 | netfilter-persistent 服务未启用 | `sudo systemctl enable netfilter-persistent` |
---
## 第四部分:常用命令速查
### 4.1 规则查看
| 命令 | 说明 |
|------|------|
| `sudo iptables -L -n -v` | 查看所有 filter 表规则及统计 |
| `sudo iptables -t nat -L -n -v` | 查看 nat 表规则 |
| `sudo iptables -L DOCKER-USER -n -v` | 只查看 DOCKER-USER 链 |
| `sudo iptables-save` | 导出所有规则(可执行格式) |
| `sudo iptables-save \| grep DOCKER` | 筛选 Docker 相关规则 |
### 4.2 规则管理
| 命令 | 说明 |
|------|------|
| `sudo iptables -I DOCKER-USER 1 -j ...` | 在 DOCKER-USER 链首部插入规则 |
| `sudo iptables -A DOCKER-USER -j ...` | 在 DOCKER-USER 链尾部追加规则 |
| `sudo iptables -D DOCKER-USER <num>` | 按编号删除规则 |
| `sudo iptables -F DOCKER-USER` | 清空 DOCKER-USER 链 |
| `sudo netfilter-persistent save` | 保存所有规则(**不推荐有 Docker 时使用**) |
### 4.3 Docker 网络调试
| 命令 | 说明 |
|------|------|
| `docker network ls` | 查看所有 Docker 网络 |
| `docker inspect <container> \| grep IPAddress` | 查看容器 IP |
| `sudo iptables -L DOCKER-ISOLATION-STAGE-1 -n -v` | 查看隔离链统计 |
| `sudo iptables -t nat -L DOCKER -n` | 查看端口映射规则 |
---
## 第五部分:总结
### 5.1 核心要点
1. **iptables 规则位于内核空间**,独立于用户空间进程运行
2. **Ubuntu 24.04 使用 iptables-persistent** 实现规则持久化,非 Red Hat 系的 `service iptables save`
3. **Docker 自动管理其规则**,使用 DOCKER、DOCKER-USER、DOCKER-ISOLATION 等自定义链
4. **DOCKER-USER 链是用户规则的唯一推荐位置**,优先级最高
5. **不要使用 `netfilter-persistent save` 保存 Docker 规则**,应单独保存系统规则
### 5.2 最佳实践清单
- [ ] 系统规则全部添加到 `DOCKER-USER` 链
- [ ] 创建独立的规则应用脚本(如 `apply-system-firewall.sh`)
- [ ] 创建独立的规则保存脚本(过滤掉 Docker 规则)
- [ ] 使用 systemd 服务确保规则在 Docker 启动后应用
- [ ] 定期验证规则加载正确性
- [ ] 避免在规则中硬编码容器 IP 地址
---
## 附录:完整配置示例
### A. 系统防火墙规则模板
```bash
#!/bin/bash
# /usr/local/bin/apply-system-firewall.sh
# 完整的系统防火墙规则模板
# 清空现有系统规则
iptables -F DOCKER-USER 2>/dev/null
# 确保 DOCKER-USER 链存在
iptables -N DOCKER-USER 2>/dev/null || true
# ========== 1. 基础规则 ==========
# 允许已建立连接
iptables -A DOCKER-USER -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许本地回环
iptables -A DOCKER-USER -i lo -j ACCEPT
# ========== 2. 服务访问控制 ==========
# SSH 访问控制
iptables -A DOCKER-USER -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -A DOCKER-USER -p tcp --dport 22 -j DROP
# HTTP/HTTPS 全开放(如需限制请修改)
iptables -A DOCKER-USER -p tcp --dport 80 -j ACCEPT
iptables -A DOCKER-USER -p tcp --dport 443 -j ACCEPT
# ========== 3. 容器服务访问控制 ==========
# 示例:限制容器 8080 端口的访问
iptables -A DOCKER-USER -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
iptables -A DOCKER-USER -p tcp --dport 8080 -j DROP
# ========== 4. 防护规则 ==========
# 限制 ICMP 速率
iptables -A DOCKER-USER -p icmp -m limit --limit 1/second -j ACCEPT
iptables -A DOCKER-USER -p icmp -j DROP
# 限制新连接速率
iptables -A DOCKER-USER -m state --state NEW -m limit --limit 100/minute -j ACCEPT
echo "系统防火墙规则应用完成"
```
### B. 规则验证脚本
```bash
#!/bin/bash
# /usr/local/bin/verify-firewall.sh
echo "========== 防火墙规则验证 =========="
echo ""
echo "1. DOCKER-USER 链规则:"
sudo iptables -L DOCKER-USER -n -v
echo ""
echo "2. Docker 规则统计:"
echo " filter 表 DOCKER 链规则数: $(sudo iptables -L DOCKER -n 2>/dev/null | wc -l)"
echo " nat 表 DOCKER 链规则数: $(sudo iptables -t nat -L DOCKER -n 2>/dev/null | wc -l)"
echo ""
echo "3. 规则冲突检查:"
if sudo iptables-save | grep -q "^-A DOCKER " | grep -v "^-A DOCKER-"; then
echo " ⚠️ 发现 Docker 自动规则与保存的规则可能冲突"
else
echo " ✅ 未发现明显冲突"
fi
echo ""
echo "4. 持久化配置检查:"
if [ -f /etc/iptables/rules.v4 ]; then
echo " ✅ 持久化文件存在: /etc/iptables/rules.v4"
echo " 文件大小: $(du -h /etc/iptables/rules.v4 | cut -f1)"
if grep -q "DOCKER " /etc/iptables/rules.v4; then
echo " ⚠️ 警告: 持久化文件中包含 Docker 规则"
fi
else
echo " ❌ 持久化文件不存在"
fi
```
---
**文档版本**:1.0
**适用系统**:Ubuntu 24.04 LTS
**最后更新**:2026-04-01

351

被折叠的 条评论
为什么被折叠?



