iptables PREROUTING + DNAT是端口映射的必须起点,负责修改入向数据包目标地址;必须配合FORWARD放行、POSTROUTING SNAT/MASQUERADE及启用ip_forward,四者缺一不可。

iptables PREROUTING + DNAT 是最常用且必须的起点
端口映射在 Linux 中本质是 NAT 行为,PREROUTING 链负责修改刚进入本机网络栈、尚未路由决策的数据包目标地址——这是对外网请求做转发的唯一正确入口。漏掉它,规则根本不会生效。
常见错误是只加 DNAT 却没指定协议或端口范围,导致 ICMP 或 UDP 流量误匹配;或者把 --dport 写成源端口(--sport),结果规则永远不触发。
-
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80:仅对 TCP 的 8080 端口生效 - 如需同时支持 HTTP/HTTPS,得两条独立规则:
--dport 80和--dport 443,不能写成--dport 80:443(语法错误) - UDP 映射必须显式声明:
-p udp,混用-p tcp规则对 UDP 无效
FORWARD 链放行不等于“打开防火墙”,而是明确授权转发路径
即使 DNAT 成功改写了目标 IP,Linux 默认会丢弃非本机目的地的数据包。必须在 FORWARD 链中显式允许该流量通过,否则连接卡在 SYN 包阶段,超时失败。
容易踩的坑是只写 -j ACCEPT 而不限定方向或接口,这会削弱安全边界;更糟的是忘记加状态匹配,导致返回流量被拦截。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 基础放行:
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT - 双网卡场景必须绑定接口:
-i eth0 -o eth1,否则内网侧可能被外网直连绕过 - 务必加返回通路:
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT,否则客户端收不到 ACK
POSTROUTING + MASQUERADE / SNAT 决定回程路径是否可靠
内网主机响应时,源 IP 是它的私有地址(如 192.168.1.100),外网客户端无法直接路由回去。必须在 POSTROUTING 链做地址伪装,让响应看起来来自网关本身。
用 MASQUERADE 还是 SNAT?前者适合 DHCP 外网 IP 场景(IP 不固定),后者要求明确写出网关外网 IP,配置稍严但性能略优。
- 动态外网 IP(家用宽带):
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE - 固定外网 IP(云服务器):
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 203.0.113.42 - 别漏子网掩码:
-s 192.168.1.0/24比-s 192.168.1.100更安全,避免规则失效
ip_forward 必须开启,且要持久化
/proc/sys/net/ipv4/ip_forward 是内核开关,值为 0 时所有转发逻辑直接跳过,前面所有规则形同虚设。临时开启用 echo 1 > /proc/sys/net/ipv4/ip_forward,但重启即失效。
不同发行版持久化方式不同,硬编码到 /etc/sysctl.conf 最通用,但 systemd-networkd 或 cloud-init 环境可能覆盖它。
- 确认当前状态:
sysctl net.ipv4.ip_forward返回net.ipv4.ip_forward = 1才算生效 - 写入配置:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p - 某些容器环境(如 Docker)会重置该值,需检查
dockerd启动参数是否含--ip-forward=true
DNAT 规则顺序、FORWARD 放行粒度、回程地址伪装方式,三者必须协同;任意一环松动,连接就断在三次握手中间。调试时优先抓包看 SYN 是否到达内网主机,再查响应能否发出——问题通常不在规则本身,而在路径上某处被静默丢弃。

















