在 Oracle Cloud ARM 服务器上安装 Proxmox VE 9,并配置 LXC NAT 网络

Oracle Cloud ARM 安装 Proxmox VE 9:面向 LXC 的完整实战教程

本文记录一次在 Oracle Cloud ARM 云服务器上安装 Proxmox VE 9,并把它作为 LXC 容器平台使用的完整过程。

重点不是 KVM 虚拟机,而是 ARM64 LXC:安装 PVE、配置 OCI 安全的 NAT 网络、下载 ARM64 容器模板、创建 Debian / Ubuntu / OpenWrt / Kali / Oracle Linux 容器,以及把容器服务通过宿主机公网高端口转发出去。

变量约定

下面所有公网 IP、密码、端口都使用占位符。照抄时请替换成你自己的值。

<PUBLIC_IP>             你的云服务器公网 IP,例如 203.0.113.10
<HOST_PRIVATE_IP>       云服务器在 OCI VCN 里的内网 IP,例如 10.0.0.30
<ROOT_PASSWORD>         宿主机 root 密码
<CT_ROOT_PASSWORD>      容器 root 密码
<HOST_PORT>             宿主机公网高端口,例如 21025
<CT_IP>                 容器内网 IP,例如 10.10.10.104
<CT_SERVICE_PORT>       容器服务端口,例如 SSH 是 22,HTTP 是 80

本文示例网络:

宿主主网卡:enp0s3
宿主公网 IP:<PUBLIC_IP>
宿主 OCI 内网 IP:<HOST_PRIVATE_IP>
LXC bridge:vmbr0
LXC 网关:10.10.10.1
LXC 网段:10.10.10.0/24
NAT 出口网卡:enp0s3

适用场景

本文适合:

  • Oracle Cloud Infrastructure,也就是 OCI
  • ARM64 / AArch64 实例
  • Debian GNU/Linux 13 trixie
  • Proxmox VE 9.x
  • 主要跑 LXC 容器
  • 不要求 KVM 虚拟机
  • 容器通过 NAT 出网
  • 容器服务通过宿主机公网高端口转发访问

一次实际安装后的版本示例:

pve-manager/9.2.9
running kernel: 7.0.14-6-pve

先说结论

Oracle Cloud ARM 实例可以安装 Proxmox VE 9,但建议把它当成 LXC 容器管理平台,而不是完整虚拟化平台。

很多 OCI ARM 实例没有 /dev/kvm,这会影响 KVM 虚拟机。但 LXC 容器不依赖 KVM,所以可以正常使用。

推荐路线:

  1. 使用 Debian 13 trixie ARM64。
  2. 添加 Proxmox VE 9 trixie arm64 软件源。
  3. 安装 PVE 内核并重启。
  4. 安装 proxmox-ve
  5. 禁用 enterprise 源。
  6. 配置独立 LXC NAT bridge:vmbr0
  7. 从 Linux Containers 镜像站下载 ARM64 CT 模板。
  8. 创建容器时使用静态内网 IP。
  9. 需要公网访问的服务,在宿主机上做 DNAT 和 FORWARD。

为什么不 DD 重装

很多教程会用第三方 DD 脚本直接刷 Proxmox 镜像。如果当前系统已经是 Debian 13 ARM64,就没必要这么做。

直接 apt 安装更稳:

  • 不需要重刷系统盘。
  • 不容易破坏 OCI 的 SSH 和网卡配置。
  • 出问题时更容易排查。
  • 更适合只跑 LXC 的用途。

注意:Proxmox VE 8 的 bookworm 源主要是 amd64;ARM64 应使用 Proxmox VE 9 的 trixie 源。

安装前检查

确认架构:

uname -m

期望看到:

aarch64

确认系统版本:

cat /etc/os-release

期望是 Debian 13 trixie。

检查 KVM:

ls -l /dev/kvm

如果提示不存在,不用慌。没有 /dev/kvm 只是不适合跑 KVM 虚拟机,LXC 仍然可以用。

修改 hostname

Proxmox 不建议 hostname 是 localhost。这里以 pve 为例:

echo pve > /etc/hostname
hostnamectl set-hostname pve

修改 /etc/hosts,把主机名指向 OCI 内网 IP:

<HOST_PRIVATE_IP> pve.local pve

例如:

10.0.0.30 pve.local pve

如果机器上有 cloud-init,建议防止重启后 hostname 被改回去:

