经过一次差点把服务器玩废的惨烈经历(从宝塔转发失效 → iptables/nftables 翻车 → 路由策略被毁 → 出站全死 → 反复重启才救回),我终于彻底搞清楚了所有坑,并写了一个绝对安全、永不翻车的端口转发脚本,专治以下场景:

  • Ubuntu 22.04 + 宝塔面板
  • 公网IP绑定在 lo 接口(routed/lo 配置,很多小厂商的VPS都是)
  • KVM/libvirt 虚拟机使用 NAT 网络(192.168.122.x 或 10.x.x.x)
  • 需要把虚拟机内的端口安全暴露给外网

这个脚本已完美避开所有已知雷区:

  • 同时写 nftables + iptables-legacy 双保险
  • 绝不 flush 任何链、绝不碰路由、绝不加 MASQUERADE
  • 支持外网端口 → 虚拟机内网IP:端口 格式
  • 删除规则精准无残留

一键安装命令(推荐,直接复制执行)

curl -sSL https://pastebin.com/raw/pLnkAPDg -o /usr/local/bin/pf && chmod +x /usr/local/bin/pf

安装完成后即可全局使用 pf 命令(建议用 root 或 sudo 执行)

使用方法

# 添加转发:外网2222 → 虚拟机192.168.122.88的22端口(SSH)
pf add 2222 192.168.122.88:22

# 添加其他服务(比如虚拟机里的Web服务5000端口)
pf add 5000 192.168.122.88:5000

# 查看当前所有转发规则
pf list

# 删除某个转发
pf del 2222

实际效果

执行 pf add 2222 192.168.122.88:22 后:

  • 外网直接 ssh user@你的公网IP -p 2222 就能进虚拟机
  • 宿主机本地 telnet 127.0.0.1 2222也通
  • 完全不影响服务器出站入站网络
  • 重启服务器规则依然存在(nftables + iptables 双写)

必须配合的操作(别忘了!)

  1. 宝塔面板 → 安全 → 防火墙 → 添加端口(把你用到的外网端口如 2222、5000 加进去)
  2. 虚拟机内部防火墙也放行对应端口(ufw allow 22 等)

完整脚本地址(备用)

https://pastebin.com/raw/pLnkAPDg