我想做的事情在概念上非常简单,但我找不到任何有关如何执行此操作的信息或帮助。
基本上,我想将我的网络配置为使用源路由 (LSRR)。现在我知道这存在“安全问题”,因此它通常在公共互联网中被阻止,因此教程进入了死胡同。然而,我有一个完全专用的网络,并且由于某些工程原因需要这样做。 [基本上,我正在做一些实验,我想“模拟”逐跳路由协议]
因此,我想将流量从(具有 IP 地址的机器)A 发送到(具有 IP 地址的机器)X。但我希望流量通过中间节点 B、C、然后 D 遵循特定路线,即 A -> B -> C -> D -> X。这些都是私有 IP 地址,我已经配置了正确的 ip_forwarding 等。
Ping 实际上允许您使用 LSRR,因此我可以通过这些中间节点(使用我指定的路由)从 A ping 到 X,并且可以验证它是否确实发生在Wireshack 跟踪中,并且工作正常。
那么问题是我如何使用 iptables 或 tun 接口(或其他 - VPN?)等的某些功能来使用松散源路由重定向沿这条路由的所有正常流量?基本上,我想在 A 实现一些东西,这样当我尝试从 A 向 X 发送流量时,它会拦截这些 IP 数据包并向它们添加 LSRR,以便它通过指定的中间点转发。
如果有人可以帮助我,我将非常感激,因为我似乎不知道如何做到这一点?
非常感谢你,特里波尼
答案1
我开始对虚拟网络上的 ssh/scp 连接使用松散源和记录路由 (LSRR) 选项。它记录在 RFC 791(原始 IP 协议规范)中。这是我发现的。
我研究了使用 Linux eBPF 修改数据包标头(用于tc
附加 eBPF 程序来修改匹配的数据包),虽然我仍然认为这可行,但随着我深入研究,其他问题变得明显。
首先,我们用以下注释解释了check_ip_options
stock 程序中的例程:openssh
/*
* If IP options are supported, make sure there are none (log and
* return an error if any are found). Basically we are worried about
* source routing; it can be used to pretend you are somebody
* (ip-address) you are not. That itself may be "almost acceptable"
* under certain circumstances, but rhosts authentication is useless
* if source routing is accepted. Notice also that if we just dropped
* source routing here, the other side could use IP spoofing to do
* rest of the interaction and could still bypass security. So we
* exit here if we detect any IP options.
*/
因此,即使我们在数据包上设置了 LSRR 选项,我们也需要一个修改后的openssh
服务器才能与 ssh 或 scp 一起工作。这个改变看起来并不困难;只需注释掉check_ip_options
代码即可。我决定,既然无论如何我都必须修改服务器openssh
,我不妨修改openssh
客户端来设置 LSRR 选项,因为这看起来比使用 eBPF 更容易。我到目前为止:
--- sshconnect.c.dist 2022-08-20 22:13:41.119013377 -0400
+++ sshconnect.c 2022-08-20 22:14:13.180812775 -0400
@@ -380,6 +380,10 @@
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
+ char lssr_option[] = {131, 0, 4, 192, 168, 4, 171};
+ lssr_option[1] = sizeof(lssr_option);
+ setsockopt(sock, IPPROTO_IP, IP_OPTIONS, lssr_option, sizeof(lssr_option));
+
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL && options.bind_interface == NULL)
return sock;
这段代码有效。选项131是LSRR,192.168.4.171是我的第一跳地址。顺便说一句,Linux 网络代码似乎并没有直接将此选项复制到数据包中,而是将地址与数据包的目标地址交换。因此,如果您阅读 RFC 791,您可能希望在 中指定您的最终目的地lssr_option
,但您应该将中间地址放在那里并使用最终目的地作为您的 IP 目的地地址。
显然我不希望我的目标地址硬连接到 C 代码中,并且我应该检查返回值是否有错误,但它有效。我测试了一下。您需要配置路径上的所有 Linux 系统以接受源路由,如下所示:
echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/accept_source_route
我还通过注释掉对 的调用来修改 openssh 服务器check_ip_options
。
数据包通过了,但wireshark和tcpdump都报告了错误的TCP校验和,并且我无法关闭TCP校验和卸载:
baccala@samsung:~/src/openssh-8.2p1$ sudo ethtool -K wlp1s0 tx off
Cannot change tx-checksumming
Could not change any device features
那么,也许 WiFi 卡计算了 TCP 校验和,并且当 LSRR 选项存在时,它没有正确完成?这不难相信,因为 TCP 校验和包括目标地址,并且当 LSRR 存在时,最终目标地址位于 LSRR 选项中,而不是目标地址字段(仅包含第一跳)。
我说“够了”并研究了其他解决方案。
我将虚拟 Linux 路由器配置为接受我的 ssh 密钥,然后使用 openssh 的“跳转主机”选项通过我的网络建立隧道,如下所示:
ssh -J [email protected],[email protected] [email protected]
我并不是想说“你甚至不应该想这样做”的潮流,但我的经验是 ssh 跳转主机对于我的问题来说是一个更容易的解决方案。
答案2
答案非常简单:源路由创造了很多很多有趣的方式来造成严重破坏,并且在实践中几乎没有什么用处(也许用于诊断,每三个蓝色月亮一次)。所以大多数现代网络设备都忽略了这一点。