Add skeleton for module and userspace iptables management

Special thanks to https://github.com/drivenets/iptables_extensions
repository with detailed explanations of iptables userspace interaction
with the kernel module.
This commit is contained in:
Vadim Vetrov 2024-07-31 22:13:06 +03:00
parent 79d592a0ca
commit b14abda600
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
9 changed files with 189 additions and 57 deletions

22
.gitignore vendored
View File

@ -5,17 +5,11 @@ build
configure~ configure~
# Kernel module files # Kernel module files
.Module.* *.o
.modules.* .*
Module.* *.mod.*
modules.* *.mod
.youtubeKblock.* modules.order
youtubeKblock.ko Module.symvers
youtubeKblock.mod* *.so
youtubeKblock.o *.ko
.mangle.*
mangle.o
.youtubeKUnblock.*
youtubeKUnblock.ko
youtubeKUnblock.mod*
youtubeKUnblock.o

4
Kbuild
View File

@ -1,3 +1,3 @@
obj-m := youtubeKUnblock.o obj-m := ipt_YTUNBLOCK.o
youtubeKUnblock-objs := youtubeKblock.o mangle.o youtubeKUnblock-objs := ipt_YTUNBLOCK.o mangle.o
ccflags-y := -std=gnu11 -Wno-unused-variable -DKERNEL_SPACE ccflags-y := -std=gnu11 -Wno-unused-variable -DKERNEL_SPACE

View File

@ -1,5 +1,5 @@
USPACE_TARGETS := default all install uninstall dev run_dev USPACE_TARGETS := default all install uninstall dev run_dev
KMAKE_TARGETS := kmake kload kunload kreload KMAKE_TARGETS := kmake kload kunload kreload xmod xtclean
.PHONY: $(USPACE_TARGETS) $(KMAKE_TARGETS) clean .PHONY: $(USPACE_TARGETS) $(KMAKE_TARGETS) clean
$(USPACE_TARGETS): $(USPACE_TARGETS):

118
ipt_YTUNBLOCK.c Normal file
View File

@ -0,0 +1,118 @@
// Kernel module for youtubeUnblock.
#include <linux/module.h>
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/mutex.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/netfilter/x_tables.h>
#include "ipt_YTUNBLOCK.h"
#include "mangle.h"
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
MODULE_AUTHOR("Vadim Vetrov <vetrovvd@gmail.com>");
MODULE_DESCRIPTION("Linux kernel module for youtube unblock");
static int rsfd;
static struct socket *rawsocket;
DEFINE_MUTEX(rslock);
static int open_raw_socket(void) {
int ret = 0;
ret = sock_create(AF_INET, SOCK_RAW, IPPROTO_RAW, &rawsocket);
if (ret < 0) {
pr_alert("Unable to create raw socket\n");
goto err;
}
sockptr_t optval = {
.kernel = NULL,
.is_kernel = 1
};
int mark = RAWSOCKET_MARK;
optval.kernel = &mark;
ret = sock_setsockopt(rawsocket, SOL_SOCKET, SO_MARK, optval, sizeof(mark));
if (ret < 0)
{
pr_alert("setsockopt(SO_MARK, %d) failed\n", mark);
goto err;
}
int one = 1;
optval.kernel = &one;
// ret = sock_setsockopt(rawsocket, IPPROTO_IP, IP_HDRINCL, optval, sizeof(one));
// if (ret < 0)
// {
// pr_alert("setsockopt(IP_HDRINCL, 1) failed\n");
// goto err;
// }
return 0;
err:
return ret;
}
static void close_raw_socket(void) {
sock_release(rawsocket);
}
static unsigned int ykb_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
if (skb->head == NULL) return XT_CONTINUE;
const __u8 *rawdata = skb->head + skb->network_header;
const __u32 rawsize = skb->len;
struct iphdr *iph = ip_hdr(skb);
pr_info("Lengths: %d %d %d %d\n", skb->len, skb->mac_len, skb->hdr_len, skb->data_len);
pr_info("Lengths: %d %d\n", skb->network_header == skb->mac_len, skb->hdr_len == iph->ihl * 4);
return XT_CONTINUE;
}
static int ykb_chk(const struct xt_tgchk_param *par) {
pr_info("Checkentry\n");
return 0;
}
static struct xt_target ykb_tg_reg __read_mostly = {
.name = "YTUNBLOCK",
.target = ykb_tg,
.table = "mangle",
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
.targetsize = sizeof(struct xt_ytunblock_tginfo),
.proto = IPPROTO_TCP,
.family = NFPROTO_IPV4,
.checkentry = ykb_chk,
.me = THIS_MODULE,
};
static int __init ykb_init(void) {
int ret = 0;
ret = open_raw_socket();
if (ret < 0) goto err;
ret = xt_register_target(&ykb_tg_reg);
if (ret < 0) goto close_rawsocket;
pr_info("youtubeUnblock kernel module started.\n");
return 0;
close_rawsocket:
close_raw_socket();
err:
return ret;
}
static void __exit ykb_destroy(void) {
xt_unregister_target(&ykb_tg_reg);
close_raw_socket();
pr_info("youtubeUnblock kernel module destroyed.\n");
}
module_init(ykb_init);
module_exit(ykb_destroy);

