Azure:一个 VM,在两个具有两个公共 IP 的 NIC 上提供两个服务

问题描述

设置

我正在设置 Azure VM(运行 Debian 10 的标准 E2as_v4)来提供多种服务。我想为每个服务使用单独的公共 IP 地址。为了测试我是否可以做到这一点,我设置了以下内容

vm1
 - nic1
  - vnet1,subnet1
  - ipconfig1: 10.0.1.1 <-> p.0.0.1
  - nsg1
    - allow: ssh (22)
 - nic2
  - vnet1,subnet2
  - ipconfig2: 10.0.2.1 <-> p.0.0.2
  - nsg2
    - allow: http (80)

vnet1
 - subnet1: 10.0.1.0/24
 - subnet2: 10.0.2.0/24
 - address space: [10.0.1.0/24,10.0.2.0/24]

其中 10.x.x.x IP 是私有的,而 p.x.x.x IP 是公共的。

nic1(网络接口)及其附带的 nsg1(网络安全组)是在我创建 VM 时自动创建的;否则它们与 nic2nsg2 对称(除了 nsg2 允许 HTTP 而不是 SSH)。此外,两个 NIC 在 VM 上都可以正常注册

问题

我可以通过 nic1 (p.0.0.1) 上的公共 IP 连接到 SSH。但是,我无法通过 nic2 (p.0.0.2) 上的公共 IP 连接到 HTTP。

我尝试过的事情

侦听 0.0.0.0。 为了检查我的服务器是否有问题,我让 HTTP 服务器侦听 0.0.0.0。然后我在 nsg1 上允许 HTTP,并在 nic1添加一个辅助 IP 配置和另一个公共 IP(静态 10.0.1.101 <-> p.0.0.3)。我在 VM 的配置中手动添加了静态私有 IP 地址(/run/network/interfaces.d/eth0;可能不是要编辑的正确文件,但 IP 已正确注册)。我现在可以通过与 nic1p.0.0.1p.0.0.3)关联的两个公共 IP 进行连接,但仍然无法通过 nic2p.0.0.2)进行连接。 这意味着我成功地为 VM 上的两个不同服务设置了两个公共 IP,但它们共享同一个 NIC。

配置负载平衡器。我还尝试使用负载平衡器实现相同的设置。在本例中,我创建了一个负载均衡器,其中包含两个后端池 - backend-pool1 用于 nic1backend-pool2 用于 nic2。我将 SSH 流量转移到 backend-pool1,将 HTTP 流量转移到 backend-pool2。结果与上述类似(SSH 连接成功,HTTP 失败,除非我使用 backend-pool1 而不是 backend-pool2)。我还尝试了直接入站 NAT 规则 - 效果相同。

检查通过子网的通信是否正常。最后,我在 subnet2 上创建了一个 VM。无论 NSG 配置如何,我都可以使用私有 IP (10.0.2.1) 与服务通信(我尝试了 NSG 上不允许的端口,但它通过了)。但是,当我使用公共 IP (p.0.0.2) 时它不起作用。

问题

我错过了什么?有没有我没有考虑的设置?无法通过在附加 NIC 上配置的公共 IP 地址连接到我的 VM 的原因是什么?

相关问题

注意:如果信息不够,我可以尝试提供命令行来重新创建设置。我正在运行的 HTTP 服务器是:

sudo docker run -it --rm -p 10.0.2.1:80:80 Nginx

然后我替换为在 0.0.0.0 上收听后续测试。

这是我用于测试的最终拓扑。

Topology I used for testing,described above

解决方法

要允许辅助接口(具有公共 IP)访问互联网或从互联网访问,我们不需要创建负载平衡器。相反,我们可以使用 iproute 来维护多个路由表。阅读http://www.rjsystems.nl/en/2100-adv-routing.phpthis SO answer了解更多详情。

经过我的验证,您可以添加以下配置,它在 Linux (ubuntu 18.04) VM 上运行。

  1. 在 Debian GNU/Linux 系统上激活 Linux 高级路由,安装 iproute 包:

    apt-get install iproute

  2. 配置两条默认路由

    echo 2 cheapskate >> /etc/iproute2/rt_tables

  3. 将新的默认路由添加到表cheapskate,然后显示:

    ~# ip route add default via 10.0.2.1 dev eth1 table cheapskate

    ~# ip route show table cheapskate

    default via 10.0.2.1 dev eth1

  4. 当数据包的发件人模式为 10.0.2.4 时添加规则,在这种情况下,应使用优先级为 1000 的路由表 cheapskate

    ip rule add from 10.0.2.4 lookup cheapskate prio 1000

内核搜索从最低优先级编号开始的 ip 规则列表,处理每个路由表,直到数据包被成功路由。

做完这一切,你可以用下面的命令检查一下,你会看到附加到二级接口的公网IP地址。

curl --interface eth1 api.ipify.org?format=json -w "\n"

请注意,您有足够的权限执行上述所有步骤。

enter image description here