在Linux内核模块中构建ICMP数据包

3

我正在尝试使用ICMP协议,并为Linux创建了一个内核模块来分析ICMP数据包(仅在ICMP代码字段为特殊数字时处理该数据包)。现在,为了测试这个模块,我必须创建一个ICMP数据包并将其发送到运行此分析模块的主机。事实上,如果我能在内核本身中实现它(作为一个模块),那就太好了。我正在寻找类似于内核中的数据包构造器的东西。我通过谷歌搜索发现了很多解释数据包生命周期的文章,而不是创建教程。用户空间的数据包构造器将是我的最后一招,特别是那些高度灵活的,例如我可以设置ICMP代码等。而且我不担心内核崩溃:-) !!!!! 欢迎任何数据包构造的想法。


检查netfilter模块的源代码,看它们如何生成针对被阻止端口的icmp响应。但正如Adel在下面所说的那样,我也会从外部用户空间使用原始套接字。 - ott--
3个回答

0

您可以尝试使用libcrafter在用户空间进行数据包构造。它非常易于使用!该库能够构造或解码大多数常见网络协议的数据包,将它们发送到网络中,捕获它们并匹配请求和响应。

例如,下面的代码可以构造并发送一个ICMP数据包:

string MyIP = GetMyIP("eth0");

/* Create an IP header */
IP ip_header;

/* Set the Source and Destination IP address */
ip_header.SetSourceIP(MyIP);                      
ip_header.SetDestinationIP("1.2.3.4"); 

/* Create an ICMP header */
ICMP icmp_header;

icmp_header.SetType(ICMP::EchoRequest);
icmp_header.SetIdentifier(RNG16());

/* Create a packet... */
Packet packet = ip_header / icmp_header;

packet.Send();

你为什么想在内核空间中构建一个ICMP数据包?只是为了好玩吗?:-p


0

Linux内核包含一个分组生成器工具pktgen,用于使用预配置的数据包测试网络。该模块的源代码位于net/core/pktgen.c。


0
先生,我强烈建议您不要使用内核模块来构建 ICMP 数据包。
您可以使用用户空间的原始套接字来制作 ICMP 数据包,甚至逐字节地构建 IP 报头。 因此,您可以使用它得到尽可能灵活的功能。
请看这个。
ip = (struct iphdr*) packet;
    icmp = (struct icmphdr*) (packet + sizeof(struct iphdr));

    /*  
     *  here the ip packet is set up except checksum
     */
    ip->ihl         = 5;
    ip->version         = 4;
    ip->tos         = 0;
    ip->tot_len         = sizeof(struct iphdr) + sizeof(struct icmphdr);
    ip->id          = htons(random());
    ip->ttl         = 255;
    ip->protocol        = IPPROTO_ICMP;
    ip->saddr           = inet_addr(src_addr);
    ip->daddr           = inet_addr(dst_addr);


    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
    {
    perror("socket");
    exit(EXIT_FAILURE);
    }

    /* 
     *  IP_HDRINCL must be set on the socket so that
     *  the kernel does not attempt to automatically add
     *  a default ip header to the packet
     */

    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));

    /*
     *  here the icmp packet is created
     *  also the ip checksum is generated
     */
    icmp->type          = ICMP_ECHO;
    icmp->code          = 0;
    icmp->un.echo.id        = 0;
    icmp->un.echo.sequence  = 0;
    icmp->checksum      = 0;
    icmp-> checksum     = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));

    ip->check           = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

如果这部分代码看起来足够灵活,那么可以了解一下原始套接字:D也许它们是您需求的最简单和最安全的答案。
请查看以下链接以获取更多信息:
http://courses.cs.vt.edu/~cs4254/fall04/slides/raw_6.pdf
http://www.cs.binghamton.edu/~steflik/cs455/rawip.txt
http://cboard.cprogramming.com/networking-device-communication/107801-linux-raw-socket-programming.html 这是一个非常好的主题,我认为非常有用。

原始套接字的前景似乎值得一试。我暂时会选择在试验基础上使用原始套接字,但如果读者在内核空间中看到了数据包构造的教程,请务必发布。显然,我会回来编写一个内核空间的数据包构造器。感谢Adel-带来的新奇刺激。 - Malice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接