From b14abda6000710f67abf3b94b054bb51cf531b4b Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Wed, 31 Jul 2024 22:13:06 +0300 Subject: [PATCH] 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. --- .gitignore | 22 +++------ Kbuild | 4 +- Makefile | 2 +- ipt_YTUNBLOCK.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ ipt_YTUNBLOCK.h | 6 +++ kmake.mk | 38 ++++++++++----- libipt_YTUNBLOCK.c | 26 ++++++++++ mangle.h | 5 +- youtubeKblock.c | 25 ---------- 9 files changed, 189 insertions(+), 57 deletions(-) create mode 100644 ipt_YTUNBLOCK.c create mode 100644 ipt_YTUNBLOCK.h create mode 100644 libipt_YTUNBLOCK.c delete mode 100644 youtubeKblock.c diff --git a/.gitignore b/.gitignore index e72e28f..f865d01 100644 --- a/.gitignore +++ b/.gitignore @@ -5,17 +5,11 @@ build configure~ # Kernel module files -.Module.* -.modules.* -Module.* -modules.* -.youtubeKblock.* -youtubeKblock.ko -youtubeKblock.mod* -youtubeKblock.o -.mangle.* -mangle.o -.youtubeKUnblock.* -youtubeKUnblock.ko -youtubeKUnblock.mod* -youtubeKUnblock.o +*.o +.* +*.mod.* +*.mod +modules.order +Module.symvers +*.so +*.ko diff --git a/Kbuild b/Kbuild index 2d99162..35c36db 100644 --- a/Kbuild +++ b/Kbuild @@ -1,3 +1,3 @@ -obj-m := youtubeKUnblock.o -youtubeKUnblock-objs := youtubeKblock.o mangle.o +obj-m := ipt_YTUNBLOCK.o +youtubeKUnblock-objs := ipt_YTUNBLOCK.o mangle.o ccflags-y := -std=gnu11 -Wno-unused-variable -DKERNEL_SPACE diff --git a/Makefile b/Makefile index 4a0e1e8..0e05091 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ 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 $(USPACE_TARGETS): diff --git a/ipt_YTUNBLOCK.c b/ipt_YTUNBLOCK.c new file mode 100644 index 0000000..de23ece --- /dev/null +++ b/ipt_YTUNBLOCK.c @@ -0,0 +1,118 @@ +// Kernel module for youtubeUnblock. +#include +#include +#include +#include +#include +#include +#include +#include "ipt_YTUNBLOCK.h" +#include "mangle.h" + +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); +MODULE_AUTHOR("Vadim Vetrov "); +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); diff --git a/ipt_YTUNBLOCK.h b/ipt_YTUNBLOCK.h new file mode 100644 index 0000000..9394f39 --- /dev/null +++ b/ipt_YTUNBLOCK.h @@ -0,0 +1,6 @@ +#ifndef IPT_YTUNBLOCK_H +#define IPT_YTUNBLOCK_H + +struct xt_ytunblock_tginfo {}; + +#endif /* IPT_YTUNBLOCK_H */ diff --git a/kmake.mk b/kmake.mk index 9a01090..00e3f0f 100644 --- a/kmake.mk +++ b/kmake.mk @@ -1,26 +1,42 @@ #Kernel module makes here PWD := $(CURDIR) -override CC := $(OCC) -override LD := $(OLD) -override CFLAGS := -override LDFLAGS := +CC := gcc +CCLD := $(CC) +LD := ld +CFLAGS := +LDFLAGS := -export CC LD CFLAGS LDFLAGS +IPT_CFLAGS := -Wall -Wpedantic -O2 -.PHONY: kmake kload kunload kreload kclean -kmake: +.PHONY: kmake kload kunload kreload kclean kmclean xclean +kmake: kmod xmod + +kmod: $(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: - insmod youtubeKUnblock.ko + insmod ipt_YTUNBLOCK.ko + cp ./libipt_YTUNBLOCK.so /usr/lib/xtables/ kunload: - -rmmod youtubeKUnblock + -rmmod ipt_YTUNBLOCK + -/bin/rm /usr/lib/xtables/libipt_YTUNBLOCK.so kreload: kunload kload -kclean: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean +kclean: xtclean kmclean +kmclean: + -$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean +xtclean: + -/bin/rm -f libipt_YTUNBLOCK.so libipt_YTUNBLOCK.o diff --git a/libipt_YTUNBLOCK.c b/libipt_YTUNBLOCK.c new file mode 100644 index 0000000..5b7b099 --- /dev/null +++ b/libipt_YTUNBLOCK.c @@ -0,0 +1,26 @@ +// Used to register target in iptables +#include +#include + +#include +#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); +} diff --git a/mangle.h b/mangle.h index 9c100b3..22b9df2 100644 --- a/mangle.h +++ b/mangle.h @@ -16,11 +16,8 @@ typedef __u32 uint32_t; #include #include -// #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 */ #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ diff --git a/youtubeKblock.c b/youtubeKblock.c deleted file mode 100644 index 3f622f6..0000000 --- a/youtubeKblock.c +++ /dev/null @@ -1,25 +0,0 @@ -// Kernel module for youtubeUnblock. -#include -#include -#include -#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 "); -MODULE_DESCRIPTION("Linux kernel module for youtube unblock"); - -module_init(ykb_init); -module_exit(ykb_destroy);