如何避免在Linux中通过本地堆栈进行路由

cod*_*ior 5 c sockets linux routing network-programming

我有以下环境:2个主机,每个主机有2个以太网接口相互连接(如下图所示):

 +---------+               +---------+                     
 |      (1)+---------------+(2)      |    
 |  host1  |               |  host2  |
 |         |               |         |
 |      (3)+---------------+(4)      |
 +---------+               +---------+
Run Code Online (Sandbox Code Playgroud)

我想编写客户端/服务器套接字工具,它将在host1上打开客户端和服务器套接字.我希望客户端通过接口(1)和服务器发送TCP数据包以侦听接口(3),数据包将通过host2.

通常,Linux堆栈将通过本地TCP/IP堆栈路由此数据包,而不将这些数据包发送到host2.

我试图为服务器和客户端使用SO_BINDTODEVICE选项,似乎服务器确实绑定到接口(3)并且没有监听localhost流量.我已经检查过来自host1的客户端无法接受,而来自host2的客户端则无法接受.

不幸的是,客户端数据包不会通过接口(1)发送到接口(2)(即使接口(1)上的tcpdump看不到数据包).当然路由是正确的(我可以ping(2)from(1),(4)from(1),(4)from(3),依此类推).

我的问题是,如果可以在不使用自定义TCP/IP堆栈的情况下实现这一点?

也许我应该尝试将目标IP地址(从客户端)更改为来自外部网络(然后将使用默认网关从接口(1) - 接口(2)),然后在postrouting中将这些更改为原始网络?这种解决方案是否可行?

我在Debian下用C编写我的应用程序.

添加更多细节和说明:

  1. 当然,对(1) - (2)和(3) - (4)都是不同的子网
  2. 我想要达到的是(1) - >(2) - >(4) - >(3)
  3. 主机2是黑盒子,所以我不能安装任何有分组转发器(将打开监听接口插座(2),并转发那些(3)至(4)) - 这是exactely我想避免什么

主要问题似乎是本地交付.当我在host1上打开socket并想要连接到套接字时,正在侦听同一主机内核的其他地址只是使用本地堆栈来传递数据包.请参见下面的netfilter图:

 --->[1]--->[ROUTE]--->[3]--->[4]--->
             |            ^
             |            |
             |         [ROUTE]
             v            |
            [2]          [5]
             |            ^
             |            |
             v            |
Run Code Online (Sandbox Code Playgroud)

数据包正在通过[5] NF_IP_LOCAL_OUT和[2] NF_IP_LOCAL_IN,而我想强制它们通过[4].

Nik*_*sov -1

您可以将不同的子网分配给 (1)-(2) 和 (3)-(4) 对,并让 host2 将数据包从 (2) 转发到 (3)。host1 上的客户端将连接到 (2) 的地址,因此本地网络堆栈不会知道目标服务器实际上也在本地运行。