Last active
March 19, 2020 12:10
-
-
Save nkapliev/781f10187bf136d9a133e25f4d12d196 to your computer and use it in GitHub Desktop.
Linux kernel 4.4+ netfilter packet capturing boilerplate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/ip.h> | |
#include <linux/netfilter.h> | |
//#undef __KERNEL__ | |
#include <linux/netfilter_ipv4.h> | |
//#define __KERNEL__ | |
// I am using this code on my VM. Was interested in capturing only non-bridge packets | |
const __be32 HOST_IP_ADDR = 20687040; | |
const __be32 LOCAL_IP_ADDR = 171681984; | |
static struct nf_hook_ops nfin; | |
static struct nf_hook_ops nfout; | |
// In every netfilter guid you will find Linux kernel 2.x version of netfilter: | |
//typedef unsigned int nf_hookfn(unsigned int hooknum, | |
// struct sk_buff *skb, | |
// const struct net_device *in, | |
// const struct net_device *out, | |
// int (*okfn)(struct sk_buff *)) | |
//{ | |
// In 4.3- it was look like this: | |
//typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops, | |
// struct sk_buff *skb, | |
// const struct nf_hook_state *state); | |
// Since 4.4+ it was generalised: | |
static unsigned int hook_func_in(void *priv, | |
struct sk_buff *skb, | |
const struct nf_hook_state *state) | |
{ | |
struct ethhdr *eth; | |
struct iphdr *ip_header; | |
eth = (struct ethhdr*)skb_mac_header(skb); | |
ip_header = (struct iphdr *)skb_network_header(skb); | |
if (HOST_IP_ADDR == ip_header->saddr) | |
return NF_ACCEPT; | |
printk("NF_IP_LOCAL_IN hook:\n"); | |
printk("src mac %pM, dst mac %pM\n", eth->h_source, eth->h_dest); | |
printk("src IP addr:=%pI4\n", &ip_header->saddr); | |
return NF_ACCEPT; | |
} | |
static unsigned int hook_func_in(void *priv, | |
struct sk_buff *skb, | |
const struct nf_hook_state *state) | |
{ | |
struct ethhdr *eth; | |
struct iphdr *ip_header; | |
eth = (struct ethhdr*)skb_mac_header(skb); | |
ip_header = (struct iphdr *)skb_network_header(skb); | |
if (LOCAL_IP_ADDR == ip_header->saddr) | |
return NF_ACCEPT; | |
printk("NF_IP_LOCAL_OUT hook:\n"); | |
printk("src mac %pM, dst mac %pM\n", eth->h_source, eth->h_dest); | |
printk("src IP addr:=%pI4\n", &ip_header->saddr); | |
return NF_ACCEPT; | |
} | |
static int __init init_main(void) | |
{ | |
nfin.hook = hook_func_in; | |
nfin.hooknum = 1; // NF_IP_LOCAL_IN // TODO | |
nfin.pf = PF_INET; | |
nfin.priority = NF_IP_PRI_FIRST; | |
nf_register_hook(&nfin); | |
nfout.hook = hook_func_out; | |
nfout.hooknum = 3; // NF_IP_LOCAL_OUT // TODO | |
nfout.pf = PF_INET; | |
nfout.priority = NF_IP_PRI_FIRST; | |
nf_register_hook(&nfout); | |
return 0; | |
} | |
static void __exit cleanup_main(void) | |
{ | |
nf_unregister_hook(&nfin); | |
nf_unregister_hook(&nfout); | |
} | |
module_init(init_main); | |
module_exit(cleanup_main); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
obj-m += ip_mac_packet_logger.o | |
all: | |
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules | |
clean: | |
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean | |
install: | |
insmod ip_mac_packet_logger.ko | |
remove: | |
rmmod ip_mac_packet_logger.ko |
I still have no idea how to import netfilter_ipv4.h
in a way to define NF_IP_LOCAL_IN
and NF_IP_LOCAL_OUT
.
It seems like I need to be in user-space mode.
But when I tried to wrap import like this:
#undef __KERNEL__
#include <linux/netfilter_ipv4.h>
#define __KERNEL__
it says that it does not know where to find limits.h
, which is used inside netfilter_ipv4.h
.
I need to move forward so decided to leave it as it is.
Used information sources:
-
Linux module guide: http://www.tldp.org/LDP/lkmpg/2.6/html/x121.html
-
Netfilter HowTo guide: https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO.txt
-
Linux source code browser tool: http://elixir.free-electrons.com/linux/v4.3.6/source/include/linux/netfilter.h
can you help me with what I do if I need to print packets like in Wireshark application?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
$
tail -f /var/log/syslog