Adding data to an outgoing packet with netfilter in a kernel module

38 views Asked by At

I was working on a kernel module lab where we built our own mini firewall. I started to research what else I can do and had an idea of trying to modify a packet by adding data to it. I came across an example that modified the options. I used that as an example and tried to adapt it to adding more data however what I have just causes the system to crash.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/slab.h>
#include <linux/inet.h>
#include <linux/time.h>
#include <linux/ktime.h>

static struct nf_hook_ops nfho_out;

unsigned int hook_out(void* priv, struct skb_buff* skb, const struct nf_hook_state* state)
{
    struct iph* iphdr;
    struct tcph* tcphdr;
    
    // Extra data to add
    unsigned char extra_data[] = {'A', 'D', 'D', 'T', 'H', 'I', 'S', 0};
    int extra_size = sizeof(extra_data);
    
    // Check valid skb
    if(!skb)
        return NF_ACCEPT;
    
    // Get IP header and check for TCP
    iph = ip_hdr(skb);
    if(!iph || iph->protocol != IPPROTO_TCP)
        return NF_ACCEPT;
    
    // Get TCP header
    tcph = tcp_hdr(skb);
    if(!tcph)
        return NF_ACCEPT;
        
    // Check for specific port
    if(ntohs(tcph->dest) != 9999)
        return NF_ACCEPT;
        
    // Make a copy of the skb with extra size for the extra data
    new_skb = skb_copy_expand(skb, skb_headroom(skb), skb->tail + extra_size, GFP_ATOMIC);
    if(!new_skb)
        return NF_ACCEPT;
        
    // Recalculate the IP header
    iph = ip_hdr(new_skb);
    if(!iph){
        kfree_skb(new_skb);
        return NF_ACCEPT;
    }
    
    // Update tot_len to include the extra bytes
    iph->tot_len = htons(ntohs(iph->tot_len) + extra_size);
    
    // Recalculate TCP header
    tcph = tcp_hdr(new_skb);
    if(!tcph){
        kfree_skb(new_skb);
        return NF_ACCEPT;
    }
    
    // Modify data here??
    
    // Calculate checksums here
    
    // From my understanding, this puts the new_skb up for kernel to send
    if(ip_local_out(new_skb)){
        kfree_skb(new_skb);
        return NF_ACCEPT;
    }
    
    printk("Modified TCP Packet!");
    
    return NF_DROP;
}

static int __init mod_init()
{
  nfho_out.hook = hook_out;
  nfho_out.hooknum = NF_INET_LOCAL_OUT;
  nfho_out.pf = PF_INET;
  nfho_out.priority = NF_IP_PRI_FIRST;
  return nf_register_hook(&nfho_out);
}

static void __exit mod_exit()
{
  nf_unregister_hook(&nfho_out);
}

MODULE_LICENSE("GPL");

module_init(mod_init);
module_exit(mod_exit);

I am new to this and stuck on how the skb should be expanded and how the extra data should be added. Also I am unsure if the ip_local_out() is the correct function to tell the kernel to process the packet.

0

There are 0 answers