C Linux中如何避免通过本地堆栈进行路由
我有以下环境:2台主机,每个主机有2个相互连接的以太网接口(如下图所示): 我想编写一个客户机/服务器套接字工具,它将在host1上同时打开客户机和服务器套接字。 我希望客户端通过接口(1)发送TCP数据包,服务器通过接口(3)侦听数据包,这些数据包将通过主机2发送 通常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编写我的应用程序 添加更多细节和澄清:C Linux中如何避免通过本地堆栈进行路由,c,linux,sockets,routing,network-programming,C,Linux,Sockets,Routing,Network Programming,我有以下环境:2台主机,每个主机有2个相互连接的以太网接口(如下图所示): 我想编写一个客户机/服务器套接字工具,它将在host1上同时打开客户机和服务器套接字。 我希望客户端通过接口(1)发送TCP数据包,服务器通过接口(3)侦听数据包,这些数据包将通过主机2发送 通常Linux堆栈将通过本地TCP/IP堆栈路由这些数据包,而不将它们发送到host2 我尝试对服务器和客户端使用SO_BINDTODEVICE选项,似乎服务器确实绑定到了接口(3),并且没有侦听本地主机流量。我已经检查过,无法接受
+---------+ +---------+
| (1)+---------------+(2) |
| host1 | | host2 |
| | | |
| (3)+---------------+(4) |
+---------+ +---------+
--->[1]--->[ROUTE]--->[3]--->[4]--->
| ^
| |
| [ROUTE]
v |
[2] [5]
| ^
| |
v |
数据包将通过[5]NF_IP_LOCAL_OUT和[2]NF_IP_LOCAL_IN,而我想强制它们通过[4]。您可以将不同的子网分配给(1)-(2)和(3)-(4)对,并让主机2将数据包从(2)转发到(3)。主机1上的客户端将连接到(2)的地址,因此本地网络堆栈将不知道目标服务器实际上也在本地运行。未测试(应该可以工作,但我可能遗漏了一些内容): Linux有几个路由表。表local包含内核为添加到主机的每个IP地址自动添加的一些路由。您可以使用
ip路由显示表local查看它们。标记为local的路由表示通过环回接口的本地路由。您可以删除该路由并添加一条普通的单播路由来替换它:
ip route del table local <ip> dev <NIC>
ip route add table local <ip> dev <NIC>
ip route flush cache
ip路由del表本地开发
ip路由添加表本地开发
ip路由刷新缓存
现在,您的第一个框将尝试向该IP地址发送IP数据报,就像它是远程地址一样,例如:它将使用ARP。因此,如果您的第二个盒子作为路由器或代理ARP,则必须答复ARP请求,或者您必须向ARP缓存添加关联:
arp -s <ip> <MAC>
arp-s
然后,您可能必须在界面上禁用rp\u过滤器:
echo 0 > /proc/sys/net/ipv4/conf/<NIC>/rp_filter
echo 0>/proc/sys/net/ipv4/conf//rp\u过滤器
再次提醒他们,如果这不起作用,您可能可以使用L2 NAT设置一些东西,使用ebtables执行非常类似的任务,我正在使用这样的脚本:
ip rule add from all lookup local # add one more local table lookup rule with high pref
ip rule del pref 0 # delete default local table lookup rule
ip rout add ${ip3} via ${ip2} src ${ip1} table 100 # add correct route to some table
ip rule add from all lookup 100 pref 1000 # add rule to lookup new table before local table
为了理解您希望消息路径为(1)-->(2)-->(4)-->(3)?您当然不需要为此定制TCP堆栈。不确定这是否是最好的方法,但您可以在主机2上执行一些网络地址转换,将一些唯一的IP地址映射到接口(3)的地址,并确保从主机2到(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内核是电话公司,它只知道我想给我妻子打电话。问题是如何强迫它打电话给我母亲,先打给邻居而不是直接打电话。实际上,(1)-(2)和(3)-(4)之间有不同的子网。要使用这个解决方案,我需要主机2上的一些转发器,它将侦听来自接口(2)的数据包,并通过接口(4)发送到接口(3)。Host2是blackbox,因此我无法在那里安装任何其他软件。无论如何,来自主机1的客户端将连接到监听接口(2)的服务器,这正是我想要避免的。您需要一些东西来反映从接口(1)发送到接口(3)的数据包-一台充当路由器的pc,一个带有nat的linksys junkbox设置,等等。发挥创意。问题是再次从主机1发送数据包。即使路由设置为发送所有数据包