通过反向 ssh 隧道代理基于 QEMU 的虚拟机中的连接

通过反向 ssh 隧道代理基于 QEMU 的虚拟机中的连接

我有以下设置:

  1. QEMU 虚拟机(VM1)运行在服务器(服务器 a)上,与其共享专用网络,并使用服务器的互联网连接访问互联网。
  2. 可通过互联网轻松访问的服务器(服务器 a)。
  3. 位于私有网络中的私有服务器(服务器 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

  1. 在两个系统上安装该wireguard-tools软件包。这将为您提供和wg命令wg-quick

  2. 在服务器 A 和服务器 B 上,生成 wireguard 的公钥和私钥:

    mkdir -p /etc/wireguard
    cd /etc/wireguard
    wg genkey > privatekey
    wg pubkey < privatekey > publickey
    
  3. 在服务器 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 网络”。它可以是任何你想要的,只要它不与现有网络冲突即可。

  4. 在服务器 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)。

  5. 在服务器A和服务器B上,启用ip转发:

    sysctl -w net.ipv4.ip_forward=1
    
  6. 在两个系统上,调出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 私有网络上具有适当路由的任何设备(或者如果我们已将路由添加到默认网关,则可以到达任何设备)。

相关内容