简体   繁体   English

我可以使用tun / tap和raw套接字制作“TCP数据包修改器”吗?

[英]Can I make a “TCP packet modifier” using tun/tap and raw sockets?

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. 我有一个谈论TCP的Linux应用程序,为了帮助分析和统计,我想修改它发出的一些TCP数据包中的数据。 I'd prefer to do this without hacking the Linux TCP stack. 我宁愿这样做而不破解Linux TCP堆栈。

The idea I have so far is to make a bridge which acts as a "TCP packet modifier". 到目前为止,我的想法是创建一个充当“TCP数据包修改器”的桥。 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. 我的想法是通过网桥一侧的tun / tap设备连接到应用程序,并通过网桥另一侧的原始套接字连接到网卡。

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. 我担心的是,当你打开一个原始套接字时,它仍然会将数据包发送到Linux的TCP堆栈,因此即使我愿意也无法修改它们并发送它们。 Is this correct? 这个对吗?

A pseudo-C-code sketch of the bridge looks like: 桥的伪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);
    }
}

Does this look possible, or are there other better ways of achieving the same thing? 这看起来有可能,还是有其他更好的方法来实现同样的目标? (TCP packet bridging and modification.) (TCP数据包桥接和修改。)

There were some apps I used years ago to do some TCP/IP packet manipulation for testing a firewall: fragoute and fragtest . 几年前我曾经使用过一些应用来做一些TCP / IP数据包操作来测试防火墙: fragoute和fragtest Looks like they haven't been touched in years, but they might give you some ideas of what to do in your code. 看起来他们多年没有碰过,但他们可能会给你一些关于你的代码做什么的想法。

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). 您可能需要考虑使用LD_PRELOAD库来挂钩它用于发送数据的函数(send(),write()等)。

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) 另一种选择是NAT到本地代理的出站连接,该本地代理可以读取数据,进行任何修改,并将其全部发送到真实目的地(有一些选项可以防止它再次被NAT并绕圈转)

You can use the click modular router . 您可以使用单击模块化路由器 It is a software router implemented entirely in C++. 它是一个完全用C ++实现的软件路由器。 Click allows you to capture packets as they pass through elements in the router where you can modify or collect statistics as needed. Click允许您在数据包通过路由器中的elements捕获数据包,您可以根据需要修改或收集统计信息。 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. 作为内核模块,您完全覆盖了linux路由机制,并且作为用户空间二进制文件,您只需从接口获得每个数据包的副本(如您在帖子中提到的那样)。 Packets can be directed through the Click graph by way of pcap filters and a variety of other mechanisms. 可以通过pcap过滤器和各种其他机制通过Click图引导数据包。

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. 如果您沿着路线前进,我认为这为您要做的事情提供了最直接的支持,因为您可以根据需要使用tun / tap,来自/来自主机或来自/来自设备捕获方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM