2013-05-15 2 views
2

libnetfilter_queue를 사용하는 방법을 배우려고합니다. 필자는 라이브러리와 함께 제공되는 예제를 컴파일했습니다.libnetfilter_queue를 사용하는 간단한 프로그램이 작동하지 않습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <netinet/in.h> 
#include <linux/types.h> 
#include <linux/netfilter.h>  /* for NF_ACCEPT */ 

#include <libnetfilter_queue/libnetfilter_queue.h> 

/* returns packet id */ 
static u_int32_t print_pkt (struct nfq_data *tb) 
{ 
    int id = 0; 
    struct nfqnl_msg_packet_hdr *ph; 
    struct nfqnl_msg_packet_hw *hwph; 
    u_int32_t mark,ifi; 
    int ret; 
    char *data; 

    ph = nfq_get_msg_packet_hdr(tb); 
    if (ph) { 
     id = ntohl(ph->packet_id); 
     printf("hw_protocol=0x%04x hook=%u id=%u ", 
      ntohs(ph->hw_protocol), ph->hook, id); 
    } 

    hwph = nfq_get_packet_hw(tb); 
    if (hwph) { 
     int i, hlen = ntohs(hwph->hw_addrlen); 

     printf("hw_src_addr="); 
     for (i = 0; i < hlen-1; i++) 
      printf("%02x:", hwph->hw_addr[i]); 
     printf("%02x ", hwph->hw_addr[hlen-1]); 
    } 

    mark = nfq_get_nfmark(tb); 
    if (mark) 
     printf("mark=%u ", mark); 

    ifi = nfq_get_indev(tb); 
    if (ifi) 
     printf("indev=%u ", ifi); 

    ifi = nfq_get_outdev(tb); 
    if (ifi) 
     printf("outdev=%u ", ifi); 
    ifi = nfq_get_physindev(tb); 
    if (ifi) 
     printf("physindev=%u ", ifi); 

    ifi = nfq_get_physoutdev(tb); 
    if (ifi) 
     printf("physoutdev=%u ", ifi); 

    ret = nfq_get_payload(tb, &data); 
    if (ret >= 0) 
     printf("payload_len=%d ", ret); 

    fputc('\n', stdout); 

    return id; 
} 


static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, 
      struct nfq_data *nfa, void *data) 
{ 
    u_int32_t id = print_pkt(nfa); 
    printf("entering callback\n"); 
    return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); 
} 

int main(int argc, char **argv) 
{ 
    struct nfq_handle *h; 
    struct nfq_q_handle *qh; 
    int fd; 
    int rv; 
    char buf[4096] __attribute__ ((aligned)); 

    printf("opening library handle\n"); 
    h = nfq_open(); 
    if (!h) { 
     fprintf(stderr, "error during nfq_open()\n"); 
     exit(1); 
    } 

    printf("unbinding existing nf_queue handler for AF_INET (if any)\n"); 
    if (nfq_unbind_pf(h, AF_INET) < 0) { 
     fprintf(stderr, "error during nfq_unbind_pf()\n"); 
     exit(1); 
    } 

    printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n"); 
    if (nfq_bind_pf(h, AF_INET) < 0) { 
     fprintf(stderr, "error during nfq_bind_pf()\n"); 
     exit(1); 
    } 

    printf("binding this socket to queue '0'\n"); 
    qh = nfq_create_queue(h, 1, &cb, NULL); 
    if (!qh) { 
     fprintf(stderr, "error during nfq_create_queue()\n"); 
     exit(1); 
    } 

    printf("setting copy_packet mode\n"); 
    if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { 
     fprintf(stderr, "can't set packet_copy mode\n"); 
     exit(1); 
    } 

    fd = nfq_fd(h); 

    while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) { 
     printf("pkt received\n"); 
     nfq_handle_packet(h, buf, rv); 
    } 

    printf("unbinding from queue 0\n"); 
    nfq_destroy_queue(qh); 

#ifdef INSANE 
    /* normally, applications SHOULD NOT issue this command, since 
    * it detaches other programs/sockets from AF_INET, too ! */ 
    printf("unbinding from AF_INET\n"); 
    nfq_unbind_pf(h, AF_INET); 
#endif 

    printf("closing library handle\n"); 
    nfq_close(h); 

    exit(0); 
} 

실행 파일을 실행해도 아무 것도받지 못합니다. 나는 또한 thread을 따라 트래픽을 생성하기 위해 netcat을 사용하려고 시도했지만 어떤 패킷도 보지 못했습니다. 아마 필터 대기열과 상호 작용할 수있는 것이 누락 되었습니까?

답변

3

예, 있습니다. 방화벽이 패킷을 통과시켜 패킷을 통과시키지 않으면 패킷이 전혀 발생하지 않고 패킷이 커널 공간을 떠나지 않을 것입니다. 그러나 사용자 공간에 패킷을 보내는 규칙을 설정하면 프로그래머가 작동합니다.

iptables -A INPUT -i eth0 -j NFQUEUE --queue-num 0 

이 줄은 --in-interface eth0이있는 INPUT에서 모든 패킷을 사용자 공간으로 보냅니다.

1

그 스레드를 읽으면 iptables 규칙을 추가하지 않았습니다 ... 이러한 규칙을 추가하면 트릭을 만들 수 있습니다.

그래서 항상 netfilter 라이브러리를 사용하여 패킷을 가져 오기 위해 iptables 규칙을 설정해야합니까?

2

libnetfilter_queue는 그대로 필터입니다. 즉, 대기열을 만들고 열 때 사용자가 지정한 설정에 따라 트래픽을 걸러냅니다.

이 필터를 통해 트래픽을 보내지 않으면 필터가 작동하지 않습니다. 이 필터를 통과하는 트래픽 양 (iptable)을 설정해야합니다.

iptable은 을 (를) 통해 또는 에서까지 시스템으로 작동합니다. Libnetfilter_queue를 사용하면 필터링 된 트래픽으로 수행 할 작업을 제어 할 수 있습니다.

희망이 있으면 도움이됩니다.

관련 문제