2

I would like to use a c kernel module to capture all the network packets coming to an interface.. My topology is something like A--->B--->C, which means A sends a UDP packet to C's IP, but the packet will go through B.

My problem is that: at B side, by tcpdump, I can really capture the packet with IP(A)--->IP(C), however, in the kernel code, it does not capture such event (e.g. no print out messages as shown in the following code sample.).

My code is pretty much similar as one previous thread in How to echo a packet in kernel space using netfilter hooks?, and here I also paste the key parts in the following.

Please, someone has the idea to solve it? anywhere wrong?

Thank you so much.

ps, if "A" directly UDP packet to "B" (destination IP is B). then it successfully print out the message...(/proc/sys/net/ipv4/ip_forward is 1, and there is no iptables rule to drop the packet.).. I tried on debian 6.0 and ubuntu 14.04 real PC, and none of them is working..however, when I tried on a virtual machine with Ubuntu 14.04, it works..

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <net/ip.h>
#include <net/udp.h>
#include <net/route.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>

#define IP_HDR_LEN 20
#define UDP_HDR_LEN 8
#define TOT_HDR_LEN 28

static unsigned int pkt_echo_begin(unsigned int hooknum,
                        struct sk_buff *skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *));

static struct nf_hook_ops pkt_echo_ops __read_mostly = {
    .pf = NFPROTO_IPV4,
    .priority = 1,
    .hooknum = NF_INET_PRE_ROUTING,
    .hook = pkt_echo_begin,
};

static int __init pkt_echo_init(void)
{
    printk(KERN_ALERT "\npkt_echo module started ...");
    return nf_register_hook(&pkt_echo_ops);
}

static void __exit pkt_echo_exit(void)
{
    nf_unregister_hook(&pkt_echo_ops);
    printk(KERN_ALERT "pkt_echo module stopped ...");
}

static unsigned int pkt_echo_begin (unsigned int hooknum,
                        struct sk_buff *skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;
    struct udphdr *udph;
    unsigned char *data;

    unsigned char *temp;

    __u16 dst_port, src_port;
    int data_len;

    if (skb) {
        iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL);

        if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) {
            udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL);
            src_port = ntohs (udph->source);
            dst_port = ntohs (udph->dest);

            if (dst_port == 6000) {
                printk(KERN_ALERT "\n UDP packet goes in"); 
// NOTE: Here we have nothing, but tcpdump works and can capture the packet.

                ......

            }
        }
    }
    return NF_ACCEPT;
}
Community
  • 1
  • 1
Luc
  • 21
  • 2
  • Luc. Why does tcpdump not work? That should be your easiest solution. – pedwards Jun 08 '15 at 15:42
  • Hi, indeed, tcpdump works... I am bit suspecting that since destination MAC/IP is not B, in this case, the packet is dropped somewhere by B before reaching to the code part...but I would realy like to find the reason and make it work.. – Luc Jun 08 '15 at 15:46
  • See [this code](http://stackoverflow.com/a/29584449/3866447). It's intended for TCP packets, but it works and can be easily modified for UDP packets. – Sam Protsenko Jun 08 '15 at 18:32
  • Hi Sam. Thanks for the code example..very appreciate..unfortunately, it also does not work for my case.. I simply changed your TCP part into UDP... and tried again....If the destination IP/MAC is B, e.g. A-->B (as in my example before), it is able to print the UDP packet... but if destination is C, e.g. A-->C, it still does not print anything.. :( I did not post the modified code based on your link since it is almost the same as yours, only difference is removing print out tcp details, replacing by print a udp receiving info. (ps, I also tried with some other hooknum/priority, still no luck) – Luc Jun 08 '15 at 19:37
  • Have you put the network interface card into promiscuous mode? Unless you do something to change the situation, a NIC will normally filter packets destined to a MAC address other than its own (excepting also multicast/broadcast packets). tcpdump turns on promiscuous mode, but this isn't the default state so when it exits, the mode is turned off. Obviously if the NIC doesn't accept the packets destined to host C, they'll never reach your hook. – Gil Hamilton Jun 09 '15 at 13:45
  • Hi Gil, thanks for the comment, I was not aware of the mode before. I checked with my NIC, and it is by default promiscuous mode OFF.. so I turn it on by "ip link set ethX promisc on", and "netstat -i" shows the flag as "BMPRU", Since it has "P" in the flag, I think it should be turned on now..However, unfortuantely, I tested again with the code, and sending some UDP packets, kernel module still does not show the UDP packet where destined to C (still the same as before)... I am stuck at this point for some time, any comment would be really appreciated. – Luc Jun 09 '15 at 20:17

0 Answers0