再谈 iptables 端口转发之 ufw

再谈 iptables 端口转发之 ufw

问题描述

服务器通过 iptables 做端口转发:28890 → 5432(PostgreSQL),原本正常。安装 UFW 后连接失败。

原始规则:

# PREROUTING(外部访问)
REDIRECT tcp dpt:28890 redir ports 5432
# OUTPUT(本机访问)
REDIRECT tcp dpt:28890 redir ports 5432

排查过程

1. UFW 状态

ufw status verbose
Default: deny (incoming), allow (outgoing), deny (routed)

关键:deny (routed) - 拒绝所有转发流量。

2. 放行 28890 无效

ufw allow 28890/tcp  # 仍然不通

3. 查看 UFW 日志

tail -f /var/log/ufw.log
[UFW BLOCK] SRC=客户端IP DST=127.0.0.1 DPT=5432

image.png

问题暴露:REDIRECT 到 127.0.0.1 后,回包源地址是 127.0.0.1,但从 eth0 出去,UFW 认为非法,直接 BLOCK。


解决方案

步骤一:改用 DNAT 到内网 IP

# 获取内网 IP
ip addr show eth0 | grep inet
# 假设得到 172.20.1.6

# 删除旧规则
iptables -t nat -D PREROUTING 1
iptables -t nat -D OUTPUT 1

# 添加 DNAT 规则(PREROUTING + OUTPUT)
iptables -t nat -A PREROUTING -p tcp --dport 28890 -j DNAT --to-destination 172.20.1.6:5432
iptables -t nat -A OUTPUT -p tcp --dport 28890 -j DNAT --to-destination 172.20.1.6:5432

步骤二:UFW 放行最终端口

ufw allow 5432/tcp   # 关键!放行转发后的目标端口
ufw reload

为什么这样能解决?

之前(REDIRECT → 127.0.0.1)

客户端 → 28890 → REDIRECT到127.0.0.1:5432 → PostgreSQL处理
→ 回包源地址127.0.0.1,从eth0出去 → UFW BLOCK ❌

之后(DNAT → 内网IP)

客户端 → 28890 → DNAT到172.20.1.6:5432 → PostgreSQL处理
→ 回包源地址172.20.1.6,从eth0出去 → UFW ACCEPT ✅

为什么放行 28890 不够?

  • ufw allow 28890 放行的是 入口 端口
  • DNAT 后目标端口变成 5432,需要放行的是 5432
  • UFW INPUT 链默认 deny,不放行 5432 包进不来

关键知识点

问题原因解决
REDIRECT 到 127.0.0.1 被 UFW 拦截回包源地址 127.0.0.1 从物理网卡出去,UFW 认为非法DNAT 到内网 IP
ufw allow 28890 无效DNAT 后目标端口变为 5432,INPUT 链检查的是 5432ufw allow 5432
PREROUTING 不够本机访问 127.0.0.1:28890 走 OUTPUT 链PREROUTING + OUTPUT 双链配置

完整命令汇总

# 1. 查看内网 IP
ip addr show eth0 | grep inet

# 2. 删除旧规则
iptables -t nat -D PREROUTING -p tcp --dport 28890 -j REDIRECT --to-port 5432
iptables -t nat -D OUTPUT -p tcp --dport 28890 -j REDIRECT --to-port 5432

# 3. 添加 DNAT 规则(替换 172.20.1.6 为实际内网 IP)
iptables -t nat -A PREROUTING -p tcp --dport 28890 -j DNAT --to-destination 172.20.1.6:5432
iptables -t nat -A OUTPUT -p tcp --dport 28890 -j DNAT --to-destination 172.20.1.6:5432

# 4. UFW 放行
ufw allow 5432/tcp
ufw reload

# 5. 持久化
netfilter-persistent save

排查心得

  1. 看日志tail -f /var/log/ufw.log 永远第一件事
  2. 关 UFW 测试ufw disable 确认是否 UFW 导致
  3. 画流量路径:明确每个环节(PREROUTING → 路由 → INPUT → 回包)
  4. DNAT 优于 REDIRECT:明确指定目标,避免 127.0.0.1 回包问题
  5. PREROUTING + OUTPUT:同时覆盖外部和本机访问
  6. 放行最终端口:DNAT 后的端口才是 INPUT 链检查的目标

一句话总结

DNAT 目标用内网 IP,UFW 放行最终目标端口(5432),PREROUTING 和 OUTPUT 双链配置。


整理于 2026年9月2日

LICENSED UNDER CC BY-NC-SA 4.0