Pacotes de pré-processamento enviados para / de interface

5

É de alguma forma possível interceptar dados de pacote antes que ele atinja uma interface, e logo após ser recebido? Por exemplo. pré-processar e enviar de volta a caminho?

Eu queria criar uma solução personalizada, como esse ótimo programa chamado vtun . Cria um dispositivo virtual que age como uma interface. Isso permite que ele faça todo tipo de coisa, como compactação de tráfego, criptografia, formatação, etc.

Eu queria saber se isso pode ser feito mais facilmente agora (o vtun é bem antigo ...). Meu sistema operacional de destino é o Ubuntu 14.04.

    
por er453r 10.07.2014 / 13:53

2 respostas

4

Sim, a estrutura do Netfilter do kernel do Linux é flexível o suficiente para tornar isso possível.

Não sei quais são suas expectativas, dizendo "solução personalizada" e "se isso puder ser feito mais facilmente agora" . Eu suponho que você está preparado para escrever código para fazer processamento de pacotes de baixo nível.

A ideia geral é a seguinte:

  1. Crie as regras iptables que passarão o tráfego da tabela desejada ( filter , nat , mangle ) para o espaço do usuário, por meio da QUEUE target.
  2. Você poderá acessar os pacotes que enviou para a fila usando a biblioteca libnetfilter_queue ou nfqueue-bindings (se você estiver trabalhando com Perl ou Python).
  3. Processe os pacotes da maneira que achar melhor e envie-os de volta.

Tenha em mente que você estará trabalhando com pacotes IP brutos, segmentos TCP ou datagramas UDP (dependendo do tipo de tráfego que deseja processar) e será de sua responsabilidade montar o tráfego corretamente, manter a correção da soma de verificação no nível do pacote e tudo o mais que a pilha TCP / IP do seu sistema operacional cuida magicamente dos bastidores.

Se você planeja trabalhar em Python, sugiro que use dpkt ou scapy para trabalhar com pacotes ou segmentos TCP. Isso tornará as coisas muito mais fáceis.

    
por 17.07.2014 / 13:11
1

Aqui está um exemplo de código usando sugestões de @dkaragasidis. Ele lê os dados do pacote e os transmite. Você pode modificar o pacote na função do manipulador.

Compile com: -lnetfilter_queue -lnfnetlink

Adicione uma regra com (exemplo): sudo iptables -A OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0

Remover regra com (exemplo): sudo iptables -D OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0

Teste com: nc -lu 4444 e nc -u YOUR_IP 4444

#include <netinet/in.h>
#include <linux/netfilter.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <stdio.h>

int handler(struct nfq_q_handle *myQueue, struct nfgenmsg *msg, struct nfq_data *pkt,   void *cbData) {
    int id = 0;
    struct nfqnl_msg_packet_hdr *header;

    if( header = nfq_get_msg_packet_hdr(pkt) )
        id = ntohl(header->packet_id);

    unsigned char *pktData;

    int len = nfq_get_payload(pkt, &pktData);

    printf("data[ %d ]:\n", len);

    int i;
    for (i = 0; i < len; i++)
        printf("%2d 0x%02x %3d %c\n", i, pktData[i], pktData[i], pktData[i]);

    printf("\n");

    return nfq_set_verdict(myQueue, id, NF_ACCEPT, len, pktData);
}

int main(int argc, char **argv) {
    struct nfq_handle *nfqHandle;
    struct nfq_q_handle *myQueue;
    struct nfnl_handle *netlinkHandle;

    int fd, res;
    char buf[4096];

    // queue connection
    if (!(nfqHandle = nfq_open())) {
        perror("Error in nfq_open()");
        return(-1);
    }

    // bind this handler
    if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
        perror("Error in nfq_bind_pf()");
        return(1);
    }

    // define a handler
    if (!(myQueue = nfq_create_queue(nfqHandle, 0, &handler, NULL))) {
        perror("Error in nfq_create_queue()");
        return(1);
    }

    // turn on packet copy mode
    if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
        perror("Could not set packet copy mode");
        return(1);
    }

    netlinkHandle = nfq_nfnlh(nfqHandle);
    fd = nfnl_fd(netlinkHandle);

    while ((res = recv(fd, buf, sizeof(buf), 0)) && res >= 0)
        nfq_handle_packet(nfqHandle, buf, res);

    nfq_destroy_queue(myQueue);
    nfq_close(nfqHandle);

    return 0;
}
    
por 17.07.2014 / 16:30