我有两台机器,A 和 B,运行 RHEL Linux。每台机器都有一个 1Gig 网卡,连接到我所说的“LAN”网络。每台机器都有一个 10Gig 网卡,连接到我所说的“BIGDATA”网络。这些网络彼此之间没有连接,除非通过这些机器。
我在 BIGDATA 网络上的 A 的 10Gig 接口上安装了光纤分路器。分路器通向捕获服务器,我想在那里记录所有进出的数据。最初都是 TCP,但将来也许使用一些 UDP 会更好。
出于开发和测试目的,我希望在 A 上运行 TCP 对话的双方,并使用这些 tap 捕获对话。使用此设置的开发人员不会在 B 上有帐户(至少这是我的目标)。
在我看来,超级用户应该可以在 B 上设置某种转发/中继,这样 A 上的客户端就可以通过分接光纤连接到 A 上的服务器。也就是说,流量在 LAN 网络上从 A 流向 B,然后在 BIGDATA 网络上返回 A。返回流量采用相同的路径返回。
到目前为止,我尝试使用 ssh 隧道。就像A:~ $ssh B -L 8051:<A's-BIGDATA-IP>:3434 -N
。这实际上非常适合捕获从客户端到服务器的流量。但不幸的是,服务器的响应找到了一种捷径,即只停留在本地,而从不出现在光纤上。查看 wireshark,数据包知道它们的目标 IP,并且不觉得有义务返回隧道。
我发现这答案,但我相信所有解决方案都要求两个接口位于同一网络上。也许我的解决方案的种子就在那里,但我找不到它们。
我想我可以用 C 从头开始编写这个程序,制作一个在 B 上运行的程序,以在 LAN 接口上建立 TCP 连接,在 BIGDATA 接口上启动另一个 TCP 连接,返回到 A,并转发回复。它只会复制 TCP 有效负载,这对于我的目的来说已经足够了。
是否有一个很酷的工具可以完成这种转发/中继?
有没有办法让 ssh 隧道按照我希望的方式运行以返回流量?
答案1
源和目标 NAT
您可以使用 DNAT 和 SNAT 的组合来转发流量,使用与你找到的答案只要您不介意破坏捕获的数据包即可。捕获的数据包的目标或源 IP 为 B,但听起来您已经对转发客户端进行了此操作。我猜 NAT 的优势在于速度,一切都保留在内核空间中。
此示例是 A 上的客户端连接到 A:BIGDATA:3434 上的服务器。NAT 规则将连接从 A 转发到 B,然后 B 转发回 A,同时将源设置为 B 以设置返回路径。可能看一下netfilter 指南如果您不熟悉 NAT 表。
确保 B 上已启用 IP 转发,方法是:
sysctl -w net.ipv4.ip_forward=1 echo 1 > /proc/sys/net/ipv4/ip_forward
流量在 LAN 网络上从 A 流向 B
# On A, forward local traffic for local service out LAN to B. iptables -t nat -A OUTPUT -p tcp -d A:BIGDATA --dport 3434 -j DNAT --to-destination B:LAN
然后返回BIGDATA网络的A。
# On B, forward the traffic to back to A over fibre iptables -t nat -A PREROUTING -p tcp -d B:LAN --dport 3434 -j DNAT --to-destination A:BIGDATA
回程流量沿原路返回
# On B, set the source address for this traffic to B fibre iptables -t nat -A POSTROUTING -d A:BIGDATA -p tcp --dport 3434 -j SNAT --to-source B:BIGDATA
NAT 连接跟踪负责最后映射回原始源 IP。
答案2
看一下EtherPuppet,可能与斯卡皮; EtherPuppet 被描述为
一个小的Linux程序,它将为以太网接口创建一个巫毒娃娃。
...
真实接口所见的所有内容都会被虚拟接口所见。发送到虚拟接口的所有内容都会被真实接口发出。
Scapy 的描述是
一个功能强大的交互式数据包处理程序。它能够伪造或解码多种协议的数据包、在线上发送数据包、捕获数据包、匹配请求和回复等等。
答案3
尽管这不是我希望找到的答案,但我最终还是找到了自己的答案。
我编写了一个在 B 上运行的程序,该程序将接受 LAN 接口上的连接并启动 BIGDATA 接口外的连接。该程序将 TCP 有效负载复制到新的传出消息中。它对返回的回复执行相同的操作。这不会保留标头信息(例如源 IP)——在我看来,这是一件好事,这样返回流量就不会走捷径。
它正在工作,尽管对于我认为如此基本的东西来说,这很痛苦。我会发布源代码,但它相当冗长,可能写得不是很好。
我将不接受任何答案,希望有人最终能偶然发现完美的解决方案!