当前位置:首页>Linux>每天学一个Linux命令系列(进阶篇25):iptables - 端口转发、IP白名单,服务器防火墙自己配

每天学一个Linux命令系列(进阶篇25):iptables - 端口转发、IP白名单,服务器防火墙自己配

  • 2026-10-04 10:33:25
每天学一个Linux命令系列(进阶篇25):iptables - 端口转发、IP白名单,服务器防火墙自己配
运
运维少年 · 科技观察

前言:防火墙不是玄学,是规则集合

我第一次接触 iptables 的时候,被"四表五链"的名号吓住了。后来发现,它就是几张表格,每张表格有几个"检查点"(链)。数据包经过每个检查点时,查一下规则表,匹配了就执行对应的动作。说白了就是一套过滤器加转发器。这期把我踩过的坑和实操经验一起分享出来。

iptables 的核心:四表五链

先记住一个口诀:表决定干什么,链决定在哪儿干。

四表

  • ·filter 表(最常用):负责过滤数据包,允许或拒绝。默认就在这个表。
  • ·nat 表:负责网络地址转换,做端口转发和共享上网。
  • ·mangle 表:修改数据包的 TOS、TTL 等标记字段。
  • ·raw 表:配置是否启用连接跟踪,一般用不到。

五链

每个表有自己可用的链(检查点):

链名方向说明
INPUT入站进入本机的数据包
OUTPUT出站本机发出的数据包
FORWARD转发经过本机但不发往本机的包
PREROUTING路由前数据包刚进来,路由决策之前
POSTROUTING路由后数据包要出去了,路由决策之后

对应关系:filter 表用 INPUT/OUTPUT/FORWARD,nat 表用 PREROUTING/POSTROUTING/OUTPUT,mangle 和 raw 表用全部五链。

规则匹配逻辑

iptables 是"首条匹配即生效"。规则是按顺序逐条匹配的,一旦匹配就不再看后面的规则。这意味着你如果把"拒绝所有"写在了"允许特定IP"前面,那允许规则就永远没机会执行了。这是个特别容易踩的坑。

查看现有规则,先别急着改

在动手之前,先看看当前服务器上有什么规则。

# 查看 filter 表所有规则,带行号,数字显示不解析主机名
iptables -L -n -v --line-numbers
  • ·-L:列出规则
  • ·-n:不解析 IP 和端口为域名/服务名,显示更快更准确
  • ·-v:显示统计数据(流量计数)
  • ·--line-numbers:显示每条规则的行号,方便插入和删除
# 查看 nat 表的规则
iptables -t nat -L -n -v --line-numbers

如果输出是空的,说明你的服务器目前没有任何自定义防火墙规则。这在生产环境是很危险的。

实战场景一:配置 IP 白名单

假设我们要实现:只允许公司 IP(比如 192.168.1.100)通过 SSH 连接,其他 IP 一律拦截。

# 清空 filter 表的所有规则(谨慎操作,SSH 可能断连)
iptables -F

# 设置默认策略:拒绝所有入站流量
iptables -P INPUT DROP

# 允许已建立的连接继续通行(不然你当前的 SSH 会话也会断)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许环回接口(localhost)的流量(很多程序依赖 lo 通信)
iptables -A INPUT -i lo -j ACCEPT

# 放行公司 IP 的 SSH 端口(22)
iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT

# 放行 HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

⚠️ 安全提醒:如果你在远程服务器上执行 iptables -P INPUT DROP,一定要先加好 ESTABLISHED,RELATED 规则。否则当前 SSH 会话也会被切断,你就把自己锁在外面了。我当年第一次配防火墙就犯过这个错,直接在腾讯云控制台重启服务器才救回来。

实战场景二:防 SSH 爆破

服务器开放公网 SSH 端口,每天都会有脚本小子扫描尝试登录。可以用 iptables 限制频率。

# 使用 recent 模块限制每个 IP 每分钟最多尝试 3 次 SSH 连接
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --name SSH -j DROP

这条规则的意思是:对每个新连接的源 IP,记录到名为 SSH 的列表中;如果这个 IP 在 60 秒内已经建立了 3 次新连接,就丢弃后续的连接请求。这个搭配 fail2ban 效果更好。

实战场景三:NAT 端口转发

假设你有一台内网服务器 192.168.1.10 运行着 Web 服务(端口 3000),想让公网通过本机 80 端口访问它。

# 允许 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# PREROUTING 链上做目标地址转换:把到达本机 80 端口的流量转到内网服务器
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:3000

# POSTROUTING 链上做源地址转换:让内网服务器以为流量来自本机(而非公网客户端)
iptables -t nat -A POSTROUTING -d 192.168.1.10 -p tcp --dport 3000 -j MASQUERADE

# FORWARD 链放行这些流量
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 3000 -j ACCEPT
iptables -A FORWARD -p tcp -s 192.168.1.10 --sport 3000 -j ACCEPT

这里的 MASQUERADE 会自动用本机出口 IP 替换源 IP。如果你的本机 IP 是固定的,可以用 SNAT --to-source 本机IP 替代,性能更好。

⚠️ 安全提醒:做端口转发时,别把 ssh 端口(22)直接转发到内网。攻击者可能通过这个跳板攻击内网机器。建议只开放必要的业务端口。

规则持久化:不然重启就没了

iptables 的规则是保存在内存中的,重启服务器就会丢失。需要手动保存和恢复。

