代码之家  ›  专栏  ›  技术社区  ›  Amir Zadeh

如何记录每个ICMP回复消息

  •  2
  • Amir Zadeh  · 技术社区  · 15 年前

    我遇到了这个问题,如何在GNU/Linux中找到ICMP回复消息的IP地址?

    4 回复  |  直到 14 年前
        1
  •  4
  •   Piskvor left the building Rohit Kumar    15 年前

    观察 libpcap -它是一个非常有效的网络嗅探库,它可以让您准确地捕获指定的数据包类型(可能通过源/目标地址等进一步过滤)。然后,您可以解析数据包并提取源和目标IP地址。链接页面有文档和一些教程。

    请注意,您需要在一台计算机上进行捕获,流量通过该计算机(源、目的地或两者之间的任何内容),就像在现代以太网网络(通过交换机连接)中一样,您通常不会看到所有网络流量。 See this Q&A 从wireshark(本质上是一个GUI到libpcap)寻找可能的解决方法。

        2
  •  2
  •   jay.lee    15 年前

    你可以试试 IPTables logging .

        3
  •  1
  •   user799518    14 年前

    这是一个简单的循环(C Linux),用于拦截所有ICMP请求/回复:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    int main(int argc, char **argv)
    {
            int sock;
            int optval;
            int ret;
            int addrlen;
            struct sockaddr_in sIn;
            char *buffer;
            char *sAddr;
            char *dAddr;
            int proto;
            int type;
    
            buffer = malloc(sizeof(char) * 32);
            sAddr = malloc(sizeof(char) * 16);
            dAddr = malloc(sizeof(char) * 16);
            if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) {
                setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));
                sIn.sin_family = AF_INET;
                sIn.sin_addr.s_addr = INADDR_ANY;
                addrlen = sizeof(sIn);
                memset(buffer, 0, 32);
                while ((ret = recvfrom(sock, buffer, 31, 0, (struct sockaddr *)&sIn, &addrlen)) != -1) {
                        if (ret > 20) {
                                proto = (unsigned char)buffer[9];
                                type = (unsigned char)buffer[20];
                                if (proto == 1 && (type == 8 || type == 0)) {
                                        memset(sAddr, 0, 16);
                                        memset(dAddr, 0, 16);
                                        sprintf(sAddr, "%d.%d.%d.%d",
                                                (unsigned char)buffer[12],
                                                (unsigned char)buffer[13],
                                                (unsigned char)buffer[14],
                                                (unsigned char)buffer[15]);
                                        sprintf(dAddr, "%d.%d.%d.%d",
                                                (unsigned char)buffer[16],
                                                (unsigned char)buffer[17],
                                                (unsigned char)buffer[18],
                                                (unsigned char)buffer[19]);
                                        if (type == 8)
                                                fprintf(stdout, "-> ICMP REQUEST FROM %s TO %s\n", sAddr, dAddr);
                                        else
                                                fprintf(stdout, "<- ICMP REPLY FROM %s TO %s\n", sAddr, dAddr);
                                }
                        }
                        memset(buffer, 0, 32);
                }
                close(sock);
            }
            free(buffer);
            free(sAddr);
            free(dAddr);
            return 0;
    }
    

    享受;)

        4
  •  0
  •   MarkR    15 年前

    你当然可以用

    socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
    

    并记录到达数据包的源地址。您需要知道ICMP数据报的结构,这样才能工作。见男7生