Как регистрировать каждое ответное сообщение ICMP - PullRequest
2 голосов
/ 06 ноября 2010

Есть вопрос, с которым я столкнулся. Как найти IP-адрес ответного сообщения ICMP в GNU / Linux?

Ответы [ 4 ]

4 голосов
/ 06 ноября 2010

Посмотрите на libpcap - это очень эффективная библиотека для анализа сети, которая позволяет вам захватывать именно тот тип пакетов, который вы укажете (возможно, отфильтрованный еще больше по адресу источника / назначения и т. Д.). Затем вы можете проанализировать пакет и извлечь IP-адреса источника и назначения. На связанной странице есть документация и несколько учебных пособий.

Обратите внимание, что вам необходимо выполнять захват на компьютере, через который проходит трафик (источник, пункт назначения или что-то среднее), как в современных сетях Ethernet (связанных с коммутаторами), вы обычно не видите весь сетевой трафик , См. Эти вопросы и ответы от Wireshark (который по сути является графическим интерфейсом для libpcap) для возможных обходных путей.

2 голосов
/ 06 ноября 2010

Вы можете попробовать протоколирование IPTables .

1 голос
/ 10 августа 2011

Это простой цикл (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;
}

Наслаждайся;)

0 голосов
/ 07 ноября 2010

Разумеется, вы можете открыть сокет с помощью

socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)

И записать адрес источника приходящих пакетов. Вам нужно будет знать структуру дейтаграммы ICMP, чтобы это работало. Смотри человек 7 сырой

...