我有以下环境:2 台主机,每台主机都有 2 个相互连接的以太网接口(如下图所示):
+---------+ +---------+
| (1)+---------------+(2) |
| host1 | | host2 |
| | | |
| (3)+---------------+(4) |
+---------+ +---------+
我想编写客户端/服务器套接字工具,它将在 host1 上打开客户端和服务器套接字。
我希望客户端通过接口(1)发送TCP数据包,服务器在接口(3)上侦听,该数据包将通过host2。
通常,Linux 堆栈会通过本地 TCP/IP 堆栈路由此数据包,而不将其发送到 host2。
我尝试过使用SO_BINDTODEVICE服务器和客户端的选项,似乎服务器确实绑定到接口(3)并且没有监听本地主机流量。我检查过来自主机 1 的客户端无法被接受,而来自主机 2 的客户端则被接受。
不幸的是,客户端数据包不会通过接口 (1) 发送到接口 (2)(即使接口 (1) 上的 tcpdump 也看不到数据包)。
当然路由是正确的(我可以从(1)ping(2),从(1)ping(4),从(3)ping(4)等等)。
我的问题是,这是否可以在不使用自定义 TCP/IP 堆栈的情况下实现?
也许我应该尝试将目标IP地址(来自客户端)更改为来自外部网络(然后将使用默认网关从接口(1)-接口(2)发送),然后在后路由中再次将它们更改为原始地址?这样的解决方案可行吗?
我正在 Debian 下用 C 语言编写我的应用程序。
添加更多细节和说明:
- 当然, (1)--(2) 和 (3)--(4) 两对是不同的子网
- 我想要实现的是(1)-->(2)-->(4)-->(3)
- host2 是黑匣子,所以我无法在那里安装任何数据包转发器(它将在接口 (2) 上打开侦听套接字并将其转发到 (3) 到 (4)) - 这正是我想要避免的
主要问题似乎是本地交付。当我在 host1 上打开套接字并想要连接到套接字时,即侦听同一主机内核的其他地址,仅使用本地堆栈来传递数据包。参见下面的netfilter图:
--->[1]--->[ROUTE]--->[3]--->[4]--->
| ^
| |
| [ROUTE]
v |
[2] [5]
| ^
| |
v |
数据包正在通过 [5] NF_IP_LOCAL_OUT 和 [2] NF_IP_LOCAL_IN,而我想强制它们通过 [4]。