if [ -f /etc/cloud/cloud.cfg ]; then
  grep -q '^preserve_hostname:' /etc/cloud/cloud.cfg \
    && sed -i 's/^preserve_hostname:.*/preserve_hostname: true/' /etc/cloud/cloud.cfg \
    || echo 'preserve_hostname: true' >> /etc/cloud/cloud.cfg
fi

安装基础工具

apt update
apt install -y ca-certificates wget curl gnupg

添加 Proxmox VE 9 ARM64 软件源

创建 keyring 目录:

install -d -m 0755 /etc/apt/keyrings

下载 Proxmox trixie 源密钥:

wget -O /etc/apt/keyrings/proxmox-release-trixie.gpg \
  https://enterprise.proxmox.com/debian/proxmox-release-trixie.gpg

添加 no-subscription 源:

cat > /etc/apt/sources.list.d/pve-install-repo.list <<'EOF'
deb [arch=arm64 signed-by=/etc/apt/keyrings/proxmox-release-trixie.gpg] http://download.proxmox.com/debian/pve trixie pve-no-subscription
EOF

更新软件源:

apt update

升级系统并安装 PVE 内核

apt full-upgrade -y
apt install -y proxmox-default-kernel

安装内核后重启:

systemctl reboot

重启回来后检查内核:

uname -r

正常会看到类似:

7.0.14-6-pve

安装 Proxmox VE 主体

为了避免 Postfix 弹交互窗口,可以先预置成本地投递:

echo 'postfix postfix/mailname string pve.local' | debconf-set-selections
echo 'postfix postfix/main_mailer_type select Local only' | debconf-set-selections

安装 PVE:

DEBIAN_FRONTEND=noninteractive apt install -y proxmox-ve postfix open-iscsi chrony

检查版本:

pveversion | head -n 1

检查失败服务:

systemctl --no-pager --state=failed

正常情况下应显示:

0 loaded units listed.

禁用 enterprise 源

安装 proxmox-ve 后,系统可能会自动生成 enterprise 源。没有订阅时,后续 apt update 可能报错。

如果存在:

/etc/apt/sources.list.d/pve-enterprise.sources

建议改成:

Enabled: no
Types: deb
URIs: https://enterprise.proxmox.com/debian/pve
Suites: trixie
Components: pve-enterprise
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg

注意:deb822 格式不要只注释 Types:,否则 apt 会认为源文件 malformed。正确做法是加:

Enabled: no

然后验证:

apt update
apt -s upgrade

访问 PVE 面板

PVE Web 默认端口是 8006

https://<PUBLIC_IP>:8006/

登录:

用户名:root
Realm:Linux PAM standard authentication
密码:宿主机 root 密码

如果打不开,检查 OCI 安全列表或网络安全组是否放行 TCP 8006

OCI 上为什么不要直接桥接主网卡

OCI 的网络不适合把公网主网卡直接桥接给容器。原因包括:

  • OCI VNIC 对 MAC/IP 绑定比较严格。
  • 公网 IP 是绑定到云网卡上的,不是普通二层网络里随便漂。
  • 直接桥接 enp0s3 可能影响宿主机 SSH。
  • 容器公网暴露应该由宿主机 NAT/转发处理。

更稳的方案是:

公网流量
  ↓
OCI VNIC / enp0s3
  ↓
PVE 宿主机 iptables DNAT
  ↓
vmbr0
  ↓
LXC 容器 10.10.10.x

容器出网路径:

LXC 容器 10.10.10.x
  ↓
网关 10.10.10.1,也就是 vmbr0
  ↓
宿主机 MASQUERADE
  ↓
enp0s3
  ↓
互联网

配置 LXC NAT 网络

本文使用:

宿主主网卡:enp0s3
LXC bridge:vmbr0
LXC 网段:10.10.10.0/24
LXC 网关:10.10.10.1
NAT 出口:enp0s3

为什么要用 dummy0

正常 PVE 空桥可以写 bridge-ports none,但某些 ifupdown2 版本对空 bridge 写法不友好,可能报错。

另外,有些 PVE 9 环境不会把 /etc/network/interfaces.d/ 里的 bridge 显示到创建 CT 的下拉框里。

稳定写法:

  • vmbr0 写进 /etc/network/interfaces 主文件。
  • 创建 dummy0 虚拟网卡。
  • vmbr0 桥接 dummy0
  • 不要把 OCI 主网卡 enp0s3 加进 vmbr0

