在 Proxmox VE 中配置端口映射并限制特定 IP 访问的完整指南
问题背景
在 Proxmox VE (PVE) 中配置端口映射时,经常会遇到这样的需求:将宿主机的特定端口映射到内网虚拟机,但只允许指定的 IP 地址访问。很多用户在配置后发现规则不生效,端口仍然可以被任意 IP 扫描到。
本文将详细介绍如何通过命令行完全解决这个问题。
根本原因分析
通过分析 iptables
配置,发现问题的核心在于:
1. PVE 防火墙覆盖自定义规则
# PVE防火墙接管了INPUT链
sudo iptables -L PVEFW-INPUT -v
# PVE防火墙接管了FORWARD链
sudo iptables -L PVEFW-FORWARD -v
2. PVE 防火墙的默认放行策略
PVE 防火墙看到目标端口不在它的管理范围内时,会直接 RETURN
(返回)到主链继续处理,导致自定义的 DROP
规则可能无法生效。
解决方案:完全使用命令行配置
步骤 1:清理现有冲突规则
# 删除所有自定义的 DNAT 规则
sudo iptables -t nat -D PREROUTING -i vmbr0 -p tcp -m tcp --dport 33389 -j DNAT --to-destination 172.16.1.2:3389 2>/dev/null || true
sudo iptables -t nat -D PREROUTING -s 154.23.255.101/32 -i vmbr0 -p tcp -m tcp --dport 33389 -j DNAT --to-destination 172.16.1.2:3389 2>/dev/null || true
# 删除所有自定义的 FORWARD 规则
sudo iptables -D FORWARD -d 172.16.1.2/32 -p tcp -m tcp --dport 3389 -j ACCEPT 2>/dev/null || true
sudo iptables -D FORWARD -s 154.23.255.101/32 -d 172.16.1.2/32 -p tcp -m tcp --dport 3389 -j ACCEPT 2>/dev/null || true
# 删除所有自定义的 INPUT 规则
sudo iptables -D INPUT -s 154.23.255.101/32 -p tcp -m tcp --dport 33389 -j ACCEPT 2>/dev/null || true
sudo iptables -D INPUT -p tcp -m tcp --dport 33389 -j DROP 2>/dev/null || true
步骤 2:配置 PVE 防火墙规则
# 创建集群防火墙规则文件
sudo tee /etc/pve/firewall/cluster.fw > /dev/null << 'EOF'
[OPTIONS]
enable: 1
[RULES]
IN ACCEPT -p tcp -dport 33389 -source 154.23.255.101/32 -log nolog
IN DROP -p tcp -dport 33389 -log nolog
EOF
步骤 3:配置虚拟机防火墙规则
# 首先找出目标虚拟机的 VMID
sudo qm list
# 创建虚拟机特定的防火墙规则文件(假设 VMID 为 100)
sudo tee /etc/pve/firewall/100.fw > /dev/null << 'EOF'
[OPTIONS]
enable: 1
[ALIASES]
[RULES]
[DNAT]
tcp 33389 172.16.1.2:3389
EOF
步骤 4:添加必要的 iptables 规则
# 添加 DNAT 端口转发规则
sudo iptables -t nat -A PREROUTING -s 154.23.255.101/32 -i vmbr0 -p tcp -m tcp --dport 33389 -j DNAT --to-destination 172.16.1.2:3389
# 添加对应的 FORWARD 规则
sudo iptables -A FORWARD -s 154.23.255.101/32 -d 172.16.1.2/32 -p tcp -m tcp --dport 3389 -j ACCEPT
步骤 5:重新加载防火墙配置
# 重新加载 PVE 防火墙配置
sudo pve-firewall restart
# 或者重启防火墙服务
sudo systemctl restart pve-firewall
步骤 6:保存配置确保重启有效
# 安装 iptables-persistent(如果尚未安装)
sudo apt install iptables-persistent -y
# 保存当前 iptables 规则
sudo netfilter-persistent save
# 确保 PVE 防火墙开机启动
sudo systemctl enable pve-firewall
验证配置
检查配置是否正确
# 检查 PVE 防火墙规则
sudo pve-firewall compile
sudo pve-firewall status
# 检查 iptables 规则
sudo iptables -L -n -v | grep -E "33389|3389"
sudo iptables -t nat -L -n -v | grep -E "33389|3389"
# 查看规则顺序
sudo iptables -L INPUT -n --line-numbers
sudo iptables -L FORWARD -n --line-numbers
测试连接
# 从允许的 IP 测试(应该能连接)
# 需要在 154.23.255.101 这个 IP 的机器上测试
telnet 您的PVE主机IP 33389
# 从其他 IP 测试(应该被拒绝)
nmap -p 33389 您的PVE主机IP
故障排查
如果遇到问题,使用以下命令排查:
# 查看详细的规则处理过程
sudo iptables -L -n -v --line-numbers
# 查看 NAT 表规则
sudo iptables -t nat -L -n -v --line-numbers
# 查看连接跟踪
sudo conntrack -L | grep 33389
# 实时监控防火墙日志
sudo tail -f /var/log/syslog | grep pve-firewall
sudo tail -f /var/log/syslog | grep -E "33389|3389"
# 检查规则命中计数
watch -n 1 'iptables -L -n -v | grep -E "33389|3389"'
配置说明
规则解释
-
集群防火墙规则 (
/etc/pve/firewall/cluster.fw
):IN ACCEPT
: 允许指定 IP 访问 33389 端口IN DROP
: 拒绝其他所有 IP 访问 33389 端口
-
虚拟机防火墙规则 (
/etc/pve/firewall/100.fw
):[DNAT]
: 配置端口转发,将 33389 端口转发到内网虚拟机的 3389 端口
-
iptables 规则:
PREROUTING
: DNAT 转发规则FORWARD
: 允许转发到目标虚拟机的流量
注意事项
- 规则顺序很重要: PVE 防火墙规则按顺序处理,确保
ACCEPT
规则在DROP
规则之前 - 配置文件权限: 确保防火墙配置文件具有正确的权限
- 网络接口: 确认规则应用在正确的网络接口上(如
vmbr0
) - IP 地址: 确保使用的 IP 地址和端口号正确无误
扩展配置
允许多个 IP 地址
# 编辑集群防火墙规则
sudo nano /etc/pve/firewall/cluster.fw
# 添加多个 IP 或网段
[RULES]
IN ACCEPT -p tcp -dport 33389 -source 154.23.255.101/32 -log nolog
IN ACCEPT -p tcp -dport 33389 -source 192.168.1.0/24 -log nolog
IN DROP -p tcp -dport 33389 -log nolog
配置多个端口
# 配置多个端口转发
[DNAT]
tcp 33389 172.16.1.2:3389
tcp 30080 172.16.1.3:80
tcp 30443 172.16.1.3:443
结论
通过以上命令行配置,您可以成功实现:
- ✅ 只允许特定 IP (
154.23.255.101
) 访问 PVE 宿主机的33389
端口 - ✅ 将流量正确转发到内网虚拟机 (
172.16.1.2:3389
) - ✅ 阻止其他所有 IP 的访问尝试
- ✅ 避免 PVE 防火墙与自定义规则的冲突
这种配置方式既保持了 PVE 防火墙的管理优势,又实现了精确的访问控制,是生产环境中推荐的配置方法。