通过单独的网卡进行通信

通过单独的网卡进行通信

假设您有一台带有两块网卡(及其相关端口)的 Web 服务器,我们将它们称为 A 和 B。其理念是将一个端口(A)连接到互联网,将另一个端口(B)连接到某个独立的服务器网络以进行各种计算。这似乎比较常见,一个网络暴露在互联网上,用于实际发送和接收信息,另一个专用网络用于安全数据存储、管理控制等。

如何通过其中一个端口引导流量?我见过的唯一方式是代码方式,在我熟悉的所有语言中,您通过提供目标地址而不是原始地址来启动通信(例如 TCP)。如果您想与连接到一个端口或另一个端口(通过交换机)的特定机器对话,您将如何指定哪个端口?此外,如果您的机器通过 A 和 B 连接,但某些流量(可能是财务信息)需要通过 B 发送,而其他流量(例如 REST 数据)更适合通过 A 发送,该怎么办?

答案1

您可能会通过路由来实现这一点 - 在端口 A 上有一个子网,在端口 B 上有一个子网。然后操作系统将根据需要到达的服务通过正确的接口路由数据包。

答案2

目前尚不清楚您需要做什么以及为什么这样做。

如果你有 2 个网卡,你的机器将有 2 个网络连接和 2 个 IP 地址。当你通过某台机器的 IP 地址与其他机器通信时,你的服务器将根据本地路由策略(例如度量)选择传出接口。

示例 1:您已连接到 2 个网络:

  • 10.0.0.0,其中您的 IP 地址为 10.10.10.2
  • 192.168.1.0,其中您的 IP 地址为 192.168.1.2

现在,如果您想连接到 192.168.1.5,您的 Web 服务器很可能会选择第二个网络 (192.168.1.0),因为目的地可以从那里直接到达。

示例 2:,仅连接到 1 个网络:

  • 192.168.1.0,其中 IP 地址为 192.168.1.2,网关为 192.168.1.1

现在,如果您想连接到 10.10.10.2,您的 Web 服务器将只将数据包发送到默认网关(路由器),因为 10.10.10.2 不在您的网络(192.168.1.0)中。您的服务器不知道您的数据包在网关上会发生什么,也不知道网关(路由器)将如何将其传送到最终目的地。这只是网关(路由器)的麻烦。

对于第二个示例,服务器上的本地路由表看起来非常简单:

  • 192.168.1.* 直接连接
  • 0.0.0.0(其他所有)通过 192.168.1.1(您的网关)连接

结论:

从代码方面来看,如果您没有编写路由软件,您就无法选择传出接口。这是合理的,因为您的应用程序对路由协议、信息和规则一无所知。操作系统会根据路由表为您做出选择。路由表由操作系统根据您的网络连接状态、策略、规则、路由协议(如果您的服务器充当路由器)等创建和更新。

如果您确实需要通过 2 个不同的传出接口(取决于目标端口)与同一目标进行通信,则应在服务器上配置路由。Linux 示例:https://unix.stackexchange.com/questions/21093/output-traffic-on-different-interfaces-based-on-destination-port

答案3

这就是为什么您通常为不同的接口分配不同的主机名或不同的子域的原因。

假设您的主机名是 host001 和 host002,并且您的网络如下所示:

<-----internet --------+------------------------------+-------whatever else--->
                       |                              |
          157.38.5.6   |                  157.38.5.7  |
       +---------------+--+             +-------------+--+
       |  host001         |             |  host002       |
       +---------------+--+             +-------------+--+
          192.168.1.1  |                  192.168.1.2 |
                       +------------------------------+-------admin lan--->

157.38.5/24 是提供商分配给您的地址范围。两个主机都可以从互联网访问,并且您可以输入

host001.mycompany.com. IN A 157.38.5.6
host002.mycompany.com. IN A 157.38.5.7

进入您的官方 DNS 记录。

(请注意,应该有一个大的防火墙在您的互联网连接中,您可能不应该在防火墙之外的任何地方使用可公开路由的地址。但为了清楚起见,我想区分内部/外部)。

在你公司内部的 DNS 服务器中,其记录不会在互联网上发布,你需要输入

host001.dmz.company.com IN A 157.38.5.6
host002.dmz.company.com IN A 157.38.5.7
host001.mgm-net.company.com IN A 192.168.1.1
host002.mgm-net.company.com IN A 192.168.1.2

现在,每当您想要通过内部网络打开连接时,您都可以使用域内的主机名之一mgm-net。这将选择192.168.1地址,并且由于每个主机都有自己的地址,因此它将使用此网络接口。如果您想使用公共网络,请使用dmz域地址。