最终 /etc/network/interfaces 示例

编辑 /etc/network/interfaces

auto lo
iface lo inet loopback

auto enp0s3
iface enp0s3 inet dhcp

auto dummy0
iface dummy0 inet manual
        pre-up ip link add dummy0 type dummy || true
        post-down ip link delete dummy0 type dummy 2>/dev/null || true

auto vmbr0
iface vmbr0 inet static
        address 10.10.10.1/24
        bridge-ports dummy0
        bridge-stp off
        bridge-fd 0
        post-up iptables -t nat -C POSTROUTING -s 10.10.10.0/24 -o enp0s3 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o enp0s3 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s 10.10.10.0/24 -o enp0s3 -j MASQUERADE 2>/dev/null || true

启用 IPv4 转发:

cat > /etc/sysctl.d/99-pve-lxc-nat.conf <<'EOF'
net.ipv4.ip_forward=1
EOF

sysctl --system

检查:

sysctl net.ipv4.ip_forward
iptables -t nat -S POSTROUTING | grep 10.10.10.0/24

期望看到:

net.ipv4.ip_forward = 1
-A POSTROUTING -s 10.10.10.0/24 -o enp0s3 -j MASQUERADE

远程云服务器上应用网络配置有断连风险。建议先检查语法:

ifreload -a -s

确认有控制台或救援方式后再实际应用。

如果只是让 PVE 面板刷新网络信息,可以重启 PVE API 和 Web:

systemctl restart pvedaemon pveproxy

检查 PVE 是否识别 vmbr0

pvesh get /nodes/$(hostname)/network --type any_bridge

应能看到 vmbr0,类型是 bridge

IPv6 / DHCPv6 注意事项

OCI 可能已经给宿主机分配了 IPv6 地址,但这不一定适合交给 ifupdown2 管理。

如果 /etc/network/interfaces 里写了:

iface enp0s3 inet6 auto

或类似 DHCPv6 配置,ifreload -a 可能会触发 dhclient -6,然后失败。

如果容器只需要 IPv4 NAT,建议宿主机 ifupdown2 配置里只保留:

auto enp0s3
iface enp0s3 inet dhcp

让 OCI 运行时自己处理宿主 IPv6,LXC 网络则走 IPv4 NAT。

ARM64 CT 模板从哪里找

PVE 自带模板列表里的 ARM64 模板很少。可以从 Linux Containers 镜像站下载:

https://images.linuxcontainers.org/images/

目录格式大致是:

https://images.linuxcontainers.org/images/<发行版>/<版本>/arm64/default/<日期>/rootfs.tar.xz

例如 Debian 13 trixie ARM64:

https://images.linuxcontainers.org/images/debian/trixie/arm64/default/

进入最新日期目录,下载 rootfs.tar.xz 到 PVE 模板目录:

cd /var/lib/vz/template/cache
wget -O debian-13-trixie-default_YYYYMMDD_arm64.tar.xz \
  https://images.linuxcontainers.org/images/debian/trixie/arm64/default/YYYYMMDD_HH:MM/rootfs.tar.xz

如果目录里有 SHA256SUMS,建议校验:

wget -O SHA256SUMS \
  https://images.linuxcontainers.org/images/debian/trixie/arm64/default/YYYYMMDD_HH:MM/SHA256SUMS

sha256sum debian-13-trixie-default_YYYYMMDD_arm64.tar.xz

把输出和 SHA256SUMS 里的 rootfs.tar.xz 对应值比较。

确认 PVE 能识别模板:

pveam list local

创建普通 Debian / Ubuntu 容器

假设创建一个 Debian 容器:

VMID:100
hostname:debian
IP:10.10.10.101/24
网关:10.10.10.1
DNS:1.1.1.1 8.8.8.8
CPU:1 核
内存:2048 MB

命令示例:

pct create 100 local:vztmpl/debian-13-trixie-default_YYYYMMDD_arm64.tar.xz \
  --arch arm64 \
  --ostype debian \
  --hostname debian \
  --cores 1 \
  --memory 2048 \
  --swap 512 \
  --rootfs local:8 \
  --net0 name=eth0,bridge=vmbr0,ip=10.10.10.101/24,gw=10.10.10.1 \
  --nameserver '1.1.1.1 8.8.8.8' \
  --searchdomain local \
  --unprivileged 1 \
  --features nesting=1 \
  --onboot 1

启动:

pct start 100

