gpt4 book ai didi

Linux:如何强制使用特定的网络接口(interface)?

转载 作者:IT王子 更新时间:2023-10-29 00:20:46 26 4
gpt4 key购买 nike

这可以被认为是 this earlier SO question 的延续.

理想情况下,无论如何,我都希望将一个进程禁锢在只使用特定接口(interface)的状态下。它将建立 TCP 连接、发送 UDP 数据报和监听 UDP 广播。目前,我正在做的是:

  1. 确定要使用的接口(interface)的 IP。
  2. 创建 IP 策略规则以将来自接口(interface)的所有数据包路由到该 IP
  3. 创建另一个 IP 策略规则以将来自该 IP 的所有数据包路由到该接口(interface)
  4. 为每条规则设置默认路由表

现在,这主要有效,但客户端进程也必须愿意配合。也就是说,它需要绑定(bind)到它要使用的接口(interface)的特定IP,我想我还需要设置SO_BINDTODEVICE。 (但是,我一直在阅读有关 SO_BINDTODEVICE 在使用 TCP 或 UDP 时是否实际工作的相互矛盾的信息。)幸运的是,客户端应用程序是 Python,我可以扩展套接字类以透明地完成所有这些工作。但我不确定这是一个完整的解决方案,尤其是在接收广播方面。

我的问题是:

  1. SO_BINDTODEVICE 是否在此处执行我想要的操作?或者它只对原始套接字有效?有人评论说,“套接字上的 SO_BINDTODEVICE 不能保证套接字只会接收到达该物理接口(interface)的电线/天线的数据包。”如果这确实是真的,那么 SO_BINDTODEVICE 做了什么?

  2. 有没有办法让本地 IP 不必是唯一的?除了一个接口(interface)上的 DHCP 服务器可能会为其分配另一个接口(interface)正在使用的 IP,从而混淆路由表之外,这不会成为问题。

  3. 如何只接收来自特定接口(interface)的广播?绑定(bind)到特定 IP 似乎使其忽略广播,这是有道理的,但并不是我想要的。

我在 Ubuntu 8.04 和 Linux 内核 2.6.26 上运行。能够通过两个不同的接口(interface)同时访问两个不同网络上的同一个子网是一个不可协商的要求,因此它(大部分)不受“不要那样做”的影响。 :)

最佳答案

至于我的一般问题,似乎有几种方法可以做到:

  • 复杂的方式涉及到路由表的变化和各个进程之间的协作。这就是我上面描述的方式。它的一个优点是它可以在用户空间工作。我在上面做了一些额外的注释,并在下面回答了我的具体问题。

  • 如果设置了 SO_BINDTODEVICE,请编写一个完全忽略路由表的自定义内核模型。但是,客户端进程仍然需要调用 setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)。此选项绝对不适合胆小的人。

  • 虚拟化流程。这可能不适合很多人,并且会带来一系列令人头疼的问题,主要是配置方面的问题。但值得一提。

选项 1 和 2 要求流程选择加入以按照我们希望的方式工作。这可以通过创建一个动态库来部分缓解,该动态库劫持 socket() 调用以创建套接字,然后在返回描述符之前立即将其绑定(bind)到设备。对此有更详细的描述 here .

经过一些研究和大量谷歌搜索后,我可以得出一些关于 Linux 内核 2.6.26 行为方式的结论。请注意,这些可能都是特定于实现的行为,甚至可能是特定于内核的。在决定根据我的单点数据实现功能之前测试您自己的平台。

  1. SO_BINDTODEVICE 确实做到了它所说的,至少对于 UDP 是这样。

  2. 每个接口(interface)的唯一 IP 似乎是必要的,因为我们正在使用路由表。自定义内核模块可以绕过此限制。

  3. 要在特定接口(interface)上接收广播,首先使用 SO_BINDTODEVICE 绑定(bind)到设备,然后使用通常的 bind() 调用绑定(bind)到广播地址。设备绑定(bind)需要先完成。然后,套接字将只接收到达该接口(interface)的广播。

我首先创建了一个套接字来测试它。然后我使用 setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev) 将它绑定(bind)到特定接口(interface)。最后,我将它绑定(bind)到广播地址。我从另一台计算机发送了一个广播,该广播将通过非绑定(bind)接口(interface)接收。设备绑定(bind)套接字没有收到这个广播,这是有道理的。删除 setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev) 调用,广播将被接收。

还应该提到的是,您也可以在这里使用 setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)。请注意,SO_REUSEADDR 的语义随广播地址而变化。具体来说,如果两个套接字都设置了 SO_REUSEADDR,则在同一台机器上将两个套接字绑定(bind)到广播地址和相同端口是合法的。

更新:SO_BINDTODEVICE 广播似乎充满了危险,特别是广播帧的接收。我正在观察一个接口(interface)上接收到的广播帧,但同时在另一个接口(interface)上消失了。看起来它们受本地路由表的影响,但不受 IP 策略规则的影响。但是,我对此不是 100% 确定,如果您希望继续进行,我只是将其作为调查点提及。这就是说:使用风险自负。为了节省时间,我在接口(interface)上打开了一个原始套接字并自己解析了以太网和 IP header 。

关于Linux:如何强制使用特定的网络接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/563235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com