iptables端口转发教程

22

1. 场景示例

  • 描述: 我们有一台公网 Linux 服务器(11.11.11.11),我们想通过访问它的 3389 端口,来安全地访问一台处于内网的 Windows RDP 主机(172.16.0.19)。

  • 拓扑图: 你 (Windows 客户端) -> 公网 (11.11.11.11) -> 内网 (172.16.0.19)

2. 准备工作:定义变量和环境

为了让脚本清晰易懂,我们先定义变量。

# 公网服务器要监听的端口
LOCAL_PORT=3389
# 真正提供服务的目标内网IP
TARGET_IP=172.16.0.19
# 目标内网IP的服务端口
TARGET_PORT=3389

3. 步骤一:开启 Linux 内核转发

这是最基础的一步。如果内核不允许IP转发,iptables 的所有努力都白费。

# 1. 临时开启
sudo sysctl -w net.ipv4.ip_forward=1

# 2. 检查是否成功
cat /proc/sys/net/ipv4/ip_forward
# (确保返回 1)

# 3. 永久开启(推荐)
# sudo nano /etc/sysctl.conf
# 找到 net.ipv4.ip_forward=1 并取消注释
# 然后执行 sudo sysctl -p 使其生效

4. 步骤二:配置 NAT 表

这是大多数教程都会讲的部分。我们需要两条规则:

  1. PREROUTING (DNAT): 把“进来”的包,目标地址换成内网 RDP 主机。

  2. POSTROUTING (SNAT/MASQUERADE): 把“出去”的包,源地址换成 Linux 服务器。(关键:否则 RDP 主机会直接回复给你的客户端,而不是回复给 Linux 服务器)

# 1. PREROUTING 规则 (DNAT):修改目标地址
sudo iptables -t nat -A PREROUTING -p tcp --dport $LOCAL_PORT -j DNAT --to-destination $TARGET_IP:$TARGET_PORT

# 2. POSTROUTING 规则 (MASQUERADE):修改源地址
sudo iptables -t nat -A POSTROUTING -d $TARGET_IP -p tcp --dport $TARGET_PORT -j MASQUERADE

5. 步骤三:配置 filter 表(防火墙放行)

这是教程的核心nat 表只负责翻译地址,但不负责放行。真正决定包能否通过的是 filter 表的 FORWARD 链。

# 注意:我们用 -I (Insert) 把规则插入到链的顶部,确保它们在 Docker 等规则之前被匹配。

# 1. 允许“已建立”和“相关”的连接(允许 RDP 的“返回”流量)
sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# 2. 允许“新”的连接(允许你客户端的“发起”流量)
sudo iptables -I FORWARD 2 -d $TARGET_IP -p tcp --dport $TARGET_PORT -j ACCEPT

6. 步骤五:持久化规则

iptables 规则默认重启失效。

  • Debian/Ubuntu:

    sudo apt-get install iptables-persistent
    sudo netfilter-persistent save
    
  • CentOS/RHEL (旧版):

    service iptables save
    # 或
    iptables-save > /etc/sysconfig/iptables

7. 如何重置 netfilter-persistent 保存的内容

步骤 1:清空当前内存中的所有规则

# 1. 清空 filter 表 (INPUT, OUTPUT, FORWARD)
sudo iptables -F
sudo iptables -X

# 2. 清空 nat 表 (PREROUTING, POSTROUTING)
sudo iptables -t nat -F
sudo iptables -t nat -X

# 3. 清空 mangle 表 (可选,以防万一)
sudo iptables -t mangle -F
sudo iptables -t mangle -X

# 4. (重要) 把默认策略改回 ACCEPT,防止SSH断开
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

步骤 2:保存这个“空”的状态

# 这会用“空规则”覆盖掉你之前保存的RDP转发规则
sudo netfilter-persistent save