设置 root 密码:

pct exec 100 -- passwd root

检查网络:

pct exec 100 -- ip addr show eth0
pct exec 100 -- ip route
pct exec 100 -- cat /etc/resolv.conf
pct exec 100 -- ping -c 3 1.1.1.1
pct exec 100 -- getent hosts deb.debian.org

创建 OpenWrt 容器

OpenWrt 比普通 Debian/Ubuntu 特殊。它默认把 eth0 当成 LAN,并且常见默认 IP 是 192.168.1.1,所以 PVE 的 net0 ip=... 不一定会自动生效。

创建示例:

pct create 102 local:vztmpl/openwrt-24.10.x-armsr-armv8-rootfs.tar.gz \
  --arch arm64 \
  --ostype unmanaged \
  --hostname openwrt \
  --cores 1 \
  --memory 2048 \
  --swap 512 \
  --rootfs local:2 \
  --net0 name=eth0,bridge=vmbr0,ip=10.10.10.103/24,gw=10.10.10.1 \
  --nameserver '1.1.1.1 8.8.8.8' \
  --searchdomain local \
  --unprivileged 0 \
  --features nesting=1 \
  --onboot 1

启动:

pct start 102

进入容器后修改 OpenWrt 网络:

pct exec 102 -- sh -c 'cp /etc/config/network /etc/config/network.before-pve-nat'

pct exec 102 -- sh -c "cat > /etc/config/network <<'EOF'
config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd00:10:10:10::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth0'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '10.10.10.103'
        option netmask '255.255.255.0'
        option gateway '10.10.10.1'
        list dns '1.1.1.1'
        list dns '8.8.8.8'
EOF
/etc/init.d/network restart"

设置 OpenWrt root 密码:

pct exec 102 -- passwd root

安装 LuCI 中文包示例:

pct exec 102 -- opkg update
pct exec 102 -- opkg install luci-i18n-base-zh-cn luci-i18n-firewall-zh-cn
pct exec 102 -- /etc/init.d/uhttpd restart

如果要安装主题,优先用官方源:

pct exec 102 -- opkg install luci-theme-material
pct exec 102 -- uci set luci.main.mediaurlbase='/luci-static/material'
pct exec 102 -- uci commit luci
pct exec 102 -- /etc/init.d/uhttpd restart

第三方 IPK 主题建议下载后先校验 hash,再安装。

创建 Kali 容器

Kali ARM64 模板也可以从 Linux Containers 镜像站找:

https://images.linuxcontainers.org/images/kali/current/arm64/default/

下载示例:

cd /var/lib/vz/template/cache
wget -O kali-current-arm64-default_YYYYMMDD_HHMM.tar.xz \
  https://images.linuxcontainers.org/images/kali/current/arm64/default/YYYYMMDD_HH:MM/rootfs.tar.xz

校验示例:

wget -O /tmp/kali-SHA256SUMS \
  https://images.linuxcontainers.org/images/kali/current/arm64/default/YYYYMMDD_HH:MM/SHA256SUMS

sha256sum kali-current-arm64-default_YYYYMMDD_HHMM.tar.xz

创建 Kali CT 示例:

pct create 103 local:vztmpl/kali-current-arm64-default_YYYYMMDD_HHMM.tar.xz \
  --arch arm64 \
  --ostype unmanaged \
  --hostname kali \
  --cores 1 \
  --memory 4096 \
  --swap 512 \
  --rootfs local:12 \
  --net0 name=eth0,bridge=vmbr0,ip=10.10.10.104/24,gw=10.10.10.1 \
  --nameserver '1.1.1.1 8.8.8.8' \
  --searchdomain local \
  --unprivileged 0 \
  --features nesting=1 \
  --onboot 1

启动:

pct start 103

有些 ostype unmanaged 镜像不会自动应用 PVE 的 IPv4 配置。如果启动后发现只有 IPv6 link-local,需要在容器里写静态网络。

Kali 使用 systemd-networkd 的示例:

pct exec 103 -- bash -lc "cat > /etc/systemd/network/10-eth0.network <<'EOF'
[Match]
Name=eth0

[Network]
Address=10.10.10.104/24
Gateway=10.10.10.1
DNS=1.1.1.1
DNS=8.8.8.8
Domains=local
EOF
systemctl enable --now systemd-networkd
systemctl restart systemd-networkd
rm -f /etc/resolv.conf
printf 'search local\nnameserver 1.1.1.1\nnameserver 8.8.8.8\n' > /etc/resolv.conf"