# 保存当前规则到文件
iptables-save > /etc/iptables/rules.v4

# 从文件恢复规则
iptables-restore < /etc/iptables/rules.v4

对于 Debian/Ubuntu,可以安装 iptables-persistent 让系统自动加载:

# 安装持久化工具
apt-get install iptables-persistent

# 手动保存规则
netfilter-persistent save

对于 CentOS/RHEL 7+,默认使用 firewalld,但底层还是 iptables。可以用 service iptables save 保存。

规则顺序:血的教训

iptables 的规则顺序就是执行顺序。如果你在 -P INPUT DROP(默认拒绝)之后追加了一条允许规则,它永远不会被匹配到,因为默认策略已经丢弃了。

# 错误示范:这条规则永远不会生效
iptables -P INPUT DROP
iptables -A INPUT -s 192.168.1.100 -j ACCEPT

# 正确做法:允许规则在拒绝之前
iptables -A INPUT -s 192.168.1.100 -j ACCEPT
iptables -P INPUT DROP

如果需要插入到指定位置,用 -I 指定行号:

# 插入到第 3 行
iptables -I INPUT 3 -s 10.0.0.1 -j ACCEPT

删除规则也要小心:

# 删除第 5 条规则
iptables -D INPUT 5

查看连接跟踪表:conntrack 辅助排查

iptables 内部维护了一个连接跟踪表(connection tracking),记录所有经过的数据流。某些类型的攻击(比如端口扫描、DDoS)会在连接跟踪表里留下痕迹。

# 查看当前连接跟踪表
cat /proc/net/nf_conntrack

# 统计各协议连接数
cat /proc/net/nf_conntrack | awk '{print $1}' | sort | uniq -c | sort -rn

如果连接跟踪表满了,新连接会被丢弃,导致业务中断。可以查看当前上限和实际使用的数量:

# 查看最大连接跟踪数
sysctl net.netfilter.nf_conntrack_max

# 查看当前跟踪的连接数
sysctl net.netfilter.nf_conntrack_count

如果 nf_conntrack_count 接近 nf_conntrack_max,说明连接跟踪表不够用了。可以调大上限:

# 临时调整(重启后失效)
sysctl -w net.netfilter.nf_conntrack_max=262144

# 永久调整
# echo 'net.netfilter.nf_conntrack_max=262144' >> /etc/sysctl.conf

或者对不需要跟踪的流量,在 raw 表里跳过跟踪:

# 对 Web 流量跳过连接跟踪
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK

不过 NOTRACK 会影响 NAT 功能,如果你在做端口转发就不要用这个了。

iptables 与 nftables:新老交替

nftables 是 iptables 的下一代替代品,从 Debian 10、RHEL 8、Ubuntu 20.04 开始成为默认防火墙框架。但很多生产环境的文档和运维脚本仍然依赖 iptables 语法。

两个主要区别:

  • ·iptables 的命令行是独立的(iptables、ip6tables、ebtables、arptables),nftables 统一成 nft 一个命令。
  • ·iptables 的规则是一维列表,nftables 支持嵌套集合,性能更好,规则更简洁。
  • ·nftables 的语法更像编程语言的表达式,学习曲线稍陡。

不过大多数场景下,你仍然可以用 iptables 命令操作(系统底层会通过兼容层调用 nftables),日常运维完全够用。

用脚本管理规则集:不要每次都手打

生产服务器的 iptables 规则往往很多条,手打太容易出错。我习惯把所有规则写进一个 Shell 脚本,每次修改就改脚本再执行一遍。

# 写一个防火墙规则脚本 /etc/iptables/rules.sh

# 清空所有规则和自定义链
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X

# 设置默认策略:入站拒绝,出站允许
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 放行本地回环和已建立的连接
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许内网段访问
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -s 172.16.0.0/12 -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT

# 允许公司办公网访问 SSH
iptables -A INPUT -s 公司外网IP -p tcp --dport 22 -j ACCEPT

# 放行业务端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

iptables-save > /etc/iptables/rules.v4

写完之后 chmod +x /etc/iptables/rules.sh,每次修改就运行这个脚本。比一条条敲命令安全多了。

排查思路:规则没生效怎么办

如果配置了规则发现不生效,按这几步排查:

1. iptables -L -n -v --line-numbers 确认规则是否存在。
2. 检查 -t 表是否正确(很多人把 DNAT 写到 filter 表了)。
3. 查看计数器 -v,如果计数器一直为 0,说明规则根本没被匹配到。
4. iptables -F 清空规则,从简单规则开始逐步加,确认每步生效。
5. 检查 iptables -L -n 的默认策略(Chain policy),如果默认策略是 DROP,放行规则没有覆盖到的流量都会被丢弃。

⚠️ 安全提醒:在生产环境操作 iptables 前,建议先写一个定时恢复脚本(crontab 里放一条 iptables-restore < /etc/iptables/rules.v4 过 5 分钟执行),防止把自己锁在外面。

总结

iptables 的本质就是四张表五条链组成的包过滤框架。掌握了 filter 表做访问控制、nat 表做端口转发、规则顺序决定成败、持久化防止重启丢失,就覆盖了 90% 的日常运维场景。如果你用的是较新的发行版,可以开始了解 nftables,但 iptables 的思维模型在 nftables 里同样适用,迁移成本并不高。

E N D

运维少年 · 科技观察

最新文章

随机文章