Detectar e responder ao ping no espaço do usuário

4

Existe uma maneira de fazer um sistema linux reagir ou fazer alguma coisa quando pingado de outro dispositivo, além de apenas enviar uma resposta (ou não)?

    
por vicco 27.04.2015 / 13:15

2 respostas

5

Você pode usar o netfilter do Linux para interceptar pings recebidos e enviá-los para o userspace. Isso fará isso:

iptables -I INPUT -p icmp --icmp-type echo-request -j NFLOG

Você pode adicionar qualquer tipo de critério do iptables como -s (fonte) para interceptar apenas alguns pings e não outros.

Observe que isso não cancela a manipulação do kernel do ping original. Envia apenas uma cópia para o userspace. Se você planeja responder ao ping do userspace, então você irá querer evitar que o kernel também o manipule para que não haja 2 respostas. Para implementar isso, basta seguir o acima com outra regra iptables para soltar o original:

iptables -I INPUT -p icmp --icmp-type echo-request -j DROP

Para receber o ping do userspace, você precisa escrever algum código em C. A biblioteca libnetfilter_log é o que você precisa. Aqui está um exemplo de código que eu escrevi alguns anos atrás e que faz exatamente isso:

#include <libnetfilter_log/libnetfilter_log.h>
[...]

    struct nflog_handle *h;
    struct nflog_g_handle *qh;
    ssize_t rv;
    char buf[4096];

    h = nflog_open();
    if (!h) {
            fprintf(stderr, "error during nflog_open()\n");
            return 1;
    }
    if (nflog_unbind_pf(h, AF_INET) < 0) {
            fprintf(stderr, "error nflog_unbind_pf()\n");
            return 1;
    }
    if (nflog_bind_pf(h, AF_INET) < 0) {
            fprintf(stderr, "error during nflog_bind_pf()\n");
            return 1;
    }
    qh = nflog_bind_group(h, 0);
    if (!qh) {
            fprintf(stderr, "no handle for group 0\n");
            return 1;
    }

    if (nflog_set_mode(qh, NFULNL_COPY_PACKET, 0xffff) < 0) {
            fprintf(stderr, "can't set packet copy mode\n");
            return 1;
    }

    nflog_callback_register(qh, &callback, NULL);

    fd = nflog_fd(h);

    while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
            nflog_handle_packet(h, buf, rv);
    }

callback é uma função que é chamada para cada pacote de entrada. É definido como algo assim:

static int
callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *ldata, void *data)
{
    payload_len = nflog_get_payload(ldata, (char **)(&ip));
    ....
    /* now "ip" points to the packet's IP header */
    /* ...do something with it... */
    ....
}
    
por 29.04.2015 / 05:09
0

A maneira simples que eu usaria é farejar o tráfego ICMP por qualquer utilitário (wireshark, tcpdump, iptables etc.). Por exemplo, você pode usar a seguinte abordagem: link

    
por 27.04.2015 / 13:34