作者:心灵星图
日期:2025-08-01


  1. 免责声明
  2. 本文仅用于个人实验与学习。
  3. 所有命令默认在「测试机」或「虚拟机」上执行,切勿直接上生产。
  4. 如果因为手抖锁死了 SSH,请直接重启实验机,切勿在生产机上演示“真·锁门”。

  1. 环境准备
  • 一台 Linux 虚拟机(Ubuntu 22.04、CentOS 7/8、Debian 11 均可)
  • 拥有 sudo 权限的普通用户
  • 默认策略:ACCEPT(查看:sudo iptables -L -n 若已有规则请先备份:sudo iptables-save > ~/backup-$(date +%F).rules

  1. iptables 核心概念 30 秒扫盲
    Tables → Chains → Rules
  • 常用表:filter(过滤)、nat(地址转换)、mangle(修改包)
  • 常用链:INPUT(到本机)、FORWARD(路过本机)、OUTPUT(从本机出去)
  • 动作:ACCEPT / DROP / REJECT / LOG / DNAT / SNAT / MASQUERADE …

  1. 动手实验路线图
    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

  1. 推荐练习脚本模板
    把上面所有实验做成可重复脚本:
#!/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,一键复原。


  1. 常见“翻车现场”与急救
  • 误把 SSH 端口封了:
    虚拟机 → 控制台重启;
    云主机 → 用 VNC/救援模式;
    物理机 → 现场 iKVM。
  • 规则顺序写错:
    记得 -I 插在链首,-A 追加到链尾,顺序影响匹配。
  • 忘记开启 ip_forward
    NAT 失败 90% 原因在此。

  1. 进阶练习清单
    [ ] 使用 ipset 替代 recent,提高黑名单容量
    [ ] 用 iptables 做限速 QoS(tc 更专业,但 filter 表也行)
    [ ] 在 DOCKER-USER 链里写规则与容器网络共舞
    [ ] 迁移到 nftables(CentOS 8/9、Ubuntu 22.04+ 默认)

  1. 小结
    用 30 分钟跑完以上实验,你已经:
    ✔ 会清空/保存/恢复规则
    ✔ 会写基本允许/拒绝
    ✔ 会用模块做频率限制
    ✔ 会做 DNAT/SNAT 端口转发
    ✔ 能把脚本固化成开机自启

恭喜入门!接下来读 man iptables-extensions,把 -m 里 30+ 模块玩一遍,你就离“老鸟”不远了。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