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

2023-12-26

我有以下环境: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. 当然, (1)--(2) 和 (3)--(4) 两对是不同的子网
  2. 我想要实现的是(1)-->(2)-->(4)-->(3)
  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]。


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

Linux 有多个路由表。桌子local包含内核为添加到主机的每个 IP 地址自动添加的一些路由。你可以看到它们ip route show table local。路线标记为local表示经过Loopback接口的本地路由。您可以删除该路线并添加普通路线unicast替换它的路线:

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_过滤器在接口上:

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

再说一遍,如果这不起作用,您可能可以使用 L2 NAT 设置一些东西,使用ebtables.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Linux 中避免通过本地堆栈进行路由 的相关文章

  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • PHP 日志文件颜色

    我正在编写一个 PHP 日志文件类 但我想为写入文件的行添加颜色 我遇到的问题是颜色也会改变终端的颜色 我想要实现的是仅更改写入日志文件的行的颜色 class logClass extends Singleton private funct
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • php56 - CentOS - Remi 仓库

    我刚刚在测试盒上安装了 php 5 6 正常的 cli php 解释器似乎不存在 gt php v bash php command not found gt php56 v PHP 5 6 13 cli built Sep 3 2015
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