如何拦截在Linux上的IP数据包

我试图在Linux上实现这个目标(不确定是否可能,如果是这样的话):我需要编写一个程序来拦截接口上的所有IP数据,并将这个数据包传递给一组特定的用户空间程序。 通过拦截,我的意思是说,一个IP数据包被我的程序(可能是一个内核模块或一个特殊的用户空间程序)捕获,那么这个数据包不会再经过IP堆栈。 例如,假设操作系统正在运行很多进程(在内核空间或用户空间),A,B,C,D …等。如果在一个接口上接收到一个IP数据包,比如eth2 ,我只想要A,B看到这个包,而其他进程甚至都知道这个包的存在。 有人能把我带入正确的方向吗? 非常感谢!

我建议你重新检查是否真的有必要按照你描述的方式拦截数据包。 这听起来像你还没有完全理解,如上所述,网络是如何工作的。

首先,除非你的程序奇迹般地读取了原始的网络数据包,而不是使用标准套接字,否则它们不会收到相互指定的流量。 每个套接字都有一个与之关联的端口,只有一个进程可以绑定到同一个主机的同一个端口上(实际上套接字只不过是一对端口和一个主机地址)。

如果你真的在你的程序中读取原始网络数据包,这是必要的,你很可能不应该在同一个主机上运行它们。 相反,使用虚拟化将不允许在不同的虚拟主机中看到彼此的数据包的程序分开,从而将它们完全分开,而不是使用相当复杂的程序化解决方案。

如果一切都失败了,你可能要仔细看看libpcap ,它允许你捕获网络包,甚至同时从几个程序捕获。 虽然你必须以root身份运行,但无论如何,将网络接口置于混杂模式等等都是必要的。 下面是从网络上读取一些东西的一个简单的例子,你可以从libpcap主页找到更多的关联

#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pcap.h> /* IP header (from tcpdump examples) */ struct sniff_ip { u_char ip_vhl; /* version << 4 | header length >> 2 */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src, ip_dst; /* source and dest address */ }; /* callback function for pcap_loop */ void cllbck(u_char * args, const struct pcap_pkthdr *hdr, const u_char * pkt) { const struct sniff_ip *ip = (struct sniff_ip *) (pkt + 14); fprintf(stderr, "Sniffed a packet with length %d.\n", hdr->len); fprintf(stderr, "IP version %d.\n", ip->ip_vhl >> 4); } int main(int argc, char *argv[]) { char *dev; /* device name */ char errbuf[PCAP_ERRBUF_SIZE]; /* buffer for libpcap errmsgs */ pcap_t *cap; /* libpcap capture session */ char *filt = "host 127.0.0.1"; /* capture filter */ struct bpf_program fp; /* compiled filter */ struct pcap_pkthdr hdr; /* packet header from libpcap */ const u_char *pkt; /* packet from libpcap */ dev = strdup(argv[1]); if (dev == NULL) { fprintf(stderr, "Invalid device.\n"); return 2; } /* open the device for live capture */ cap = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (cap == NULL) { fprintf(stderr, "Opening device `%s´ failed: %s\n", dev, errbuf); return 2; } /* compile the capture filter */ if (pcap_compile(cap, &fp, filt, 0, PCAP_NETMASK_UNKNOWN) < 0) { fprintf(stderr, "Failed to parse filter `%s´: %s\n", filt, pcap_geterr(cap)); return 2; } /* set the filter active for this session */ if (pcap_setfilter(cap, &fp) == -1) { fprintf(stderr, "Couldn't install filter %s: %s\n", filt, pcap_geterr(cap)); return 2; } /* pcap close will loop until an error if 2nd arg is < 0 */ pcap_loop(cap, -1, cllbck, NULL); /* end session, pcap_loop has exited ie. an error has occurred */ pcap_close(cap); return 0; } /* end of file */