Kali 的 DNS 可能优先返回 IPv6,但本文网络只有 IPv4 NAT。apt 可以强制 IPv4:

pct exec 103 -- bash -lc "printf 'Acquire::ForceIPv4 \"true\";\n' > /etc/apt/apt.conf.d/99-force-ipv4"

安装 SSH:

pct exec 103 -- bash -lc "apt-get -o Acquire::ForceIPv4=true update"
pct exec 103 -- bash -lc "DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::ForceIPv4=true install -y openssh-server"

允许 root 密码登录:

pct exec 103 -- passwd root

pct exec 103 -- bash -lc "install -d -m 0755 /etc/ssh/sshd_config.d
cat > /etc/ssh/sshd_config.d/99-root-login.conf <<'EOF'
PermitRootLogin yes
PasswordAuthentication yes
EOF
systemctl enable --now ssh || service ssh start"

验证:

pct exec 103 -- ss -ltn | grep ':22 '

创建 Oracle Linux 容器

Oracle Linux ARM64 模板目录示例:

https://images.linuxcontainers.org/images/oracle/10/arm64/default/

下载:

cd /var/lib/vz/template/cache
wget -O oracle-10-arm64-default_YYYYMMDD_HHMM.tar.xz \
  https://images.linuxcontainers.org/images/oracle/10/arm64/default/YYYYMMDD_HH:MM/rootfs.tar.xz

校验:

wget -O /tmp/oracle-SHA256SUMS \
  https://images.linuxcontainers.org/images/oracle/10/arm64/default/YYYYMMDD_HH:MM/SHA256SUMS

sha256sum oracle-10-arm64-default_YYYYMMDD_HHMM.tar.xz

创建 Oracle Linux CT:

pct create 104 local:vztmpl/oracle-10-arm64-default_YYYYMMDD_HHMM.tar.xz \
  --arch arm64 \
  --ostype unmanaged \
  --hostname oracle \
  --cores 1 \
  --memory 2048 \
  --swap 512 \
  --rootfs local:10 \
  --net0 name=eth0,bridge=vmbr0,ip=10.10.10.105/24,gw=10.10.10.1 \
  --nameserver '1.1.1.1 8.8.8.8' \
  --searchdomain local \
  --unprivileged 0 \
  --features nesting=1 \
  --onboot 1

启动:

pct start 104

如果没拿到 IPv4,可以用 NetworkManager 写静态配置:

pct exec 104 -- bash -lc "cat > /etc/NetworkManager/system-connections/eth0.nmconnection <<'EOF'

[connection]

id=eth0 type=ethernet interface-name=eth0 autoconnect=true

[ipv4]

method=manual addresses=10.10.10.105/24 gateway=10.10.10.1 dns=1.1.1.1;8.8.8.8; dns-search=local;

[ipv6]

method=ignore EOF chmod 600 /etc/NetworkManager/system-connections/eth0.nmconnection systemctl enable –now NetworkManager nmcli connection reload nmcli connection up eth0 || systemctl restart NetworkManager”

Oracle Linux 也建议强制 dnf 使用 IPv4:

pct exec 104 -- bash -lc "mkdir -p /etc/dnf/dnf.conf.d
printf 'ip_resolve=4\n' > /etc/dnf/dnf.conf.d/99-force-ipv4.conf"

安装 SSH:

pct exec 104 -- bash -lc "dnf -y --setopt=ip_resolve=4 install openssh-server"

允许 root 密码登录:

pct exec 104 -- passwd root

pct exec 104 -- bash -lc "install -d -m 0755 /etc/ssh/sshd_config.d
cat > /etc/ssh/sshd_config.d/99-root-login.conf <<'EOF'
PermitRootLogin yes
PasswordAuthentication yes
EOF
systemctl enable --now sshd || /usr/sbin/sshd"

验证:

pct exec 104 -- ss -ltn | grep ':22 '

注意:某些极简 Oracle Linux rootfs 可能没有 hostname 命令。这不影响 SSH。可以先写 /etc/hostname

pct exec 104 -- sh -c "echo oracle > /etc/hostname"

容器 DNS 怎么填

本文宿主机只做 NAT,没有配置 DNS 转发服务。所以容器 DNS 不要填 10.10.10.1

推荐:

DNS:1.1.1.1
备用 DNS:8.8.8.8

