linux - 如何在 linux 上拦截 IP 数据包

标签 linux ip intercept packets

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

最佳答案

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

首先,除非您的程序以某种神奇的方式设法读取原始网络数据包而不是使用标准套接字,否则它们无论如何都不会接收发往彼此的流量。每个套接字都有一个与之关联的端口,并且只有一个进程可以绑定(bind)到同一主机中的同一端口(套接字实际上只不过是一对端口和主机地址)。

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

如果一切都失败了,你可能想好好看看 libpcap它允许您捕获网络数据包,甚至可以同时从多个程序捕获。尽管您必须以 root 身份运行它们,但无论如何这对于能够将网络接口(interface)置于混杂模式等等都是必要的。这是一个简单的示例,用于从网络上读取一些内容,您可以从 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 */

关于linux - 如何在 linux 上拦截 IP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19884331/

相关文章:

linux - R 核心转储去哪里了?

iphone - 使用 TfL 数据的 iPhone 应用程序的 IP 地址是什么?

ssl - URL 如何转换为 TCP/IP 请求?

c++ - 直线x和y n-截点/C++

java - 拦截并解析 Logger 或控制台输出而不干扰它

linux - 当用户在 linux/unix 中键入 size 命令时,结果是什么意思?

linux - 良好的 POSIX 线程编程视频培训

c - 在 AT&T IA-32 Linux 汇编程序 (gas) 上拆分字符串

Java 应用程序与 Android 应用程序获取不同的 IP - 为什么?

java - 为什么 Apache Camel 拦截不起作用?