使用 Linux,如何指定在哪个以太网接口上传输数据 [英] Using Linux, how to specify which ethernet interface data is transmitted on

查看:24
本文介绍了使用 Linux,如何指定在哪个以太网接口上传输数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个基于 Linux 的服务器系统,其中有两个网络接口,都在同一个子网上(现在,我们只说它们是 172.17.32.10 & 172.17.32.11).当我向网络上的主机发送数据时,我想指定数据在服务器上的哪个接口上传输.我需要能够在软件中从一个接口切换到另一个接口(或者甚至可能在两个接口上进行传输)(静态路由规则不适用于此应用程序).

I'm working on a Linux based server system in which there are two network interfaces, both on the same subnet (for now, lets just say they are 172.17.32.10 & 172.17.32.11). When I send data to a host on the network, I would like to specify which interface on my server the data is transmitted on. I need to be able to switch from one interface to the other (or maybe even transmit on both) in software (static routing rules won't work for this application).

我在 StackOverflow 中发现了一个相关问题,该问题建议使用 netlink 库动态修改路由.从直觉上看,这似乎应该可行,但我想知道是否还有其他选择可以实现相同的结果.

I found a related question in StackOverflow that suggested using the netlink library to modify routes on the fly. This intuitively seems like it should work, but I was wondering if there were any other options to accomplish this same result.

推荐答案

无意冒犯,但关于使用 bind() 的答案是完全错误的.bind() 将控制放置在数据包 IP 标头中的源 IP 地址.它不控制将使用哪个接口发送数据包:将参考内核的路由表来确定哪个接口到达特定目的地的成本最低.(*见注释)

No offense intended, but the answer about using bind() is quite wrong. bind() will control the source IP address placed within the packet IP header. It does not control which interface will be used to send the packet: the kernel's routing table will be consulted to determine which interface has the lowest cost to reach a particular destination. (*see note)

相反,您应该使用 SO_BINDTODEVICE sockopt.这有两件事:

  • 数据包总是从你指定的接口传出,不管内核路由表怎么说.
  • 只有到达指定接口的数据包才会被传递到套接字.到达其他接口的数据包不会.
  • Instead, you should use an SO_BINDTODEVICE sockopt. This does two things:

    • Packets will always egress from the interface you specified, regardless of what the kernel routing tables says.
    • Only packets arriving on the specified interface will be handed to the socket. Packets arriving on other interfaces will not.
    • 如果您要在多个接口之间切换,我建议为每个接口创建一个套接字.因为您也只会接收到您绑定的接口的数据包,所以您需要将所有这些套接字添加到您的 select()/poll()/无论你使用什么.

      If you have multiple interfaces you want to switch between, I'd suggest creating one socket per interface. Because you'll also only receive packets to the interface you've bound to, you'll need to add all of these sockets to your select()/poll()/whatever you use.

      #include <net/if.h>
      
      struct ifreq ifr;
      
      memset(&ifr, 0, sizeof(ifr));
      strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
      if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
                  (void *)&ifr, sizeof(ifr)) < 0) {
          perror("SO_BINDTODEVICE failed");
      }
      

      (*注)Bind() 到接口 IP 地址可能会导致混淆但仍然是正确的行为.例如,如果您bind() 到 eth1 的 IP 地址,但是路由表将数据包从 eth0 发送出去,那么一个数据包将出现在 eth0 线路上,但带有 eth1 接口的源 IP 地址.这很奇怪但被允许,尽管发送回 eth1 IP 地址的数据包将被路由回 eth1.您可以使用带有两个 iP 接口的 Linux 系统对此进行测试.我有一个,并对其进行了测试,bind() 不能有效地将数据包引导出物理接口.

      (*note) Bind() to an interface IP address can lead to confusing but nonetheless correct behavior. For example if you bind() to the IP address for eth1, but the routing table sends the packet out eth0, then a packet will appear on the eth0 wire but carrying the source IP address of the eth1 interface. This is weird but allowed, though packets sent back to the eth1 IP address would be routed back to eth1. You can test this using a Linux system with two iP interfaces. I have one, and did test it, and bind() is not effective in steering the packet out a physical interface.

      虽然技术上允许,但根据拓扑,这可能仍然不起作用.为了抑制攻击者使用伪造 IP 源地址的分布式拒绝服务攻击,许多路由器现在执行反向路径转发 (RPF) 检查.源 IP 地址位于错误"路径的数据包可能会被丢弃.

      Though technically allowed, depending on topology this may nonetheless not work. To dampen distributed denial of service attacks where the attackers use forged IP source addresses, many routers now perform Reverse Path Forwarding (RPF) checks. Packets with a source IP address on the "wrong" path may be dropped.

      这篇关于使用 Linux,如何指定在哪个以太网接口上传输数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