PVE 命令行可以写:

--nameserver '1.1.1.1 8.8.8.8'

PVE 面板里如果只有一个输入框,也可以填:

1.1.1.1 8.8.8.8

端口转发原理

容器在 10.10.10.0/24 私网里,外网不能直接访问。要让公网访问容器服务,需要在 PVE 宿主机上做两件事:

  1. DNAT:把宿主机公网高端口改写到容器 IP 和服务端口。
  2. FORWARD:允许这条转发流量通过宿主机。

以把容器 SSH 暴露出去为例:

公网访问:ssh -p <HOST_PORT> root@<PUBLIC_IP>
  ↓
宿主机 enp0s3 收到 TCP <HOST_PORT>
  ↓
iptables PREROUTING DNAT
  ↓
转发到 <CT_IP>:22
  ↓
容器 sshd 响应

以 Web 服务为例:

公网访问:http://<PUBLIC_IP>:<HOST_PORT>/
  ↓
宿主机 enp0s3 收到 TCP <HOST_PORT>
  ↓
DNAT 到 <CT_IP>:80
  ↓
容器 HTTP 服务响应

临时添加端口转发

示例 1:把 OpenWrt LuCI 从公网高端口转发到容器 80

宿主公网端口:29971
容器 IP:10.10.10.103
容器服务端口:80
公网访问:http://<PUBLIC_IP>:29971/

命令:

iptables -t nat -A PREROUTING \
  -i enp0s3 -p tcp --dport 29971 \
  -j DNAT --to-destination 10.10.10.103:80

iptables -A FORWARD \
  -i enp0s3 -o vmbr0 \
  -p tcp -d 10.10.10.103 --dport 80 \
  -j ACCEPT

示例 2:把 Kali SSH 转发出去。

宿主公网端口:21025
容器 IP:10.10.10.104
容器服务端口:22
公网访问:ssh -p 21025 root@<PUBLIC_IP>

命令:

iptables -t nat -A PREROUTING \
  -i enp0s3 -p tcp --dport 21025 \
  -j DNAT --to-destination 10.10.10.104:22

iptables -A FORWARD \
  -i enp0s3 -o vmbr0 \
  -p tcp -d 10.10.10.104 --dport 22 \
  -j ACCEPT

示例 3:把 Oracle Linux SSH 转发出去。

宿主公网端口:36078
容器 IP:10.10.10.105
容器服务端口:22
公网访问:ssh -p 36078 root@<PUBLIC_IP>

命令:

iptables -t nat -A PREROUTING \
  -i enp0s3 -p tcp --dport 36078 \
  -j DNAT --to-destination 10.10.10.105:22

iptables -A FORWARD \
  -i enp0s3 -o vmbr0 \
  -p tcp -d 10.10.10.105 --dport 22 \
  -j ACCEPT

这些规则是临时的,重启或网络重载后可能丢失。生产使用建议持久化。

持久化端口转发

本文采用把规则写进 /etc/network/interfacesvmbr0 段。

改前先备份:

cp -a /etc/network/interfaces /etc/network/interfaces.backup.$(date +%Y%m%d-%H%M%S)

iface vmbr0 inet static 下面加入转发规则。

OpenWrt LuCI 示例:

        # openwrt-luci-forward
        post-up iptables -t nat -C PREROUTING -i enp0s3 -p tcp --dport 29971 -j DNAT --to-destination 10.10.10.103:80 2>/dev/null || iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 29971 -j DNAT --to-destination 10.10.10.103:80
        post-up iptables -C FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.103 --dport 80 -j ACCEPT 2>/dev/null || iptables -A FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.103 --dport 80 -j ACCEPT
        post-down iptables -t nat -D PREROUTING -i enp0s3 -p tcp --dport 29971 -j DNAT --to-destination 10.10.10.103:80 2>/dev/null || true
        post-down iptables -D FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.103 --dport 80 -j ACCEPT 2>/dev/null || true

Kali SSH 示例:

        # kali-ssh-forward
        post-up iptables -t nat -C PREROUTING -i enp0s3 -p tcp --dport 21025 -j DNAT --to-destination 10.10.10.104:22 2>/dev/null || iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 21025 -j DNAT --to-destination 10.10.10.104:22
        post-up iptables -C FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.104 --dport 22 -j ACCEPT 2>/dev/null || iptables -A FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.104 --dport 22 -j ACCEPT
        post-down iptables -t nat -D PREROUTING -i enp0s3 -p tcp --dport 21025 -j DNAT --to-destination 10.10.10.104:22 2>/dev/null || true
        post-down iptables -D FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.104 --dport 22 -j ACCEPT 2>/dev/null || true

