Существует вопрос, на который я столкнулся, как мы можем найти ip-адрес сообщения ICMP-ответа в GNU/Linux?Как регистрировать каждое ответное сообщение ICMP
ответ
Посмотрите на libpcap - это очень эффективная библиотека для сетевого нюхания, которая позволяет вам точно фиксировать тип указанных вами пакетов (возможно, еще более фильтрованный по адресу источника/адресата и т. Д.). Затем вы можете проанализировать пакет и извлечь исходные и целевые IP-адреса. Связанная страница содержит документацию и несколько руководств.
Обратите внимание, что вы должны делать захват на компьютере, через который проходит трафик (источник, пункт назначения или что-то среднее), как в современных сетях Ethernet (связанных с коммутаторами), вы обычно не видите всю сеть трафик. See this Q&A от Wireshark (который по существу является графическим интерфейсом для libpcap) для возможных обходных решений.
Вы можете попробовать IPTables logging.
Можно, конечно, открыть сокет с
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
Срубы адрес источника пакетов, поступающих. Для этого вам нужно будет узнать структуру дейтаграммы ICMP. См человека 7 сырец
Это простой цикл (С 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;
}
Enjoy;)
я иногда нужно выяснить внешний IP-адрес встроенное устройство, например внутренний маршрутизатор за основным NAT. Обычно в качестве диагностических инструментов доступны только ping и traceroute. Теперь, когда этот код работает на удаленном сервере, я не могу сразу увидеть, какой IP-адрес является источником запроса ICMP. Спасибо большое! –