【发布时间】:2011-12-16 17:46:14
【问题描述】:
我有以下环境:2 台主机,每台都有 2 个相互连接的以太网接口(如下图所示):
+---------+ +---------+
| (1)+---------------+(2) |
| host1 | | host2 |
| | | |
| (3)+---------------+(4) |
+---------+ +---------+
我想编写客户端/服务器套接字工具,它将在 host1 上打开客户端和服务器套接字。 我希望客户端通过接口(1)发送 TCP 数据包,服务器在接口(3)上侦听,这些数据包将通过 host2。
通常,Linux 堆栈会通过本地 TCP/IP 堆栈路由此数据包,而不会将这些数据包发送到 host2。
我尝试对服务器和客户端使用 SO_BINDTODEVICE 选项,似乎服务器确实绑定到接口 (3) 并且没有监听本地主机流量。我已经检查了来自 host1 的客户端不能被接受,而来自 host2 的客户端可以。
不幸的是,客户端数据包没有通过接口 (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]。
【问题讨论】:
-
只是为了理解您希望您的消息路径为 (1) --> (2) --> (4) --> (3) ?
-
您当然不需要为此定制 TCP 堆栈。不确定它是否是最好的方法,但您可以在 host2 上进行一些网络地址转换,将一些唯一的 IP 地址映射到接口 (3) 的地址,并确保从 host2 到 (3) 的数据包通过 (4 )。 Host1 然后会连接到那个唯一的 IP 地址。
-
如果一个套接字在另一台机器上从 (1) 连接到 (2),而另一个套接字在第一台机器上连接 (4) 到 (3),为什么 Linux TCP 堆栈会跳过通过网络? TCP 堆栈如何可能知道这种不寻常的拓扑结构以及它如何可能知道您的意图?
-
这样想:你想让你的妻子(在隔壁房间)知道晚饭准备好了,但她生你的气,不和你说话。所以你决定给你妈妈打电话,让她告诉她的邻居给你的妻子打电话。你拨你妈妈的号码。现在... 你认为哪个电话会响?您认为电话公司会让您妻子的电话响铃的假设是否合理?
-
让我们添加 IP 地址以进行澄清。假设接口 (1) 的 IP 地址为 192.168.1.1,接口 (3) 的 IP 地址为 192.168.10.1。当我打开套接字并想连接 192.168.10.1 时,内核会知道它是 host1 上其他接口的本地地址。如果 Linux 内核是电话公司,它只知道我想给我的妻子打电话。关键是如何强迫它打电话给我妈妈,先打电话给邻居而不是直接打电话。
标签: c linux sockets routing network-programming