Oracle Linux SSH 示例:

        # oracle-ssh-forward
        post-up iptables -t nat -C PREROUTING -i enp0s3 -p tcp --dport 36078 -j DNAT --to-destination 10.10.10.105:22 2>/dev/null || iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 36078 -j DNAT --to-destination 10.10.10.105:22
        post-up iptables -C FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.105 --dport 22 -j ACCEPT 2>/dev/null || iptables -A FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.105 --dport 22 -j ACCEPT
        post-down iptables -t nat -D PREROUTING -i enp0s3 -p tcp --dport 36078 -j DNAT --to-destination 10.10.10.105:22 2>/dev/null || true
        post-down iptables -D FORWARD -i enp0s3 -o vmbr0 -p tcp -d 10.10.10.105 --dport 22 -j ACCEPT 2>/dev/null || true

这里的 -C ... || -A ... 是为了避免重复添加同一条规则。

选择公网高端口

建议用 10000 以上的随机端口,避开常见服务端口。

查看当前监听端口:

ss -ltn

查看已有 DNAT 端口:

iptables -t nat -S PREROUTING

随机挑一个端口:

shuf -i 10000-60999 -n 1

确认端口没被占用:

PORT=21025
ss -ltn | grep -q ":$PORT " && echo "port in use" || echo "port free"
iptables -t nat -S PREROUTING | grep -- "--dport $PORT " && echo "dnat exists" || echo "dnat free"

OCI 安全列表 / 网络安全组

宿主机 iptables 配好以后,OCI 侧也要放行对应公网端口。

例如你要访问:

ssh -p 21025 root@<PUBLIC_IP>

OCI 安全列表或 NSG 需要允许:

源:你的客户端 IP,或 0.0.0.0/0
协议:TCP
目标端口:21025

PVE 面板则需要允许:

TCP 8006

OpenWrt LuCI 示例需要允许:

TCP 29971

如果 iptables 没问题但公网访问不通,优先查 OCI 安全列表/NSG。

验证端口转发

验证容器服务是否监听:

pct exec 103 -- ss -ltn | grep ':22 '
pct exec 104 -- ss -ltn | grep ':22 '
pct exec 102 -- netstat -ltnp | grep ':80 '

验证宿主机规则:

iptables -t nat -S PREROUTING | grep 21025
iptables -S FORWARD | grep 10.10.10.104

从外部验证 SSH:

ssh -p 21025 root@<PUBLIC_IP>
ssh -p 36078 root@<PUBLIC_IP>

从外部验证 HTTP:

curl -I http://<PUBLIC_IP>:29971/

如果返回 HTTP/1.1 200 OK302 或 LuCI 登录页内容,说明通了。

基础检查命令

查看容器列表:

pct list

查看容器配置:

pct config 103

进入容器:

pct enter 103

在容器里执行命令:

pct exec 103 -- uname -m
pct exec 103 -- cat /etc/os-release

检查 PVE 存储:

pvesm status

检查本地模板:

pveam list local

检查 bridge:

ip -br addr
bridge link
pvesh get /nodes/$(hostname)/network --type any_bridge

检查 NAT:

sysctl net.ipv4.ip_forward
iptables -t nat -S
iptables -S FORWARD

常见问题

PVE 创建 CT 时桥接下拉框没有 vmbr0

优先检查:

pvesh get /nodes/$(hostname)/network --type any_bridge

如果看不到 vmbr0,尝试:

  • vmbr0 配置写入 /etc/network/interfaces 主文件。
  • 不要只写在 /etc/network/interfaces.d/vmbr0
  • vmbr0 使用 bridge-ports dummy0
  • 重启 pvedaemonpveproxy
systemctl restart pvedaemon pveproxy

ifupdown2 不接受 bridge-ports none

某些环境会报:

bridge-ports: invalid value "none"

可以改用 dummy0

auto dummy0
iface dummy0 inet manual
        pre-up ip link add dummy0 type dummy || true
        post-down ip link delete dummy0 type dummy 2>/dev/null || true

auto vmbr0
iface vmbr0 inet static
        address 10.10.10.1/24
        bridge-ports dummy0
        bridge-stp off
        bridge-fd 0

