iptables 实战演练手册 ——从“小白”到“能写脚本”的 30 分钟
看到 INPUT 的 policy 为 DROP,且只有 lo 与 ESTABLISHED 被 ACCEPT,OK!测试机有双网卡:eth0(192.168.1.10) 外网,eth1(10.0.0.1) 内网,内网一台 WebServer(10.0.0.8:80),想从外网 8080 端口访问。实验 E:防暴力破解(fail2ban 的纯 iptables 版)把实验 C 再升级:连续 5 次输
作者:心灵星图
日期:2025-08-01
- 免责声明
- 本文仅用于个人实验与学习。
- 所有命令默认在「测试机」或「虚拟机」上执行,切勿直接上生产。
- 如果因为手抖锁死了 SSH,请直接重启实验机,切勿在生产机上演示“真·锁门”。
- 环境准备
- 一台 Linux 虚拟机(Ubuntu 22.04、CentOS 7/8、Debian 11 均可)
- 拥有 sudo 权限的普通用户
- 默认策略:ACCEPT(查看:
sudo iptables -L -n
若已有规则请先备份:sudo iptables-save > ~/backup-$(date +%F).rules
)
- iptables 核心概念 30 秒扫盲
Tables → Chains → Rules
- 常用表:filter(过滤)、nat(地址转换)、mangle(修改包)
- 常用链:INPUT(到本机)、FORWARD(路过本机)、OUTPUT(从本机出去)
- 动作:ACCEPT / DROP / REJECT / LOG / DNAT / SNAT / MASQUERADE …
- 动手实验路线图
A. 清空并设置安全基线
B. 练习「允许/禁止」常用端口
C. 练习「限制连接频率」
D. 练习「端口转发 + NAT」
E. 练习「防暴力破解」
F. 保存 & 恢复 & 开机自动加载
每个实验都分三步:
① 场景说明 → ② 动手命令 → ③ 验证方法
实验 A:清空并设置安全基线
① 场景
先关门,再按需开窗。
② 动手
# 新建会话:推荐开两个终端窗口,避免把自己锁外面
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT # 一般让出流量先放行,避免更新失败
# 允许回环
sudo iptables -A INPUT -i lo -j ACCEPT
# 允许已建立/关联连接
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
③ 验证sudo iptables -L -n --line
看到 INPUT 的 policy 为 DROP,且只有 lo 与 ESTABLISHED 被 ACCEPT,OK!
实验 B:允许/禁止常用端口
① 场景
打开 22/80/443,关闭 21。
② 动手
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 21 -j DROP
③ 验证
- 本机:
curl -I http://127.0.0.1
应能通。 - 另一台机器:
telnet <测试机IP> 21
应被拒绝。
实验 C:限制连接频率(防暴力破解)
① 场景
对 SSH 端口 22 每分钟只允许 3 个新连接。
② 动手
sudo iptables -I INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_ATTEMPTS --set
sudo iptables -I INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_ATTEMPTS --update --seconds 60 --hitcount 4 -j DROP
③ 验证
开另一台机:for i in {1..5}; do ssh <测试机>; done
第 4 次开始应无法建立连接,60 秒后恢复。
实验 D:端口转发 + NAT(虚拟机场景最直观)
① 场景
测试机有双网卡:eth0(192.168.1.10) 外网,eth1(10.0.0.1) 内网,
内网一台 WebServer(10.0.0.8:80),想从外网 8080 端口访问。
② 动手
# 开启转发
sudo sysctl -w net.ipv4.ip_forward=1
# 永久生效可写入 /etc/sysctl.conf
# 目的地址转换(DNAT)
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
-j DNAT --to-destination 10.0.0.8:80
# 源地址转换(SNAT),让内网服务器回包能回来
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
-j MASQUERADE
③ 验证
外网机:curl http://192.168.1.10:8080
能看到 10.0.0.8 的网页。
实验 E:防暴力破解(fail2ban 的纯 iptables 版)
① 场景
把实验 C 再升级:连续 5 次输错密码,拉黑 IP 1 小时。
② 动手
# 创建自定义链
sudo iptables -N SSH_BRUTE
sudo iptables -A SSH_BRUTE -m recent --name SSH_BLACK --set
sudo iptables -A SSH_BRUTE -j DROP
# 规则:新连接先检查黑名单
sudo iptables -I INPUT -p tcp --dport 22 -m recent \
--name SSH_BLACK --rcheck --seconds 3600 -j DROP
# 再检查错误频率
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_FAIL --set
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_FAIL --update --seconds 60 --hitcount 5 -j SSH_BRUTE
③ 验证
故意输错密码 5 次,iptables -L -n
里能看到 SSH_BLACK 命中计数,IP 被封 3600 秒。
实验 F:保存、恢复、开机自启
Debian / Ubuntu:
sudo apt install iptables-persistent
sudo netfilter-persistent save
sudo netfilter-persistent reload
CentOS / RHEL:
sudo yum install iptables-services
sudo systemctl enable --now iptables
sudo service iptables save
手动文件法(任何发行版通用):
# 保存
sudo iptables-save > /etc/iptables/rules.v4
# 恢复
sudo iptables-restore < /etc/iptables/rules.v4
# 开机加载:在 /etc/rc.local 或 systemd service 里调用 iptables-restore
- 推荐练习脚本模板
把上面所有实验做成可重复脚本:
#!/bin/bash
# filename: lab-iptables.sh
set -e
# 1. 清空
iptables -F
iptables -t nat -F
iptables -X
# 2. 默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 3. 基本允许
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 4. 防暴力
iptables -N SSH_BRUTE
iptables -A SSH_BRUTE -m recent --name SSH_BLACK --set
iptables -A SSH_BRUTE -j DROP
iptables -I INPUT -p tcp --dport 22 -m recent --name SSH_BLACK --rcheck --seconds 3600 -j DROP
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_FAIL --set
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --name SSH_FAIL --update --seconds 60 --hitcount 5 -j SSH_BRUTE
# 5. 保存
iptables-save > ~/lab-$(date +%F).rules
echo "Done, rules saved in ~/lab-$(date +%F).rules"
加执行权限 chmod +x lab-iptables.sh
,每次练习完 ./lab-iptables.sh
,一键复原。
- 常见“翻车现场”与急救
- 误把 SSH 端口封了:
虚拟机 → 控制台重启;
云主机 → 用 VNC/救援模式;
物理机 → 现场 iKVM。 - 规则顺序写错:
记得-I
插在链首,-A
追加到链尾,顺序影响匹配。 - 忘记开启
ip_forward
:
NAT 失败 90% 原因在此。
- 进阶练习清单
[ ] 使用 ipset 替代 recent,提高黑名单容量
[ ] 用 iptables 做限速 QoS(tc 更专业,但 filter 表也行)
[ ] 在 DOCKER-USER 链里写规则与容器网络共舞
[ ] 迁移到 nftables(CentOS 8/9、Ubuntu 22.04+ 默认)
- 小结
用 30 分钟跑完以上实验,你已经:
✔ 会清空/保存/恢复规则
✔ 会写基本允许/拒绝
✔ 会用模块做频率限制
✔ 会做 DNAT/SNAT 端口转发
✔ 能把脚本固化成开机自启
恭喜入门!接下来读 man iptables-extensions,把 -m
里 30+ 模块玩一遍,你就离“老鸟”不远了。
更多推荐
所有评论(0)