summaryrefslogtreecommitdiff
path: root/md/notes/kernel
diff options
context:
space:
mode:
authorArturs Artamonovs <dos21h@gmail.com>2024-04-12 09:07:58 +0100
committerArturs Artamonovs <dos21h@gmail.com>2024-04-12 09:07:58 +0100
commit1612c672efc6eae9dcf8d9b2ca9542d027a60b94 (patch)
treea82032645e5f3065c42e0feaab7b7d4b8b3455e6 /md/notes/kernel
parent46336b7a31fb14e22fe9c270f5ba50b21a8909a5 (diff)
downloadmd-content-1612c672efc6eae9dcf8d9b2ca9542d027a60b94.tar.gz
md-content-1612c672efc6eae9dcf8d9b2ca9542d027a60b94.zip
Add netfilter icmp example
Diffstat (limited to 'md/notes/kernel')
-rw-r--r--md/notes/kernel/netfilter_module.md280
-rw-r--r--md/notes/kernel/netlink_show_ip.md2
-rw-r--r--md/notes/kernel/netlink_socket.md2
-rw-r--r--md/notes/kernel/topics.md4
4 files changed, 285 insertions, 3 deletions
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 <linux/module.h> /* Needed by all modules */
+#include <linux/kernel.h>
+
+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)
<!-- Create syscall -->
-
<!-- Dummy I2C driver -->
<!-- Dummy SPI driver -->
<!-- Create ADC driver -->
<!-- Mutex'es -->
<!-- Threads -->
<!-- Locking -->
+<!-- RB-trees -->
### Deep into kernel
@@ -57,6 +58,7 @@ accordingly.
### Kernel userspace
[Netlink show ip](/notes/kernel/netlink_show_ip.md)
+
<!-- Netfilter set ip -->
<!-- khttpd -->