Use netfilter hook instead of iptables target

KISS principle is in action. No need to specify rules, just insmod
youtubeUnblock and it works!
This commit is contained in:
Vadim Vetrov 2024-09-01 20:58:50 +03:00
parent 5e327497bb
commit 5eeff9bc0d
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
6 changed files with 74 additions and 128 deletions

4
Kbuild
View File

@ -1,3 +1,3 @@
obj-m := ipt_YTUNBLOCK.o obj-m := kyoutubeUnblock.o
ipt_YTUNBLOCK-objs := iptk_YTUNBLOCK.o mangle.o quic.o utils.o kmod_utils.o kyoutubeUnblock-objs := kytunblock.o mangle.o quic.o utils.o kmod_utils.o
ccflags-y := -std=gnu11 -Wno-unused-variable -DKERNEL_SPACE -DDEBUG ccflags-y := -std=gnu11 -Wno-unused-variable -DKERNEL_SPACE -DDEBUG

View File

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

View File

@ -10,41 +10,20 @@ LDFLAGS :=
IPT_CFLAGS := -Wall -Wpedantic -O2 IPT_CFLAGS := -Wall -Wpedantic -O2
.PHONY: kmake kload kunload kreload kclean kmclean xclean .PHONY: kmake kload kunload kreload kclean kmclean xclean
kmake: kmod xmod kmake: kmod
kmod: 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 libip6t_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 $@ $<;
libip6t_YTUNBLOCK.so: libip6t_YTUNBLOCK.o
$(CCLD) -shared -fPIC ${IPT_CFLAGS} -o $@ $^;
libip6t_YTUNBLOCK.o: libip6t_YTUNBLOCK.c
$(CC) ${IPT_CFLAGS} -D_INIT=lib$*_init -fPIC -c -o $@ $<;
kload: kload:
insmod ipt_YTUNBLOCK.ko insmod kyoutubeUnblock.ko
cp ./libipt_YTUNBLOCK.so /usr/lib/xtables/
cp ./libip6t_YTUNBLOCK.so /usr/lib/xtables/
kunload: kunload:
-rmmod ipt_YTUNBLOCK -rmmod kyoutubeUnblock
-/bin/rm /usr/lib/xtables/libipt_YTUNBLOCK.so
-/bin/rm /usr/lib/xtables/libip6t_YTUNBLOCK.so
kreload: kunload kload kreload: kunload kload
kclean: xtclean kmclean kclean: kmclean
kmclean: kmclean:
-$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean -$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
xtclean:
-/bin/rm -f libipt_YTUNBLOCK.so libipt_YTUNBLOCK.o

View File

