Is it possible to access ip fragments with libnetf

2019-08-12 04:06发布

问题:

I am using libnetfilter_queue in C to capture packets. I am setting an iptable rule to queue the incoming packets that would later be processed by the userspace implementation like this: iptables -A INPUT -j NFQUEUE --queue-num 0. I used nfqnl_test example as a framework to implement the capture. Everything works as expected. However, I noticed that it is impossible to inspect the queue on the level of ip fragments. That is, if a packet is coming in fragments it is first reassembled before being put into the queue. But I would like to work with fragments. So is there a way to enforce that kind of behavior? What I want to have is a queue where I could observe raw incoming packets (both fragmented and unfragmented) so I would be able to act on them accordingly.

I read that the reassembly indeed happens before. On the other hand, with iptables there is -f flag available so there should be a "fragmentation granularity" which I am looking for. I also tried adjusting iptable rules (e.g. iptables -t raw -D PREROUTING -i eth0 -j NFQUEUE --queue-num 0), but the result is still the same. I can only observe already reassembled packet which I definitely know that arrives in fragments.

Any help is really appreciated.

回答1:

So I have found a solution to the problem and I am sharing it here in case some people are interested. The credit goes to Adel from netfilter mailing list who suggested the possible workaround. Basically, the solution is to use nftables and set up a chain with the priority lower than the one for the defragmentation. I have tested this setting with C code and it seems to work pretty well (I did not notice any side effects). However, I have to mention that I used it only for observing IP fragments and I did not tamper with them.

Below there are two functions to set up nftables and then remove them.

void set_nftable() {

    int status = 0;

    // Create a nftable 
    status = system("nft add table ip filter");

    // Add a chain to the nftable called "predefrag" which has lower priority than the defragmentation -450 < -400
    status = system("nft add chain ip filter predefrag { type filter hook prerouting priority -- -450 \\; }");

    // Set the nftable rule (queue packets to be accessed by a user-space application)
    status = system("nft add filter predefrag meta iif eth0 counter queue num 0 bypass"); 
}

void remove_nftable() {

    int status = 0;

    // Flush the rules that are stored in the chains that belong to the nftable
    status = system("nft flush table ip filter");

    // Delete the chain from the nftable
    status = system("nft delete chain ip filter predefrag");

    // Delete the nftable
    status = system("nft delete table ip filter");
}

With those functions the nfqnl_test code can be used to capture IP fragments. Below there are useful links for setting up nftables and understating how they work (the comments in the functions are pretty self-explanatory once get acquainted with the nftables manual).

http://wiki.nftables.org/wiki-nftables/index.php/Building_and_installing_nftables_from_sources

http://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables

http://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains

http://wiki.nftables.org/wiki-nftables/index.php/Simple_rule_management

http://wiki.nftables.org/wiki-nftables/index.php/Queueing_to_userspace



回答2:

Before anything else, make sure that your network card isn't the one doing the reassembly.

Various offloading techniques performed by modern network card such as LRO, UFO, and others can reassemble IP level fragments. I suggesting using ethtool -k to check which offloads are active on the relevant interface, then turning them off one by one using ethtool -K.