From 1612c672efc6eae9dcf8d9b2ca9542d027a60b94 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Fri, 12 Apr 2024 09:07:58 +0100 Subject: Add netfilter icmp example --- md/notes/kernel/netfilter_module.md | 280 ++++++++++++++++++++++++++++++++++++ md/notes/kernel/netlink_show_ip.md | 2 +- md/notes/kernel/netlink_socket.md | 2 +- md/notes/kernel/topics.md | 4 +- 4 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 md/notes/kernel/netfilter_module.md diff --git a/md/notes/kernel/netfilter_module.md b/md/notes/kernel/netfilter_module.md new file mode 100644 index 0000000..fbe56b6 --- /dev/null +++ b/md/notes/kernel/netfilter_module.md @@ -0,0 +1,280 @@ +title: Netlink socket +keywords: kernel,linux,netlink,socket + +# Kernel netfilter module + + +## Files + +You need to create to files __Makefile__ and __netlink_socket.c__. + +__Makefile__ +```Makefile +obj-m += netlink_socket.o + +KDIR ?= /lib/modules/$(shell uname -r)/build + +all: + make -C $(KDIR) M=$(PWD) modules + +clean: + make -C $(KDIR) M=$(PWD) clean + +``` + + +__netlink_socket.c__ +```c +//http://www.tldp.org/LDP/lkmpg/2.4/html/c147.htm +#include /* Needed by all modules */ +#include + +int netlink_socket_init( void ) +{ + printk(KERN_DEBUG "Netlink World!\n"); + return 0; +} + +void netlink_socket_exit( void ) +{ + printk(KERN_DEBUG "Exit Netlink World!\n"); +} + +module_init( netlink_socket_init ); +module_exit( netlink_socket_exit ); + +MODULE_LICENSE("GPL"); +``` + + +Add to makefile step to compile userspace program + +```makefile +all: + make -C $(KDIR) M=$(PWD) modules + gcc netlink_connect.c -o netlink_connect +``` + + + +## Prepare the hook function + +```c +... +static unsigned int netfilter_icmp_blockicmppkt_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) +{ + struct iphdr *iph; // IP header + struct udphdr *udph; // UDP header + + if(!skb) + return NF_ACCEPT; + + iph = ip_hdr(skb); // retrieve the IP headers from the packet + if(iph->protocol == IPPROTO_UDP) { + udph = udp_hdr(skb); + if(ntohs(udph->dest) == 53) { + return NF_ACCEPT; // accept UDP packet + } + } + else if (iph->protocol == IPPROTO_TCP) { + return NF_ACCEPT; // accept TCP packet + } + else if (iph->protocol == IPPROTO_ICMP) { + printk(KERN_INFO "Drop ICMP packet \n"); + return NF_DROP; // drop TCP packet + } + + return NF_ACCEPT; +} +... +``` + +## Register netfilter + +```c +... +int netfilter_icmp_init( void ) +{ + ... + nf_blockicmppkt_ops = (struct nf_hook_ops*)kcalloc(1, sizeof(struct nf_hook_ops), GFP_KERNEL); + if (nf_blockicmppkt_ops != NULL) { + nf_blockicmppkt_ops->hook = (nf_hookfn*)netfilter_icmp_blockicmppkt_hook; + nf_blockicmppkt_ops->hooknum = NF_INET_PRE_ROUTING; + nf_blockicmppkt_ops->pf = NFPROTO_IPV4; + nf_blockicmppkt_ops->priority = NF_IP_PRI_FIRST; // set the priority + + nf_register_net_hook(&init_net, nf_blockicmppkt_ops); + } + ... + return 0; +} +... +``` + +## Data structures and fucntions + +The lis of functions used in this example + +__nf_register_net_hook__ +``` +int nf_register_net_hook(struct net *net, const struct nf_hook_ops *ops); +``` + +__udp_hdr__ +```c +static inline struct udphdr *udp_hdr(const struct sk_buff *skb) +{ + return (struct udphdr *)skb_transport_header(skb); +} +``` + +__ip_hdr__ +```c +static inline struct iphdr *ip_hdr(const struct sk_buff *skb) +{ + return (struct iphdr *)skb_network_header(skb); +} +``` + +list of hooknum options in hook_ops +```c +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS, + NF_INET_INGRESS = NF_INET_NUMHOOKS, +}; +``` + +list of pf options in hook_ops +```c +enum { + NFPROTO_UNSPEC = 0, + NFPROTO_INET = 1, + NFPROTO_IPV4 = 2, + NFPROTO_ARP = 3, + NFPROTO_NETDEV = 5, + NFPROTO_BRIDGE = 7, + NFPROTO_IPV6 = 10, +#ifndef __KERNEL__ /* no longer supported by kernel */ + NFPROTO_DECNET = 12, +#endif + NFPROTO_NUMPROTO, +}; +``` + + +list of priority option in hook_ops +```c +enum nf_ip_hook_priorities { + NF_IP_PRI_FIRST = INT_MIN, + NF_IP_PRI_RAW_BEFORE_DEFRAG = -450, + NF_IP_PRI_CONNTRACK_DEFRAG = -400, + NF_IP_PRI_RAW = -300, + NF_IP_PRI_SELINUX_FIRST = -225, + NF_IP_PRI_CONNTRACK = -200, + NF_IP_PRI_MANGLE = -150, + NF_IP_PRI_NAT_DST = -100, + NF_IP_PRI_FILTER = 0, + NF_IP_PRI_SECURITY = 50, + NF_IP_PRI_NAT_SRC = 100, + NF_IP_PRI_SELINUX_LAST = 225, + NF_IP_PRI_CONNTRACK_HELPER = 300, + NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, + NF_IP_PRI_LAST = INT_MAX, +}; +``` + +List of protocol options when check for ip header protocol + + +```c +enum { + IPPROTO_IP = 0, /* Dummy protocol for TCP */ + IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ + IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ + IPPROTO_TCP = 6, /* Transmission Control Protocol */ + IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ + IPPROTO_PUP = 12, /* PUP protocol */ + IPPROTO_UDP = 17, /* User Datagram Protocol */ + IPPROTO_IDP = 22, /* XNS IDP protocol */ + IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */ + IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ + IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ + IPPROTO_RSVP = 46, /* RSVP Protocol */ + IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ + IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ + IPPROTO_AH = 51, /* Authentication Header protocol */ + IPPROTO_MTP = 92, /* Multicast Transport Protocol */ + IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ + IPPROTO_ENCAP = 98, /* Encapsulation Header */ + IPPROTO_PIM = 103, /* Protocol Independent Multicast */ + IPPROTO_COMP = 108, /* Compression Header Protocol */ + IPPROTO_L2TP = 115, /* Layer 2 Tunnelling Protocol */ + IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ + IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ + IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */ + IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation */ + IPPROTO_RAW = 255, /* Raw IP packets */ + IPPROTO_MPTCP = 262, /* Multipath TCP connection */ + IPPROTO_MAX +}; +``` + +## Compile + +Compile the module and userspace program + +```sh +make +``` + +## Load module + +```sh +sudo insmod netlink_socket.ko +``` + +check that module is running + +```sh +lsmod | grep netlink +``` + +## Unload module + +```sh +rmmod netlink_socket +``` + + +## Test + +Run userspace programm and receive back message with capitalised letters + +```bash + +``` + +## Note + +This example mostly followed from levelup blog, now time to figure out what I can add on top of it. + +## Links + +1. https://inai.de/documents/Netfilter_Modules.pdf +2. https://infosecwriteups.com/linux-kernel-communication-part-1-netfilter-hooks-15c07a5a5c4e +3. https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-4.html +4. https://github.com/zentyal/ndpi-netfilter/blob/master/src/main.c +5. https://levelup.gitconnected.com/write-a-linux-firewall-from-scratch-based-on-netfilter-462013202686 +6. https://blogs.oracle.com/linux/post/introduction-to-netfilter +7. https://elixir.bootlin.com/linux/v6.6.20/source/include/uapi/linux/netfilter.h#L12 +8. https://elixir.bootlin.com/linux/v6.6.20/source/net/ipv4/ip_input.c#L560 +9. https://elixir.bootlin.com/linux/v6.6.20/source/include/linux/ip.h#L19 +10. https://elixir.bootlin.com/linux/v6.6.20/source/include/linux/udp.h#L21 +11. https://elixir.bootlin.com/linux/v6.6.20/source/include/linux/skbuff.h#L842 + diff --git a/md/notes/kernel/netlink_show_ip.md b/md/notes/kernel/netlink_show_ip.md index 87f0b83..204e7a1 100644 --- a/md/notes/kernel/netlink_show_ip.md +++ b/md/notes/kernel/netlink_show_ip.md @@ -247,7 +247,7 @@ make Output looks like -``` +```sh received message type 20 interface lo prefix length 8 diff --git a/md/notes/kernel/netlink_socket.md b/md/notes/kernel/netlink_socket.md index e022e52..fd3477e 100644 --- a/md/notes/kernel/netlink_socket.md +++ b/md/notes/kernel/netlink_socket.md @@ -1,7 +1,7 @@ title: Netlink socket keywords: kernel,linux,netlink,socket -# Kernel compile "Hello world" +# Kernel netlink socket As base start from minimal kernel module diff --git a/md/notes/kernel/topics.md b/md/notes/kernel/topics.md index 8682aeb..e2c107b 100644 --- a/md/notes/kernel/topics.md +++ b/md/notes/kernel/topics.md @@ -35,14 +35,15 @@ accordingly. [Kernel /dev/hwrng](/writeup/kernel_dev_hwrng.md) [Netlink socket](/notes/kernel/netlink_socket.md) +[Netfilter module](/notes/kernel/netfilter_module.md) - + ### Deep into kernel @@ -57,6 +58,7 @@ accordingly. ### Kernel userspace [Netlink show ip](/notes/kernel/netlink_show_ip.md) + -- cgit v1.2.3