一、确认公网网关和物理网卡
在 PVE 宿主机执行:
ip route
示例:default via 103.254.63.1 dev enp3s0
记录以下信息:
- 公网网卡:enp3s0
- 公网 IP:103.254.63.80/25
- 公网网关:103.254.63.1
二、配置 PVE 网络
- 执行,然后清空内容
nano /etc/network/interfaces
- 把示例配置内容,修改为你的!
- 公网网卡:enp3s0
- 公网 IP:103.254.63.80/25
- 公网网关:103.254.63.1
auto lo
iface lo inet loopback
# 物理网卡
auto enp3s0
iface enp3s0 inet manual
# 公网桥
auto vmbr0
iface vmbr0 inet static
address 103.254.63.80/25
gateway 103.254.63.1
bridge-ports enp3s0
bridge-stp off
bridge-fd 0
# NAT 内网桥
auto vmbr1
iface vmbr1 inet static
address 192.168.100.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
应用配置:
ifreload -a
远程操作时建议保留当前 SSH 会话,避免网络配置错误后失联。
检查:
ip -br addr
ip route
应看到:
vmbr0 103.254.63.80/25
vmbr1 192.168.100.1/24
默认路由应为:
default via 103.254.63.1 dev vmbr0
三、开启 IPv4 转发
创建配置:
cat >/etc/sysctl.d/99-pve-forward.conf <<'EOF'
net.ipv4.ip_forward=1
EOF
立即生效:
sysctl --system
检查:
sysctl net.ipv4.ip_forward
应显示:net.ipv4.ip_forward = 1
只需配置一次,重启后自动生效。
四、安装 iptables 持久化工具
apt update
apt install iptables-persistent -y
安装时如询问是否保存当前规则,可以选择:Yes
五、配置内网 NAT 上网
- 添加 MASQUERADE
先检查规则是否存在,避免重复添加:
iptables -t nat -C POSTROUTING \
-s 192.168.100.0/24 \
-o vmbr0 \
-j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING \
-s 192.168.100.0/24 \
-o vmbr0 \
-j MASQUERADE
- 允许内网访问公网
iptables -C FORWARD \
-i vmbr1 -o vmbr0 \
-s 192.168.100.0/24 \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT 2>/dev/null || \
iptables -A FORWARD \
-i vmbr1 -o vmbr0 \
-s 192.168.100.0/24 \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT
允许公网返回数据:
iptables -C FORWARD \
-i vmbr0 -o vmbr1 \
-d 192.168.100.0/24 \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT 2>/dev/null || \
iptables -A FORWARD \
-i vmbr0 -o vmbr1 \
-d 192.168.100.0/24 \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT
- 保存规则
netfilter-persistent save
检查:
iptables -t nat -L POSTROUTING -n -v
iptables -L FORWARD -n -v
应看到:
MASQUERADE all -- 192.168.100.0/24 0.0.0.0/0
检查持久化文件:
grep -E 'MASQUERADE|192\.168\.100' /etc/iptables/rules.v4
六、安装并配置 DHCP
安装:
apt install dnsmasq -y
创建配置文件:
cat >/etc/dnsmasq.d/vmbr1.conf <<'EOF'
interface=vmbr1
bind-dynamic
dhcp-range=192.168.100.10,192.168.100.200,255.255.255.0,12h
dhcp-option=option:router,192.168.100.1
dhcp-option=option:dns-server,223.5.5.5,8.8.8.8
EOF
检查配置:
dnsmasq --test
正常应显示:dnsmasq: syntax check OK
启动并设置开机启动:
systemctl enable --now dnsmasq
重启:
systemctl restart dnsmasq
检查:
systemctl status dnsmasq --no-pager
应显示:Active: active (running)
查看 DHCP 日志:
journalctl -u dnsmasq -n 50 --no-pager
七、添加 TCP 端口转发
示例:
- 公网端口:25701
- VM IP:192.168.100.185
- VM 端口:2002
- 协议:TCP
- 添加 DNAT
iptables -t nat -C PREROUTING \
-i vmbr0 \
-p tcp \
--dport 25701 \
-j DNAT \
--to-destination 192.168.100.185:2002 2>/dev/null || \
iptables -t nat -A PREROUTING \
-i vmbr0 \
-p tcp \
--dport 25701 \
-j DNAT \
--to-destination 192.168.100.185:2002
- 允许公网访问 VM
iptables -C FORWARD \
-i vmbr0 -o vmbr1 \
-p tcp \
-d 192.168.100.185 \
--dport 2002 \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT 2>/dev/null || \
iptables -A FORWARD \
-i vmbr0 -o vmbr1 \
-p tcp \
-d 192.168.100.185 \
--dport 2002 \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT
返回流量已经由前面的通用规则允许:
vmbr1 → vmbr0,ESTABLISHED,RELATED
因此通常不需要再为每个端口单独添加返回规则。
保存:
netfilter-persistent save
检查:
iptables -t nat -L PREROUTING -n -v --line-numbers
iptables -L FORWARD -n -v --line-numbers
八、端口转发模板
只需要修改以下内容:
- 公网端口
- VM IP
- VM 内部端口
- TCP 或 UDP
TCP 模板:
PUBLIC_PORT=25701
VM_IP=192.168.100.185
VM_PORT=2002
iptables -t nat -A PREROUTING \
-i vmbr0 \
-p tcp \
--dport "$PUBLIC_PORT" \
-j DNAT \
--to-destination "$VM_IP:$VM_PORT"
iptables -A FORWARD \
-i vmbr0 -o vmbr1 \
-p tcp \
-d "$VM_IP" \
--dport "$VM_PORT" \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT
netfilter-persistent save
九、删除端口转发规则
方法一:按完整规则删除
删除 DNAT:
iptables -t nat -D PREROUTING \
-i vmbr0 \
-p tcp \
--dport 25701 \
-j DNAT \
--to-destination 192.168.100.185:2002
删除 FORWARD:
iptables -D FORWARD \
-i vmbr0 -o vmbr1 \
-p tcp \
-d 192.168.100.185 \
--dport 2002 \
-m conntrack --ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT
保存:
netfilter-persistent save
方法二:按行号删除
先查看行号:
iptables -t nat -L PREROUTING -n -v --line-numbers
iptables -t nat -L POSTROUTING -n -v --line-numbers
iptables -L FORWARD -n -v --line-numbers
删除第一条 DNAT 规则,执行以下命令:
iptables -t nat -D PREROUTING 1
验证结果
iptables -t nat -L PREROUTING -n -v --line-numbers
例如:删除 PREROUTING 第 5和4 条:必须先删序号大的,再删序号小的
iptables -D FORWARD 5
iptables -D FORWARD 4
删除后保存:
netfilter-persistent save
十、注意事项
所有命令都在 PVE 宿主机执行,VM 网络测试命令除外。
每次新增、删除或修改 iptables 规则后,都要执行:
netfilter-persistent save
常见问题
PVE虚拟机网络超时、容器端口映射及ZFS磁盘容量问题的排查与解决方法如下。已为您整理为留档保存的格式。
一、PVE虚拟机网络超时排查与解决
(以构建Docker错误为例)
当PVE虚拟机内部使用NAT/桥接映射时,网络超时通常由以下三个原因引起。请按优先级依次排查与解决:
- 配置 Docker 镜像加速源
在VM终端中执行以下命令,直接复制整段命令并按回车:
mkdir -p /etc/docker
cat <<EOF > /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.net",
"https://mirror.gcr.io"
]
}
EOF
systemctl daemon-reload
systemctl restart docker
- 修改 DNS 解析
在VM终端中执行以下命令,直接复制整段命令并按回车:
cat <<EOF > /etc/resolv.conf
nameserver 223.5.5.5
nameserver 119.29.29.29
nameserver 8.8.8.8
EOF
- 修改 Dockerfile(避免拉取语法插件)
进入项目目录(例如 /opt/pan):
cd /opt/pan
nano Dockerfile
在编辑器中找到 # syntax=docker/dockerfile:1.7 这一行,并将其完全删除。保存并退出编辑器后,重新运行构建命令。
二、容器端口映射问题
- 如果容器的端口映射显示为
127.0.0.1:8080->8080/tcp,这意味着该端口仅能被容器宿主机自身访问,外部无法访问。
解决方法: 将端口映射中的 127.0.0.1 修改为 0.0.0.0。
- 宿主机使用
Caddy反向代理 VM
推荐直接使用 Caddy 反向代理到虚拟机的内部 IP 和端口:
os.abc.xyz {
encode zstd gzip
reverse_proxy http://192.168.100.50:8080 {
transport http {
read_timeout 1h
write_timeout 1h
}
}
}
三、前端仅显示单块硬盘容量
示例:OVH 16THDD 安装 PVE9 组 RAID 10,前端仅显示单块硬盘容量,这是因为 ZFS 文件系统设置了配额(quota)
解决方法: 取消 data/zd0 的配额,使其能够使用整个 ZFS 池的容量:
zfs set quota=none data/zd0
执行后,再次运行 zfs list 命令进行确认。如果不成功,继续往下操作!
也就是说,你前面并没有真正执行成功 growpart,或者根本还没执行它。当前这一步还没到 ZFS 扩容,必须先把四个 part5 从约 1.8T 扩到约 3.6T。
先执行:
which growpart
如果没有任何输出,就安装:
apt update
apt install -y cloud-guest-utils
接下来执行:
growpart /dev/sda 5
growpart /dev/sdb 5
growpart /dev/sdc 5
growpart /dev/sdd 5
正常成功时应该看到类似:CHANGED: partition=5 ...
执行完先不要马上做 zpool online -e,先检查:
fdisk -l /dev/sda
fdisk -l /dev/sdb
fdisk -l /dev/sdc
fdisk -l /dev/sdd
我们希望看到 sda5/sdb5/sdc5/sdd5 从:1.8T 变成约:3.6T
如果这一步成功,再执行:
zpool set autoexpand=on data
然后:
zpool online -e data wwn-0x5000cca0bcd72307-part5
zpool online -e data wwn-0x5000cca250d68821-part5
zpool online -e data wwn-0x5000cca0bcdaa5a5-part5
zpool online -e data wwn-0x5000cca097cffe88-part5
最后检查:
zpool list
zfs list
目标应该接近:
data SIZE ≈ 7.2T
data/zd0 AVAIL ≈ 7.0T
后建议你再执行一次:
zpool status
zpool get autoexpand data
zfs get quota data/zd0
正常应该分别看到:
state: ONLINE
autoexpand: on
quota: none
如果是这样,这部分就彻底处理完成了。
