2013-05-15 84 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規則...添加這些規則使竅門。

所以我總是需要設置iptables規則來使用netfilter庫來獲取數據包?

2

libnetfilter_queue就像它被命名的過濾器一樣。這意味着,它會根據創建和打開隊列時所提供的設置過濾出流量。

如果不通過這個過濾器發送任何數據,過濾無關的努力。通過此過濾器需要多少(什麼樣的)流量,您必須在iptable中設置。

Iptable可用作防火牆進入,通過取出您的系統。 Libnetfilter_queue允許您控制如何處理過濾的流量。

希望這有助於你一些。