我有以下设置:
- QEMU 虚拟机(VM1)运行在服务器(服务器 a)上,与其共享专用网络,并使用服务器的互联网连接访问互联网。
- 可通过互联网轻松访问的服务器(服务器 a)。
- 位于私有网络中的私有服务器(服务器 b)。
我的目标是能够将 VM1 连接到服务器 b,以便 VM1 可以访问在服务器 b 上运行的任何服务(即 Web 服务器),另外,我还希望能够访问服务器 b 所在的私有网络。
我通过以下命令创建了从服务器 b 到服务器 a 的反向代理: ssh -v -o ServerAliveInterval = 15 -i“ keychain.pem” -N -R localhost:8888:localhost:443[电子邮件保护]
并且在 /etc/libvirt/hooks/qemu 文件中我添加了以下条目以将 VM1 的端口 443 转发到服务器 a 的端口 8888(反向 shh 隧道):
/sbin/iptables -D FORWARD -o virbr0 -p tcp -d $VM_IP --dport 443 -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport 8888 -j DNAT --to $VM_IP:443
其中 VM_IP 是 VM1 的内部 IP 地址。但是,当从 8888->443 转发时,服务器 b 似乎拒绝连接:
debug1:connect_next:主机 localhost([127.0.0.1]:443)正在进行中,fd=5
debug1:通道0:新[127.0.0.1]
debug1:确认转发的tcpip
debug1:通道 0:连接失败:连接被拒绝
connect_to 本地主机端口 443:失败。
debug1:通道 0:空闲:127.0.0.1,nchannels 1
我也尝试允许访问服务器 b 上的端口 443,但似乎没有帮助:sudo iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT。
我不确定主机为什么拒绝连接。有趣的是,如果我在服务器 b 的端口 8080 上运行一个非常简单的 python web 并反向 ssh 隧道它: ssh -v -o ServerAliveInterval = 15 -i“ keychain.pem” -N -R localhost:8888:localhost:8080[电子邮件保护]
我可以通过 curl -k https://localhost:8080 从服务器 a 访问 Web 服务器,也可以通过 curl https://SERVER_A_IP:8080/ 通过 GatewayPorts=yes 与 VM1 共享。我不明白为什么服务器 b 拒绝连接 - 有一种更简单的方法可以做到这一点(服务器 b 和 VM1 不容易从互联网访问)。
答案1
您可以创建一个Wireguard服务器 A 和服务器 B 之间的 VPN,用于将您的 VM 中的流量路由到服务器 B(以及服务器 B 的专用网络)。
假设
你有:
为了回答这个问题,我将假设以下地址:
在服务器 A 上
- 服务器A公网地址:192.168.122.28
- 服务器A虚拟机网络:172.16.10.0/24
- VM 1 地址:172.16.10.10
在服务器B上
- 私有网络:192.168.27.0/24
- 私网路由器地址:192.168.27.1
- 路由器公网地址:无(或未知)
- 服务器B私网地址:192.168.27.10
- 服务器 B
- 服务器B专用网络上的附加设备:
- X:192.168.27.21
- Y: 192.168.27.22
- Z: 192.168.27.23
您需要将这些地址替换为适合您环境的地址。
创建VPN
在两个系统上安装该
wireguard-tools
软件包。这将为您提供和wg
命令wg-quick
。在服务器 A 和服务器 B 上,生成 wireguard 的公钥和私钥:
mkdir -p /etc/wireguard cd /etc/wireguard wg genkey > privatekey wg pubkey < privatekey > publickey
在服务器 A 上创建 wireguard 配置:
cat > /etc/wireguard/wg0.conf <<EOF [Interface] Address = 10.200.10.10/24 ListenPort = 51820 PostUp = wg set %i private-key /etc/wireguard/privatekey [Peer] PublicKey = <contents of server B /etc/wireguard/publickey> AllowedIPs = 192.168.27.0/24,10.200.10.0/24 EOF
此处和下一步中的 10.200.10.0/24 地址是“vpn 网络”。它可以是任何你想要的,只要它不与现有网络冲突即可。
在服务器 B 上创建 wireguard 配置:
cat > /etc/wireguard/wg0.conf <<EOF [Interface] Address = 10.200.10.11/24 ListenPort = 51820 PostUp = wg set %i private-key /etc/wireguard/privatekey PostUp = until ping -c1 10.200.10.10; do sleep 1; done [Peer] PublicKey = <contents of server A /etc/wireguard/publickey> AllowedIPs = 172.16.10.0/24,10.200.10.0/24 Endpoint = 192.168.122.28:51820 EOF
此处的命令
PostUp = until ping ...
将导致wg-quick up wg0
阻塞,直到它能够成功 ping 通服务器 A 上的 VPN 地址。这是必要的,因为只有服务器 A 具有公共地址,因此我们需要从服务器 B 启动 VPN 连接(如果您尝试首先从服务器 A 连接到服务器 B,则 VPN 将无法启动,因为服务器 A 现在无法连接到服务器 B)。在服务器A和服务器B上,启用ip转发:
sysctl -w net.ipv4.ip_forward=1
在两个系统上,调出
wg0
:wg-quick up wg0
现在,我们可以从 VM1 (172.16.10.10) ping 服务器 B (192.167.27.10)。我们可以访问该服务器上托管的任何服务。
我们有使用权到服务器 B 上同一专用网络上的所有设备,但我们有一个路由问题:服务器 A(VM1 的默认网关)知道如何到达 192.168.27.0/24,但专用网络上的设备(服务器 B 除外)对 VPN 一无所知。因此,如果您从 VM1 尝试 ping 192.168.27.21 上的设备 X,您的数据包将正确到达设备 X,但 X 会尝试通过网络的默认路由器路由其回复 - 而默认路由器不知道如何处理它们,因此它们将被丢弃。您的解决方案是:
- 为专用网络上的每台设备提供一条到 172.16.10.0/24 的路由,或者
- 配置默认路由器,路由到 172.16.10.0/24
(两种情况下均通过服务器 B 路由,192.168.27.10)
那看起来会像这样:
ip route add 172.16.10.0/24 via 192.168.27.10
ip route add 10.200.10.0/24 via 192.168.27.10
有了适当的路由,从 VM1 我就可以到达服务器 B 以及服务器 B 私有网络上具有适当路由的任何设备(或者如果我们已将路由添加到默认网关,则可以到达任何设备)。