本地主机如何选择出接口

这就是路由表的用途。您的路由表将类似于以下内容:

destination     netmask             gateway      metric  interface
    0.0.0.0     0.0.0.0             157.38.5.1        1       eth0
 157.38.5.0     255.255.255.0                         0       eth0
 192.168.1.0    255.255.255.0                         0       eth1

该表的具体格式取决于您的操作系统、操作系统版本和用于显示该表的命令。此外,度量的绝对值可能不同。关键在于,从所有路由表条目中,内核将消除那些不符合目标地址的条目。如果您连接到 192.168.1.1,这将从列表中删除第二个条目 (157...)。此时默认路由 (0.0.0.0) 仍然符合条件。

然后,从所有剩余的可能性中选择具有最佳度量的那个。传统上,度量是到达目的地的跳数的同义词,因此最低度量是最好的。Windows 使用另一种方式,最高度量是最好的。无论如何,它是本地路由表中可能的路由和度量的组合,决定使用哪个本地接口。

如果您尝试从公司内部“网络较远的地方”进行连接,这一点尤其重要,因为您的 PC 和目标网络之间存在一个或多个路由器。

进一步改善的可能性

  • 您可能希望为主机提供不同的主机名,而不是不同的网络域。因此,您可能有一个 host001-ext.mycompany.com 和一个 host001-adm.mycompany.com 主机条目,这样您就不必在每次连接到特定主机时都“拼写”域。但是,通过弄乱不同 PC 上的域搜索顺序,您可以做一些技巧,让 PC A 首选 dmz.company.com,PC B 首选 mgm-net.company.com,如果在配置文件中只看到“host001”,则“自动选择”正确的网络。

  • 如果您同步最后的 IP 字节,您就不会感到困惑;外部的 157.38.5.6 应该与内部的 192.178.1.6 匹配,而不是 192.168.1.1。使用一致的最后字节,您可以创建一个脚本,从外部地址自动生成内部地址。

  • “危险”服务,如端口 22/ssh(在 unix 上)或 3389/远程桌面,可以/应该只绑定在 192.168.1.X 地址上。这样,如果您在内部网络上,您仍然可以通过 ssh 进入您的计算机,但您已经消除了来自外部的攻击媒介。

配置/编程

OS API 的功能之一是隐藏所有这些细节,因此除非您特别要求,否则您不会看到“数据来自哪个接口”的任何差异。

从 C 套接字 API 中,您可以使用getsockname()getpeername()函数来查找套接字的本地/远程地址。当您使用bind()设置侦听套接字时,其中一个参数是结构sockaddr,您必须在其中设置端口,并且您可能设置 IP 地址。通常,只需将其设置为 0.0.0.0,这意味着套接字将绑定到任何地址上的该端口。

在 Java 中,您可以使用Socket.getRemoteSocketAddress()Socket.getInetAddress来执行相同的操作,并且ServerSocket()有一个 3 参数版本可让您设置要监听的地址。

应用程序通常具有配置文件来执行相同操作。例如,sshd中的配置/etc/sshd/sshd_config有一个ListenAddress参数。如果您ListenAddress 192.168.1.1在此处说,那么在创建套接字时sshd会将其传递给192.168.1.1bind()并且您的操作系统不会接受发往的 ssh 数据包157.38.5.6

同样,apache 网络服务器有一个配置参数Listen,允许您设置要监听的端口和可选的地址。

通常,Windows 程序在某些配置点击中具有此功能。在 IIS 中,您可以使用端口和 IP 地址(其中地址可以是“*”表示所有地址)将服务绑定到服务器,这实际上起到了相同的作用。

答案4

从您的文字中,我不确定您是否真的在谈论两个真正独立的网络,即:

  1. 每个子网使用一个不同的交换机(或一个具有多个 VLAN 的管理型交换机);

  2. 每个交换机连接到服务器上的一个 NIC(网卡);

  3. 所有其他计算机只连接到一个交换机;

  4. 每个子网都有自己的寻址,例如,一个子网的地址为 192.168.0.*,另一个子网的地址为 192.1.68.1.*

如果确实如此,那么:

  1. 服务器上的 Linux 应该路由流量自动地从一个网络到另一个网络(如果没有,请使用 Google iptables,在两个 NICS 之间进行路由,并告诉我们您正在运行哪个 Linux)

  2. 服务器也是配置的好地方防火墙来限制您不想跨网络路由的流量。

  3. 流量流向的区分仅仅基于 IP 地址(参见上面的第 4 条)。

  4. 通常,您不会连接两个子网上的 PC,而是使用路由和防火墙(在单点,即服务器上)来微调跨子网传输的内容。

相关内容