我想编写一个透明代理,为系统设置默认路由 0.0.0.0,让所有数据包都通过我的 tun(或 windows 上的 wintun)设备。
通过这样做,我可以从 tun 设备读取 Ip 帧,并注入到我的 lwip 网络堆栈中进行处理。
为了学习如何做,我只是阅读了一些透明的工具,例如https://github.com/eycorsican/leaf/blob/d35e649e620ab9f49be927962849f31e81054230/leaf/src/proxy/tun/inbound.rs#L111
但是我陷入了路由循环。0.0.0.0 默认路由将路由所有经过 tun 的数据包,因此我可以读取所有系统数据包。
如果将数据包写入 tun 设备,然后内核做出路由决策,它会在那里看到默认路由并将其再次发送到我刚刚编写的 tun 设备。
我的问题是:
它会读取我刚刚写入的数据包吗?
如果不是,内核或 tun 设备如何避免这种情况?
作为https://superuser.com/a/1614808/944262答案是
要么使用网络命名空间(然后你可以有两个默认路由)
我当然知道用户网络堆栈可以解析从 tun 设备读取的 IP 帧,但是使用它的目的是什么?
答案1
我不太确定你的 LWIP 网络堆栈在这种情况下应该做什么,以及它与透明代理有何关系,因此部分答案:
从网络角度来看,您的 TUN 设备看起来就像另一个网络接口。因此,计算机会假设有一个 LAN 段连接到此设备,此段上还有其他计算机,等等。
现在 LWIP(我没用过)似乎是一个实现网络堆栈的库。假设您将 LWIP 的底层连接到 TUN 接口(如果您没有这样做,请澄清),这意味着使用 LWIP 的应用程序将是主计算机在 TUN 后面的 LAN 段上看到的“其他设备”。
这意味着在这种情况下,主计算机获得一个仅私有的 IP 地址,比如 TUN 上的 192.168.0.1,您的应用程序在 LWIP 上获得 192.168.0.2,并且它们可以通信。
现在,如果您考虑的应用程序是透明代理(再次强调,如果您没有这样做,请在您的问题中添加更多信息),并且该应用程序想要使用普通的 Linux 网络堆栈连接到世界其他地方,那么最简单的方法是使用网络命名空间:
设置一个新的命名空间(在 Google 上查找教程)。将计算机的默认网络接口(例如wlan0
)移到该命名空间中。在命名空间中添加到该网络接口的默认路由。在命名空间中运行应用程序 + LWIP 库,但将 TUN 接口移到主网络命名空间。在主网络命名空间中,通过 TUN 接口设置到应用程序 IP(192.168.0.2)的默认路由。
这意味着在主网络命名空间中运行的所有应用程序都使用主网络命名空间中的默认路由通过您的应用程序连接到外部,并且您的应用程序可以转发这些应用程序并通过“真实”接口wlan0
和第二个默认路由连接到外部。
无路由冲突,无返回数据包。