加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

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

发布时间:2020-12-14 00:59:55 所属栏目:Linux 来源:网络整理
导读:我有以下环境:2个主机,每个主机有2个以太网接口相互连接(如下图所示): +---------+ +---------+ | (1)+---------------+(2) | | host1 | | host2 | | | | | | (3)+---------------+(4) | +---------+ +---------+ 我想编写客户端/服务器套接字工具,它将在h
我有以下环境:2个主机,每个主机有2个以太网接口相互连接(如下图所示):

+---------+               +---------+                     
 |      (1)+---------------+(2)      |    
 |  host1  |               |  host2  |
 |         |               |         |
 |      (3)+---------------+(4)      |
 +---------+               +---------+

我想编写客户端/服务器套接字工具,它将在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) – (2)和(3) – (4)都是不同的子网
>我想要实现的是(1) – >(2) – >(4) – >(3)
> host2是blackbox所以我无法在那里安装任何数据包转发器(将在接口(2)上打开侦听套接字并将其转发到(3)到(4)) – 这是我想要避免的

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

--->[1]--->[ROUTE]--->[3]--->[4]--->
             |            ^
             |            |
             |         [ROUTE]
             v            |
            [2]          [5]
             |            ^
             |            |
             v            |

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

解决方法

未经测试(应该工作,但我可能错过了一些东西):

Linux有几个路由表.表local包含内核为添加到主机的每个IP地址自动添加的一些路由.您可以使用ip route show table local查看它们.标记为本地的路由表示通过环回接口的本地路由.您可以删除该路由并添加正常的单播路由来替换它:

ip route del table local <ip> dev <NIC>
ip route add table local <ip> dev <NIC>
ip route flush cache

现在,您的第一个框将尝试将IP数据报发送到该IP地址,就好像它是一个远程地址,例如:它将使用ARP.因此,如果第二个框作为路由器或正在执行代理ARP,则必须回复ARP请求,否则您必须添加与ARP缓存的关联:

arp -s <ip> <MAC>

然后,您可能必须在接口上禁用rp_filter:

echo 0 > /proc/sys/net/ipv4/conf/<NIC>/rp_filter

再次,如果这不起作用,你可以使用ebtables设置L2 NAT的东西.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读