我可以制作一个“TCP 数据包修改器”吗?使用 tun/tap 和原始套接字?
我有一个与 TCP 通信的 Linux 应用程序,为了帮助分析和统计,我想修改它发送的一些 TCP 数据包中的数据。我更愿意在不破坏 Linux TCP 堆栈的情况下完成此操作。
到目前为止,我的想法是制作一个充当“TCP 数据包修改器”的网桥。我的想法是通过桥一侧的 tun/tap 设备连接到应用程序,并通过桥另一侧的原始套接字连接到网卡。
我担心的是,当你打开一个原始套接字时,它仍然会向 Linux 的 TCP 堆栈发送数据包,因此即使我愿意,我也无法修改它们并继续发送它们。这是正确的吗?
该桥的伪 C 代码草图如下所示:
tap_fd = open_tap_device("/dev/net/tun");
raw_fd = open_raw_socket();
for (;;) {
select(fds = [tap_fd, raw_fd]);
if (FD_ISSET(tap_fd, &fds)) {
read_packet(tap_fd);
modify_packet_if_needed();
write_packet(raw_fd);
}
if (FD_ISSET(raw_fd, &fds)) {
read_packet(raw_fd);
modify_packet_if_needed();
write_packet(tap_fd);
}
}
这看起来可能吗?或者是否有其他更好的方法来实现相同的目标? (TCP数据包桥接和修改。)
I have a Linux application that talks TCP, and to help with analysis and statistics, I'd like to modify the data in some of the TCP packets that it sends out. I'd prefer to do this without hacking the Linux TCP stack.
The idea I have so far is to make a bridge which acts as a "TCP packet modifier". My idea is to connect to the application via a tun/tap device on one side of the bridge, and to the network card via raw sockets on the other side of the bridge.
My concern is that when you open a raw socket it still sends packets up to Linux's TCP stack, and so I couldn't modify them and send them on even if I wanted to. Is this correct?
A pseudo-C-code sketch of the bridge looks like:
tap_fd = open_tap_device("/dev/net/tun");
raw_fd = open_raw_socket();
for (;;) {
select(fds = [tap_fd, raw_fd]);
if (FD_ISSET(tap_fd, &fds)) {
read_packet(tap_fd);
modify_packet_if_needed();
write_packet(raw_fd);
}
if (FD_ISSET(raw_fd, &fds)) {
read_packet(raw_fd);
modify_packet_if_needed();
write_packet(tap_fd);
}
}
Does this look possible, or are there other better ways of achieving the same thing? (TCP packet bridging and modification.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我几年前使用过一些应用程序来进行一些 TCP/IP 数据包操作来测试防火墙:fragoute 和 fragtest 。看起来它们已经很多年没有被触及了,但它们可能会给你一些关于在代码中做什么的想法。
There were some apps I used years ago to do some TCP/IP packet manipulation for testing a firewall: fragoute and fragtest. Looks like they haven't been touched in years, but they might give you some ideas of what to do in your code.
您可能需要考虑使用 LD_PRELOAD 库来挂钩它用于发送数据的函数(send()、write() 等)。
这根本不会涉及任何内核混乱。
另一种选择是将出站连接 NAT 到本地代理,该代理可以读取数据,进行任何修改,并将其全部发送到真正的目的地(使用一些选项来防止它再次被 NAT 并循环)
You might want to consider using a LD_PRELOAD library to hook the functions that it uses to send the data out (send(), write() etc).
That wouldn't involve any kernel messing-around at all.
Another option is to NAT the outbound connections to a local proxy which can read the data, make whatever modifications, and send it all out to the real destination (with some options to prevent it being NAT'd again and going round in circles)
您可以使用Click 模块化路由器。它是一个完全用C++实现的软件路由器。 Click 允许您在数据包通过路由器中的
元素
时捕获数据包,您可以根据需要修改或收集统计信息。作为内核模块,您完全覆盖 Linux 路由机制,并且作为用户态二进制文件,您只需从接口获取每个数据包的副本(正如您在帖子中提到的)。数据包可以通过 pcap 过滤器和各种其他机制引导通过点击图。如果您沿着bridge路线前进,我认为这为您想要做的事情提供了最直接的支持,因为您可以使用 tun/tap、到/从主机或到/从设备捕获方法根据您的要求。
You can use the click modular router. It is a software router implemented entirely in C++. Click allows you to capture packets as they pass through
elements
in the router where you can modify or collect statistics as needed. As a kernel module, you completely override the linux routing mechanism and as a userland binary you simply get a duplicate (as you mention in your post) of each packet from the interface. Packets can be directed through the Click graph by way of pcap filters and a variety of other mechanisms.If you are headed down the bridge route, I think this provides the most direct support for what you are looking to do as you can use tun/tap, to/from host or to/from device capture methods as you require.