PVE只有一个IP,如何让内部的虚拟机也能上网。--SNAT源地址转换
通常我们租用云厂商的VPS或者独服服务器,运营商基本只会给你提供一个公网IP,这样我们在PVE下创建的虚拟机/LXC容器就没有足够的IP进行分配。也就没法正常访问外部网络,因此我们需要在PVE下配置内部的桥接网络NAT,需要在PVE设置SNAT规则和DHCP。
首先,我们应该明确SNAT和DHCP各自的作用。SNAT,即源地址转换,用于将虚拟机的内部IP地址转换为宿主机的外部IP地址,这样虚拟机就可以访问外部网络。而DHCP则负责为虚拟机分配内部IP地址,简化网络配置。
配置SNAT和DHCP
这里拿我的腾讯轻量云4核4G8M的VPS来做个案例,已经安装了PVE8.4,运营商只给了一个IPv4和IPv6,目前PVE内部的LXC容器无法直接获取到IP地址,导致它们无法直接访问互联网。需要通过PVE的SNAT(源地址转换)和DHCP(自动分配IP地址给内部的虚拟机和容器),让这些虚拟机和容器能够上网。
安装dnsmasq
为了使用DHCP功能,需要额外安装 dnsmasq。通过以下命令执行:
apt install dnsmasq禁用默认的 dnsmasq 服务
systemctl disable --now dnsmasq配置SDN
确保你的PVE版本是8.2及以上,这些版本才开始支持SDN功能。
创建Simple区域
步骤:数据中心 → SDN → 区域 → 添加Simple → 填写名称ID → 勾选DHCP
创建Vnets
步骤:数据中心 → SDN → Vnets → 创建VNet → 填写名称 → 勾选区域如果想让虚拟机之间互不通信,禁止访问对方,只需要勾选【隔离端口】就好了。这里我没有这类需求就不勾选了
创建子网
步骤:数据中心 → SDN → Vnets → 选中创建好的VNet → 创建子网 → 填写子网网段和网关 → 勾选SNAT
配置DHCP范围
步骤:数据中心 → SDN → Vnets → 选中创建好的VNet → 选中子网 → DHCP范围 → 添加IP范围
都已设置完毕,我们需要应用更改。在SDN面板并单击“应用”来完成。确保网络重新加载任务成功完成。如果它完成且没有任何错误或警告,您应该能够使用新创建的 VNet。
配置防火墙
如果使用 PVE 防火墙,则还需要在 VNet 接口上允许 DHCP 转发和 DNS 流量。否则,您的访客将无法联系 dnsmasq 进行 DHCP 租约和 DNS 查询。为此,请向数据中心防火墙添加两个规则:一个用于 DNS 查询,另一个用于 DHCP 转发。这两个规则都应使用方向 “in”、作 “ACCEPT” 和 VNet 名称作为接口名称
对于 DNS 规则,您还应将目标地址设置为网络网关。这只允许 dnsmasq 服务器的 DNS 流量。如果您不设置它,则将允许所有 DNS 流量,这可用于规避其他防火墙规则。不能以相同的方式限制 DHCP,因为它需要首先能够发出广播消息。最后,将两者标记为已启用并保存规则。
创建LXC容器验证上网
创建虚拟机或者容器配置网络时,记得选择VNet作为网桥,并将IPv4设置为 DHCP,获取的IP段取决于您配置的子网。
访问外网成功
自定义DNS
Dnsmasq还可以为整个VNet提供DNS。如果要为VNet配置自定义DNS服务器,则需要通过编辑文件 /etc/pve/sdn/subnets.cfg并设置dhcp-dns-server配置来完成。
使用nano命令编辑nano /etc/pve/sdn/subnets.cfg,在里面加入一行dhcp-dns-server 8.8.8.8即可。
subnet: dhcpsnat-172.16.80.0-24
vnet vnet0
dhcp-range start-address=172.16.80.50,end-address=172.16.80.200
gateway 172.16.80.1
dhcp-dns-server 8.8.8.8
snat 1进阶玩法
因为是NAT网络,我们的虚拟机和LXC容器目前只能在NAT局域网下访问使用,如果要想在外面直接公网访问,还得做个端口转发工作。可以通过使用Socat和iptables这类端口转发工具进行转发。这类工具都是在命令行操作的上手有一定门槛,新手可以在PVE里安装个Lucky端口转发面板,转发规则直接在UI上配置,简单好上手。
Socat端口转发
可以通过socat端口转发将虚拟机/容器IP映射到VPS的公网ipv4上。
PVE预装了socat端口转发工具,只需要写入规则即可。
LXC容器信息
IP:172.16.80.99
ssh端口:22
转发TCP协议(在PVE Shell执行)
使用nohup命令后台侦听本机22222端口,并连接LXC容器172.16.80.99:22的TCP端口将日志输出到/root/socat.log
nohup socat TCP4-LISTEN:22222,reuseaddr,fork TCP4:172.16.80.99:22 >> /root/socat.log 2>&1 &转发UDP协议(在PVE Shell执行)
使用nohup命令后台侦听本机22222端口,并连接LXC容器172.16.80.99:22的UDP端口将日志输出到/root/socat.log
nohup socat -T 600 UDP4-LISTEN:22222,reuseaddr,fork UDP4:172.16.80.99:22 >> /root/socat.log 2>&1 &配置开机自启
执行以上规则,重启PVE就失效了,所以将规则写入开机自启让其永久生效。
创建rc-local.service自启服务
echo "[Unit]
Description=/etc/rc-local
ConditionPathExists=/etc/rc-local
[Service]
Type=forking
ExecStart=/etc/rc-local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/rc-local.service编辑rc-local文件
nano /etc/rc-local写入以下内容,并把容器需要转发的规则写入进来。
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# 转发TCP协议
nohup socat TCP4-LISTEN:22222,reuseaddr,fork TCP4:172.16.80.99:22 >> /root/socat.log 2>&1 &
# 转发UDP协议
nohup socat -T 600 UDP4-LISTEN:22222,reuseaddr,fork UDP4:172.16.80.99:22 >> /root/socat.log 2>&1 &设置开机自启
# 授予可执行权限
chmod +x /etc/rc-local
# 设置开机启动
systemctl enable rc-local.service
systemctl start rc-local.service到这里就能愉快的用上LXC容器了,折腾结束。
iptables端口转发
除了用Socat端口转发外,也可以使用Iptables进行转发,支持TCP/UDP和端口范围转发。
安装iptables
apt update && apt install iptables iproute2 iptables-persistent永久生效需修改 /etc/sysctl.conf,设置 net.ipv4.ip_forward=1 并运行 sysctl -p
echo 1 > /proc/sys/net/ipv4/ip_forward添加端口转发规则(DNAT)
使用iptables端口转发让LXC容器在外部也能正常访问。
单个端口转发DNAT 规则
# 外部端口22转发到172.16.80.99:22(tcp)
iptables -t nat -A PREROUTING -p tcp --dport 22 -j DNAT --to-destination 172.16.80.99:22
# 外部端口22转发到172.16.80.99:22(udp)
iptables -t nat -A PREROUTING -p udp --dport 22 -j DNAT --to-destination 172.16.80.99:22允许转发流量
iptables -A FORWARD -p tcp -d 172.16.80.99 --dport 22 -j ACCEPT
iptables -A FORWARD -p udp -d 172.16.80.99 --dport 22 -j ACCEPTSNAT 规则(内网返回数据)
iptables -t nat -A POSTROUTING -p tcp -d 172.16.80.99 --dport 22 -j SNAT --to-source 172.16.80.1
iptables -t nat -A POSTROUTING -p udp -d 172.16.80.99 --dport 22 -j SNAT --to-source 172.16.80.1保存规则
netfilter-persistent save端口范围转发DNAT 规则
# 外部端口5000-6000转发到172.16.80.99:5000:6000(tcp)
iptables -t nat -A PREROUTING -p tcp --dport 5000:6000 -j DNAT --to-destination 172.16.80.99:5000-6000
# 外部端口5000-6000转发到172.16.80.99:5000:6000(udp)
iptables -t nat -A PREROUTING -p udp --dport 5000:6000 -j DNAT --to-destination 172.16.80.99:5000-6000允许转发流量
iptables -A FORWARD -p tcp -d 172.16.80.99 --dport 5000:6000 -j ACCEPT
iptables -A FORWARD -p udp -d 172.16.80.99 --dport 5000:6000 -j ACCEPTSNAT 规则(内网返回数据)
iptables -t nat -A POSTROUTING -p tcp -d 172.16.80.99 --dport 5000:6000 -j SNAT --to-source 172.16.80.1
iptables -t nat -A POSTROUTING -p udp -d 172.16.80.99 --dport 5000:6000 -j SNAT --to-source 172.16.80.1保存规则
netfilter-persistent save
4 条评论
那外网如何访问lxc呢?比如我要在lxc装代理,设备端如何填写lxc的ip和端口呢?
需要做端口转发,文章已补充这类功能需求
你好,我跟着配置完了,防火墙全部关闭状态,lxc可以访问宿主机,但是无法访问局域网和外网,该怎么办啊,谢谢
需要做端口转发,文章已补充这类功能需求