6
ipt_YTUNBLOCK.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef IPT_YTUNBLOCK_H
#define IPT_YTUNBLOCK_H
struct xt_ytunblock_tginfo {};
#endif /* IPT_YTUNBLOCK_H */

View File

@ -1,26 +1,42 @@
#Kernel module makes here #Kernel module makes here
PWD := $(CURDIR) PWD := $(CURDIR)
override CC := $(OCC) CC := gcc
override LD := $(OLD) CCLD := $(CC)
override CFLAGS := LD := ld
override LDFLAGS := CFLAGS :=
LDFLAGS :=
export CC LD CFLAGS LDFLAGS IPT_CFLAGS := -Wall -Wpedantic -O2
.PHONY: kmake kload kunload kreload kclean .PHONY: kmake kload kunload kreload kclean kmclean xclean
kmake: kmake: kmod xmod
kmod:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
xmod: libipt_YTUNBLOCK.so
libipt_YTUNBLOCK.so: libipt_YTUNBLOCK.o
$(CCLD) -shared -fPIC ${IPT_CFLAGS} -o $@ $^;
libipt_YTUNBLOCK.o: libipt_YTUNBLOCK.c
$(CC) ${IPT_CFLAGS} -D_INIT=lib$*_init -fPIC -c -o $@ $<;
kload: kload:
insmod youtubeKUnblock.ko insmod ipt_YTUNBLOCK.ko
cp ./libipt_YTUNBLOCK.so /usr/lib/xtables/
kunload: kunload:
-rmmod youtubeKUnblock -rmmod ipt_YTUNBLOCK
-/bin/rm /usr/lib/xtables/libipt_YTUNBLOCK.so
kreload: kunload kload kreload: kunload kload
kclean: kclean: xtclean kmclean
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
kmclean:
-$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
xtclean:
-/bin/rm -f libipt_YTUNBLOCK.so libipt_YTUNBLOCK.o

26
libipt_YTUNBLOCK.c Normal file
View File

@ -0,0 +1,26 @@
// Used to register target in iptables
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include "ipt_YTUNBLOCK.h"
#define _init __attribute__((constructor)) _INIT
#define __maybe_unused __attribute__((__unused__))
static void YTKB_help(void) {
printf("Youtube Unblock - bypass youtube slowdown DPI in Russia\n");
}
static struct xtables_target ykb_tg_reg = {
.name = "YTUNBLOCK",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_ytunblock_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_ytunblock_tginfo)),
.help = YTKB_help,
};
void _init(void) {
xtables_register_target(&ykb_tg_reg);
}

View File

@ -16,11 +16,8 @@ typedef __u32 uint32_t;
#include <linux/tcp.h> #include <linux/tcp.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
// #define ntohs(x) __constant_ntohs(x)
// #define ntohl(x) __constant_ntohl(x)
// #define htons(x) __constant_htons(x)
// #define htonl(x) __constant_htonl(x)
/* from <netinet/ip.h> */
#define IP_RF 0x8000 /* reserved fragment flag */ #define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */ #define IP_MF 0x2000 /* more fragments flag */

View File

@ -1,25 +0,0 @@
// Kernel module for youtubeUnblock.
#include <linux/module.h>
#include <linux/init.h>
#include <linux/printk.h>
#include "mangle.h"
static int __init ykb_init(void) {
pr_info("youtubeUnblock kernel module started.\n");
return 0;
}
static void __exit ykb_destroy(void) {
pr_info("youtubeUnblock kernel module destroyed.\n");
}
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
MODULE_AUTHOR("Vadim Vetrov <vetrovvd@gmail.com>");
MODULE_DESCRIPTION("Linux kernel module for youtube unblock");
module_init(ykb_init);
module_exit(ykb_destroy);