2

There is this question i ran into, how can we find the ip address of the ICMP reply message in GNU/Linux?

Amir Zadeh
  • 3,481
  • 2
  • 26
  • 47

4 Answers4

4

Look into libpcap - it's a very efficient library for network sniffing, which lets you capture exactly the type of packets you specify (possibly filtered even further by source/destination address etc.). You can then parse the packet and extract the source and destination IP addresses. The linked page has documentation and several tutorials.

Note that you need to be doing the capture on a computer across which the traffic passes (source, destination, or anything in between) as in modern Ethernet networks (connected with switches), you normally don't see all network traffic. See this Q&A from Wireshark (which is essentially a GUI to libpcap) for possible workarounds.

Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
2

You can try IPTables logging.

jay.lee
  • 19,388
  • 8
  • 39
  • 38
1

This is a simple loop (C Linux) to intercept all ICMP REQUEST/REPLY:

#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 ;)

  • I sometimes need to figure out the external IP address of an embedded device e.g. a domestic router behind a major NAT. Usually only ping and traceroute are available as diagnostic tools. Now with this code running on a remote server, I can in no time see which IP address is the source of the ICMP request.Thanks a lot! – mr-euro Apr 25 '14 at 16:01
0

You can certainly open a socket with

socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)

And log the source address of packets arriving. You will need to know the structure of an ICMP datagram for this to work. See man 7 raw

MarkR
  • 62,604
  • 14
  • 116
  • 151