Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux中如何避免通过本地堆栈进行路由_C_Linux_Sockets_Routing_Network Programming - Fatal编程技术网

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

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),并且没有侦听本地主机流量。我已经检查过,无法接受

我有以下环境: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编写我的应用程序

添加更多细节和澄清:

  • 当然,这两对(1)-(2)和(3)-(4)都是不同的子网
  • 我想要达到的是(1)-->(2)-->(4)-->(3)
  • host2是blackbox,因此我无法在那里安装任何数据包转发器(将打开接口(2)上的侦听套接字并将其转发到(3)到(4))-这正是我想要避免的
  • 主要问题似乎是在当地交货。当我打开host1上的socket并想要连接到socket时,即监听同一主机内核的其他地址时,只使用本地堆栈来传递数据包。请参见下面的netfilter图:

     +---------+               +---------+                     
     |      (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发送数据包。即使路由设置为发送所有数据包