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

查看:792
本文介绍了使用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天全站免登陆