clinuxsocketsmoduleuserspace

Linux NFQUEUE handling issue


I am trying to write a userspace application that binds to an NFQUEUE socket to which a kernel module will forward incoming packets (by tagging them NF_QUEUE). This is accomplised by using an iptables rule like:

iptables -­A INPUT -j NFQUEUE --­­queue­-num 0

The iptables ACCEPT chain looks like this:

iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        
ACCEPT     all  --  anywhere             anywhere            state    RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere           
ACCEPT     all  --  anywhere             anywhere           
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited
NFQUEUE    all  --  anywhere             anywhere            NFQUEUE num 0

This is the code that polls the NFQUEUE socket (QNUM is 0):

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");
    return 1;
}   

/* Register a  callback function for our queue number */
qh = nfq_create_queue(h, QNUM, &cb_func, NULL);

if (!qh)
{   
    fprintf(stderr, "error during creating nf_queue\n");
    return 1;
}   

/* See if we have received a packet and send it to our cb func */
fd = nfq_fd(h);
if (fd < 0)
   return 1;

#if 1    
for (;;)
{
    if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
        nfq_handle_packet(h, buf, sizeof(buf)); /* send packet to callback */
        continue;
    }
}
#endif

The problem is that /proc/net/netfilter/nf_queue lists queue number 2 instead of number 0 as being used and thus my userspace program does not detect any incoming packet in the associated socket. Why is that?

cat /proc/net/netfilter/nf_queue
0 NONE
1 NONE
2 nf_queue
3 NONE
4 NONE
5 NONE
6 NONE
7 NONE
8 NONE
9 NONE
10 NONE
11 NONE
12 NONE

Solution

  • I figured it out. After all, I didn't even need a kernel module to do this, just the iptables rule. The problem was that the rule was not the first in the chain. Moving it first, with

    sudo iptables -I INPUT -j NFQUEUE --queue-num 0
    

    solved it.