@ -9,8 +9,11 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/netfilter/x_tables.h> #include <linux/version.h>
#include "ipt_YTUNBLOCK.h"
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include "mangle.h" #include "mangle.h"
#include "config.h" #include "config.h"
@ -69,20 +72,23 @@ MODULE_VERSION("0.3.2");
MODULE_AUTHOR("Vadim Vetrov <vetrovvd@gmail.com>"); MODULE_AUTHOR("Vadim Vetrov <vetrovvd@gmail.com>");
MODULE_DESCRIPTION("Linux kernel module for youtube unblock"); MODULE_DESCRIPTION("Linux kernel module for youtube unblock");
static unsigned int ykb_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
if ((skb->mark & config.mark) == config.mark)
return XT_CONTINUE;
if (skb->head == NULL) return XT_CONTINUE; static unsigned int ykb_nf_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state) {
if ((skb->mark & config.mark) == config.mark)
goto accept_no_free;
if (skb->head == NULL)
goto accept_no_free;
uint32_t buflen = skb->len; uint32_t buflen = skb->len;
if (buflen > MAX_PACKET_SIZE) if (buflen > MAX_PACKET_SIZE)
goto accept; goto accept_no_free;
NETBUF_ALLOC(buf, buflen); NETBUF_ALLOC(buf, buflen);
if (!NETBUF_CHECK(buf)) if (!NETBUF_CHECK(buf))
goto no_free; goto accept_no_free;
if (skb_copy_bits(skb, 0, buf, buflen) < 0) { if (skb_copy_bits(skb, 0, buf, buflen) < 0) {
pr_err("Unable copy bits\n"); pr_err("Unable copy bits\n");
@ -100,39 +106,27 @@ static unsigned int ykb_tg(struct sk_buff *skb, const struct xt_action_param *pa
accept: accept:
NETBUF_FREE(buf); NETBUF_FREE(buf);
no_free: accept_no_free:
return XT_CONTINUE; return NF_ACCEPT;
drop: drop:
NETBUF_FREE(buf); NETBUF_FREE(buf);
kfree_skb(skb); kfree_skb(skb);
return NF_STOLEN; return NF_STOLEN;
} }
static int ykb_chk(const struct xt_tgchk_param *par) {
return 0;
}
static struct nf_hook_ops ykb_nf_reg __read_mostly = {
static struct xt_target ykb_tg_reg __read_mostly = { .hook = ykb_nf_hook,
.name = "YTUNBLOCK", .pf = NFPROTO_IPV4,
.target = ykb_tg, .hooknum = NF_INET_POST_ROUTING,
.table = "mangle", .priority = NF_IP_PRI_MANGLE,
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
.targetsize = sizeof(struct xt_ytunblock_tginfo),
.family = NFPROTO_IPV4,
.checkentry = ykb_chk,
.me = THIS_MODULE,
}; };
static struct xt_target ykb6_tg_reg __read_mostly = { static struct nf_hook_ops ykb6_nf_reg __read_mostly = {
.name = "YTUNBLOCK", .hook = ykb_nf_hook,
.target = ykb_tg, .pf = NFPROTO_IPV6,
.table = "mangle", .hooknum = NF_INET_POST_ROUTING,
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD), .priority = NF_IP6_PRI_MANGLE,
.targetsize = sizeof(struct xt_ytunblock_tginfo),
.family = NFPROTO_IPV6,
.checkentry = ykb_chk,
.me = THIS_MODULE,
}; };
static int __init ykb_init(void) { static int __init ykb_init(void) {
@ -141,24 +135,39 @@ static int __init ykb_init(void) {
ret = open_raw_socket(); ret = open_raw_socket();
if (ret < 0) goto err; if (ret < 0) goto err;
if (config.use_ipv6) { if (config.use_ipv6) {
ret = open_raw6_socket(); ret = open_raw6_socket();
if (ret < 0) goto close_rawsocket; if (ret < 0) goto close_rawsocket;
ret = xt_register_target(&ykb6_tg_reg); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
if (ret < 0) goto close_raw6socket; struct net *n;
for_each_net(n) {
ret = nf_register_net_hook(n, &ykb6_nf_reg);
if (ret < 0)
lgerror("bad rat",ret);
}
#else
nf_register_hook(&ykb6_nf_reg);
#endif
} }
ret = xt_register_target(&ykb_tg_reg);
if (ret < 0) goto close_xt6_target; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
struct net *n;
for_each_net(n) {
ret = nf_register_net_hook(n, &ykb_nf_reg);
if (ret < 0)
lgerror("bad rat",ret);
}
#else
nf_register_hook(&ykb_nf_reg);
#endif
pr_info("youtubeUnblock kernel module started.\n"); pr_info("youtubeUnblock kernel module started.\n");
return 0; return 0;
close_xt6_target:
if (config.use_ipv6) xt_unregister_target(&ykb6_tg_reg);
close_raw6socket:
if (config.use_ipv6) close_raw6_socket();
close_rawsocket: close_rawsocket:
close_raw_socket(); close_raw_socket();
err: err:
@ -166,9 +175,25 @@ err:
} }
static void __exit ykb_destroy(void) { static void __exit ykb_destroy(void) {
xt_unregister_target(&ykb_tg_reg); if (config.use_ipv6) {
if (config.use_ipv6) xt_unregister_target(&ykb6_tg_reg); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
if (config.use_ipv6) close_raw6_socket(); struct net *n;
for_each_net(n)
nf_unregister_net_hook(n, &ykb6_nf_reg);
#else
nf_unregister_hook(&ykb6_nf_reg);
#endif
close_raw6_socket();
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
struct net *n;
for_each_net(n)
nf_unregister_net_hook(n, &ykb_nf_reg);
#else
nf_unregister_hook(&ykb_nf_reg);
#endif
close_raw_socket(); close_raw_socket();
pr_info("youtubeUnblock kernel module destroyed.\n"); pr_info("youtubeUnblock kernel module destroyed.\n");
} }

View File

@ -1,26 +0,0 @@
// Used to register target in iptables
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter_ipv6/ip6_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 ykb6_tg_reg = {
.name = "YTUNBLOCK",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV6,
.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(&ykb6_tg_reg);
}

View File

@ -1,26 +0,0 @@
// 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);
}