容器没有 IPv4

如果 pct exec <VMID> -- ip addr 只看到 fe80::,说明镜像没有应用 PVE 注入的静态 IP。

处理方式:

  • Debian/Kali 这类 systemd 镜像:写 /etc/systemd/network/10-eth0.network
  • Oracle Linux/Fedora 系:写 NetworkManager 连接文件。
  • OpenWrt:改 /etc/config/network

容器能 ping IP,不能解析域名

检查:

pct exec <VMID> -- cat /etc/resolv.conf

推荐写:

nameserver 1.1.1.1
nameserver 8.8.8.8

不要写 10.10.10.1,除非宿主机上配置了 DNS 转发。

Kali apt 解析到 IPv6 后失败

如果网络只有 IPv4 NAT,Kali apt 可能解析到 IPv6 地址后失败。强制 apt 用 IPv4:

pct exec 103 -- bash -lc "printf 'Acquire::ForceIPv4 \"true\";\n' > /etc/apt/apt.conf.d/99-force-ipv4"

然后:

pct exec 103 -- apt-get update

Oracle dnf 解析到 IPv6 后失败

强制 dnf 用 IPv4:

pct exec 104 -- bash -lc "mkdir -p /etc/dnf/dnf.conf.d
printf 'ip_resolve=4\n' > /etc/dnf/dnf.conf.d/99-force-ipv4.conf"

或者执行安装时临时加:

dnf -y --setopt=ip_resolve=4 install openssh-server

公网端口访问不通

按顺序查:

  1. OCI 安全列表或 NSG 是否放行 <HOST_PORT>
  2. 宿主机 iptables -t nat -S PREROUTING 是否有 DNAT。
  3. 宿主机 iptables -S FORWARD 是否放行到容器。
  4. net.ipv4.ip_forward 是否为 1
  5. 容器服务是否监听对应端口。
  6. 容器 IP 是否正确。

命令:

sysctl net.ipv4.ip_forward
iptables -t nat -S PREROUTING
iptables -S FORWARD
pct exec <VMID> -- ss -ltn

PVE 面板显示硬盘变小

50G 云盘在 Linux 里可能显示约 49G,这是 GB/GiB 换算差异。ext4 还会预留一部分空间给 root,PVE 本身也会占用几 GB。

这属于正常情况,不是硬盘真的变小。

一个完整例子

目标:

PVE 宿主公网 IP:<PUBLIC_IP>
LXC 网段:10.10.10.0/24
OpenWrt:102,10.10.10.103,LuCI 80 -> 公网 29971
Kali:103,10.10.10.104,SSH 22 -> 公网 21025
Oracle Linux:104,10.10.10.105,SSH 22 -> 公网 36078

公网访问方式:

# OpenWrt LuCI
http://<PUBLIC_IP>:29971/

# Kali SSH
ssh -p 21025 root@<PUBLIC_IP>

# Oracle Linux SSH
ssh -p 36078 root@<PUBLIC_IP>

宿主机持久化规则放在 /etc/network/interfacesvmbr0 段,容器内部只需要确保服务监听自己的内网端口。

安全建议

  • 不要把 root 密码写进公开教程。
  • 公网 SSH 端口建议使用高端口,并在 OCI 安全列表里限制来源 IP。
  • 如果长期使用,建议改成密钥登录,然后关闭密码登录。
  • 公开 Web 面板前先设置强密码。
  • 第三方 OpenWrt 主题或 IPK 包先校验 hash,再安装。
  • 每次改 /etc/network/interfaces 前先备份。
  • 远程 reload 网络前确认有云控制台或救援方式。

总结

Oracle Cloud ARM 上安装 Proxmox VE 9 是可行的,但最适合作为 LXC 容器平台。

关键点:

  • 用 Debian 13 trixie ARM64。
  • 用 Proxmox VE 9 trixie arm64 源。
  • 没有 /dev/kvm 不影响 LXC。
  • OCI 主网卡不要桥进 vmbr0
  • 容器使用 vmbr0 + IPv4 NAT 出网。
  • 公网访问容器服务,在宿主机 enp0s3 上做 DNAT + FORWARD。
  • 转发规则写进 /etc/network/interfacesvmbr0 段持久化。
  • ARM64 模板从 Linux Containers 镜像站下载,并尽量做 SHA256 校验。

这套方案不需要 DD 重装,风险比刷第三方镜像低,也更适合 OCI 这种云网络环境。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