mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2024-12-22 06:15:31 +00:00
Split raw socket logic from iptables kernel module, add udp over ipv6
support
This commit is contained in:
parent
731da0dd50
commit
5e327497bb
2
Kbuild
2
Kbuild
@ -1,3 +1,3 @@
|
|||||||
obj-m := ipt_YTUNBLOCK.o
|
obj-m := ipt_YTUNBLOCK.o
|
||||||
ipt_YTUNBLOCK-objs := iptk_YTUNBLOCK.o mangle.o quic.o utils.o
|
ipt_YTUNBLOCK-objs := iptk_YTUNBLOCK.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
|
||||||
|
246
iptk_YTUNBLOCK.c
246
iptk_YTUNBLOCK.c
@ -1,4 +1,6 @@
|
|||||||
#define _GNU_SOURCE
|
#ifndef KERNEL_SPACE
|
||||||
|
#error "You are trying to compile the kernel module not in the kernel space"
|
||||||
|
#endif
|
||||||
// Kernel module for youtubeUnblock.
|
// Kernel module for youtubeUnblock.
|
||||||
// Make with make kmake && sudo iptables -t mangle -D OUTPUT 1 && sudo make kreload && sudo iptables -t mangle -I OUTPUT -p tcp -j YTUNBLOCK
|
// Make with make kmake && sudo iptables -t mangle -D OUTPUT 1 && sudo make kreload && sudo iptables -t mangle -I OUTPUT -p tcp -j YTUNBLOCK
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -15,6 +17,7 @@
|
|||||||
#include "raw_replacements.h"
|
#include "raw_replacements.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include "kmod_utils.h"
|
||||||
|
|
||||||
struct config_t config = {
|
struct config_t config = {
|
||||||
.threads = THREADS_NUM,
|
.threads = THREADS_NUM,
|
||||||
@ -66,245 +69,6 @@ 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 struct socket *rawsocket;
|
|
||||||
DEFINE_MUTEX(rslock);
|
|
||||||
|
|
||||||
static struct socket *raw6socket;
|
|
||||||
DEFINE_MUTEX(rs6lock);
|
|
||||||
|
|
||||||
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 = config.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 sr_err;
|
|
||||||
}
|
|
||||||
int one = 1;
|
|
||||||
optval.kernel = &one;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
sr_err:
|
|
||||||
sock_release(rawsocket);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void close_raw_socket(void) {
|
|
||||||
sock_release(rawsocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) {
|
|
||||||
int ret = 0;
|
|
||||||
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
|
||||||
|
|
||||||
struct iphdr *iph;
|
|
||||||
|
|
||||||
if ((ret = ip4_payload_split(
|
|
||||||
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in daddr = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = 0,
|
|
||||||
.sin_addr = {
|
|
||||||
.s_addr = iph->daddr
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msghdr msg;
|
|
||||||
struct kvec iov;
|
|
||||||
iov.iov_base = (__u8 *)pkt;
|
|
||||||
iov.iov_len = pktlen;
|
|
||||||
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, 1);
|
|
||||||
|
|
||||||
msg.msg_flags = 0;
|
|
||||||
msg.msg_name = &daddr;
|
|
||||||
msg.msg_namelen = sizeof(struct sockaddr_in);
|
|
||||||
msg.msg_control = NULL;
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
|
|
||||||
mutex_lock(&rslock);
|
|
||||||
ret = kernel_sendmsg(rawsocket, &msg, &iov, 1, pktlen);
|
|
||||||
mutex_unlock(&rslock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int open_raw6_socket(void) {
|
|
||||||
int ret = 0;
|
|
||||||
ret = sock_create(AF_INET6, SOCK_RAW, IPPROTO_RAW, &raw6socket);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
pr_alert("Unable to create raw socket\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sockptr_t optval = {
|
|
||||||
.kernel = NULL,
|
|
||||||
.is_kernel = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
int mark = config.mark;
|
|
||||||
optval.kernel = &mark;
|
|
||||||
ret = sock_setsockopt(raw6socket, SOL_SOCKET, SO_MARK, optval, sizeof(mark));
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
pr_alert("setsockopt(SO_MARK, %d) failed\n", mark);
|
|
||||||
goto sr_err;
|
|
||||||
}
|
|
||||||
int one = 1;
|
|
||||||
optval.kernel = &one;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
sr_err:
|
|
||||||
sock_release(raw6socket);
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void close_raw6_socket(void) {
|
|
||||||
sock_release(raw6socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) {
|
|
||||||
int ret = 0;
|
|
||||||
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
|
||||||
|
|
||||||
struct ip6_hdr *iph;
|
|
||||||
|
|
||||||
if ((ret = ip6_payload_split(
|
|
||||||
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in6 daddr = {
|
|
||||||
.sin6_family = AF_INET6,
|
|
||||||
/* Always 0 for raw socket */
|
|
||||||
.sin6_port = 0,
|
|
||||||
.sin6_addr = iph->ip6_dst
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msghdr msg;
|
|
||||||
struct kvec iov;
|
|
||||||
iov.iov_base = (__u8 *)pkt;
|
|
||||||
iov.iov_len = pktlen;
|
|
||||||
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, 1);
|
|
||||||
|
|
||||||
msg.msg_flags = 0;
|
|
||||||
msg.msg_name = &daddr;
|
|
||||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
|
||||||
msg.msg_control = NULL;
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
|
|
||||||
mutex_lock(&rs6lock);
|
|
||||||
ret = kernel_sendmsg(raw6socket, &msg, &iov, 1, pktlen);
|
|
||||||
mutex_unlock(&rs6lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (pktlen > AVAILABLE_MTU) {
|
|
||||||
pr_warn("The packet is too big and may cause issues!");
|
|
||||||
|
|
||||||
NETBUF_ALLOC(buff1, MAX_PACKET_SIZE);
|
|
||||||
if (!NETBUF_CHECK(buff1)) {
|
|
||||||
lgerror("Allocation error", -ENOMEM);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
NETBUF_ALLOC(buff2, MAX_PACKET_SIZE);
|
|
||||||
if (!NETBUF_CHECK(buff2)) {
|
|
||||||
lgerror("Allocation error", -ENOMEM);
|
|
||||||
NETBUF_FREE(buff2);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
uint32_t buff1_size = MAX_PACKET_SIZE;
|
|
||||||
uint32_t buff2_size = MAX_PACKET_SIZE;
|
|
||||||
|
|
||||||
switch (config.fragmentation_strategy) {
|
|
||||||
case FRAG_STRAT_TCP:
|
|
||||||
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
|
||||||
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
|
||||||
|
|
||||||
goto erret_lc;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FRAG_STRAT_IP:
|
|
||||||
if ((ret = ip4_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
|
||||||
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
|
||||||
|
|
||||||
goto erret_lc;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_warn("send_raw_socket: Packet is too big but fragmentation is disabled!");
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto erret_lc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sent = 0;
|
|
||||||
ret = send_raw_socket(buff1, buff1_size);
|
|
||||||
|
|
||||||
if (ret >= 0) sent += ret;
|
|
||||||
else {
|
|
||||||
goto erret_lc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = send_raw_socket(buff2, buff2_size);
|
|
||||||
if (ret >= 0) sent += ret;
|
|
||||||
else {
|
|
||||||
goto erret_lc;
|
|
||||||
}
|
|
||||||
|
|
||||||
NETBUF_FREE(buff1);
|
|
||||||
NETBUF_FREE(buff2);
|
|
||||||
return sent;
|
|
||||||
erret_lc:
|
|
||||||
NETBUF_FREE(buff1);
|
|
||||||
NETBUF_FREE(buff2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ipvx = netproto_version(pkt, pktlen);
|
|
||||||
|
|
||||||
if (ipvx == IP4VERSION)
|
|
||||||
return send_raw_ipv4(pkt, pktlen);
|
|
||||||
|
|
||||||
else if (ipvx == IP6VERSION)
|
|
||||||
return send_raw_ipv6(pkt, pktlen);
|
|
||||||
|
|
||||||
printf("proto version %d is unsupported\n", ipvx);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms) {
|
|
||||||
pr_warn("delay_packet_send won't work on current youtubeUnblock version");
|
|
||||||
send_raw_socket(data, data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct instance_config_t instance_config = {
|
|
||||||
.send_raw_packet = send_raw_socket,
|
|
||||||
.send_delayed_packet = delay_packet_send,
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned int ykb_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
static unsigned int ykb_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||||
{
|
{
|
||||||
if ((skb->mark & config.mark) == config.mark)
|
if ((skb->mark & config.mark) == config.mark)
|
||||||
@ -355,7 +119,6 @@ static struct xt_target ykb_tg_reg __read_mostly = {
|
|||||||
.table = "mangle",
|
.table = "mangle",
|
||||||
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
|
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
|
||||||
.targetsize = sizeof(struct xt_ytunblock_tginfo),
|
.targetsize = sizeof(struct xt_ytunblock_tginfo),
|
||||||
.proto = IPPROTO_TCP,
|
|
||||||
.family = NFPROTO_IPV4,
|
.family = NFPROTO_IPV4,
|
||||||
.checkentry = ykb_chk,
|
.checkentry = ykb_chk,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
@ -367,7 +130,6 @@ static struct xt_target ykb6_tg_reg __read_mostly = {
|
|||||||
.table = "mangle",
|
.table = "mangle",
|
||||||
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
|
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD),
|
||||||
.targetsize = sizeof(struct xt_ytunblock_tginfo),
|
.targetsize = sizeof(struct xt_ytunblock_tginfo),
|
||||||
.proto = IPPROTO_TCP,
|
|
||||||
.family = NFPROTO_IPV6,
|
.family = NFPROTO_IPV6,
|
||||||
.checkentry = ykb_chk,
|
.checkentry = ykb_chk,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
|
255
kmod_utils.c
Normal file
255
kmod_utils.c
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
#ifndef KERNEL_SPACE
|
||||||
|
#error "You are trying to compile the kernel module not in the kernel space"
|
||||||
|
#endif
|
||||||
|
#include "kmod_utils.h"
|
||||||
|
|
||||||
|
#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 "config.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
static struct socket *rawsocket;
|
||||||
|
DEFINE_MUTEX(rslock);
|
||||||
|
|
||||||
|
static struct socket *raw6socket;
|
||||||
|
DEFINE_MUTEX(rs6lock);
|
||||||
|
|
||||||
|
|
||||||
|
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 = config.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 sr_err;
|
||||||
|
}
|
||||||
|
int one = 1;
|
||||||
|
optval.kernel = &one;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
sr_err:
|
||||||
|
sock_release(rawsocket);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_raw_socket(void) {
|
||||||
|
sock_release(rawsocket);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
|
int ret = 0;
|
||||||
|
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
||||||
|
|
||||||
|
struct iphdr *iph;
|
||||||
|
|
||||||
|
if ((ret = ip4_payload_split(
|
||||||
|
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in daddr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = 0,
|
||||||
|
.sin_addr = {
|
||||||
|
.s_addr = iph->daddr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msghdr msg;
|
||||||
|
struct kvec iov;
|
||||||
|
iov.iov_base = (__u8 *)pkt;
|
||||||
|
iov.iov_len = pktlen;
|
||||||
|
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, 1);
|
||||||
|
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
msg.msg_name = &daddr;
|
||||||
|
msg.msg_namelen = sizeof(struct sockaddr_in);
|
||||||
|
msg.msg_control = NULL;
|
||||||
|
msg.msg_controllen = 0;
|
||||||
|
|
||||||
|
mutex_lock(&rslock);
|
||||||
|
ret = kernel_sendmsg(rawsocket, &msg, &iov, 1, pktlen);
|
||||||
|
mutex_unlock(&rslock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_raw6_socket(void) {
|
||||||
|
int ret = 0;
|
||||||
|
ret = sock_create(AF_INET6, SOCK_RAW, IPPROTO_RAW, &raw6socket);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_alert("Unable to create raw socket\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockptr_t optval = {
|
||||||
|
.kernel = NULL,
|
||||||
|
.is_kernel = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
int mark = config.mark;
|
||||||
|
optval.kernel = &mark;
|
||||||
|
ret = sock_setsockopt(raw6socket, SOL_SOCKET, SO_MARK, optval, sizeof(mark));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
pr_alert("setsockopt(SO_MARK, %d) failed\n", mark);
|
||||||
|
goto sr_err;
|
||||||
|
}
|
||||||
|
int one = 1;
|
||||||
|
optval.kernel = &one;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
sr_err:
|
||||||
|
sock_release(raw6socket);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_raw6_socket(void) {
|
||||||
|
sock_release(raw6socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
|
int ret = 0;
|
||||||
|
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
||||||
|
|
||||||
|
struct ip6_hdr *iph;
|
||||||
|
|
||||||
|
if ((ret = ip6_payload_split(
|
||||||
|
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 daddr = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
/* Always 0 for raw socket */
|
||||||
|
.sin6_port = 0,
|
||||||
|
.sin6_addr = iph->ip6_dst
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msghdr msg;
|
||||||
|
struct kvec iov;
|
||||||
|
iov.iov_base = (__u8 *)pkt;
|
||||||
|
iov.iov_len = pktlen;
|
||||||
|
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, 1);
|
||||||
|
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
msg.msg_name = &daddr;
|
||||||
|
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||||
|
msg.msg_control = NULL;
|
||||||
|
msg.msg_controllen = 0;
|
||||||
|
|
||||||
|
mutex_lock(&rs6lock);
|
||||||
|
ret = kernel_sendmsg(raw6socket, &msg, &iov, 1, pktlen);
|
||||||
|
mutex_unlock(&rs6lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (pktlen > AVAILABLE_MTU) {
|
||||||
|
pr_warn("The packet is too big and may cause issues!");
|
||||||
|
|
||||||
|
NETBUF_ALLOC(buff1, MAX_PACKET_SIZE);
|
||||||
|
if (!NETBUF_CHECK(buff1)) {
|
||||||
|
lgerror("Allocation error", -ENOMEM);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
NETBUF_ALLOC(buff2, MAX_PACKET_SIZE);
|
||||||
|
if (!NETBUF_CHECK(buff2)) {
|
||||||
|
lgerror("Allocation error", -ENOMEM);
|
||||||
|
NETBUF_FREE(buff2);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
uint32_t buff1_size = MAX_PACKET_SIZE;
|
||||||
|
uint32_t buff2_size = MAX_PACKET_SIZE;
|
||||||
|
|
||||||
|
switch (config.fragmentation_strategy) {
|
||||||
|
case FRAG_STRAT_TCP:
|
||||||
|
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
||||||
|
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
||||||
|
|
||||||
|
goto erret_lc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FRAG_STRAT_IP:
|
||||||
|
if ((ret = ip4_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
||||||
|
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
||||||
|
|
||||||
|
goto erret_lc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_warn("send_raw_socket: Packet is too big but fragmentation is disabled!");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto erret_lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sent = 0;
|
||||||
|
ret = send_raw_socket(buff1, buff1_size);
|
||||||
|
|
||||||
|
if (ret >= 0) sent += ret;
|
||||||
|
else {
|
||||||
|
goto erret_lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = send_raw_socket(buff2, buff2_size);
|
||||||
|
if (ret >= 0) sent += ret;
|
||||||
|
else {
|
||||||
|
goto erret_lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
NETBUF_FREE(buff1);
|
||||||
|
NETBUF_FREE(buff2);
|
||||||
|
return sent;
|
||||||
|
erret_lc:
|
||||||
|
NETBUF_FREE(buff1);
|
||||||
|
NETBUF_FREE(buff2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipvx = netproto_version(pkt, pktlen);
|
||||||
|
|
||||||
|
if (ipvx == IP4VERSION)
|
||||||
|
return send_raw_ipv4(pkt, pktlen);
|
||||||
|
|
||||||
|
else if (ipvx == IP6VERSION)
|
||||||
|
return send_raw_ipv6(pkt, pktlen);
|
||||||
|
|
||||||
|
printf("proto version %d is unsupported\n", ipvx);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms) {
|
||||||
|
pr_warn("delay_packet_send won't work on current youtubeUnblock version");
|
||||||
|
send_raw_socket(data, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct instance_config_t instance_config = {
|
||||||
|
.send_raw_packet = send_raw_socket,
|
||||||
|
.send_delayed_packet = delay_packet_send,
|
||||||
|
};
|
14
kmod_utils.h
Normal file
14
kmod_utils.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#ifndef KMOD_UTILS_H
|
||||||
|
#define KMOD_UTILS_H
|
||||||
|
|
||||||
|
int open_raw_socket(void);
|
||||||
|
void close_raw_socket(void);
|
||||||
|
int open_raw6_socket(void);
|
||||||
|
void close_raw6_socket(void);
|
||||||
|
int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen);
|
||||||
|
int send_raw_socket(const uint8_t *pkt, uint32_t pktlen);
|
||||||
|
void delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms);
|
||||||
|
|
||||||
|
#endif /* KMOD_UTILS_H */
|
10
mangle.c
10
mangle.c
@ -56,7 +56,7 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
return process_tcp_packet(raw_payload, raw_payload_len);
|
return process_tcp_packet(raw_payload, raw_payload_len);
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
return process_udp4_packet(raw_payload, raw_payload_len);
|
return process_udp_packet(raw_payload, raw_payload_len);
|
||||||
default:
|
default:
|
||||||
goto accept;
|
goto accept;
|
||||||
}
|
}
|
||||||
@ -290,15 +290,15 @@ drop:
|
|||||||
return PKT_DROP;
|
return PKT_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_udp4_packet(const uint8_t *pkt, uint32_t pktlen) {
|
int process_udp_packet(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
const struct iphdr *iph;
|
const void *iph;
|
||||||
uint32_t iph_len;
|
uint32_t iph_len;
|
||||||
const struct udphdr *udph;
|
const struct udphdr *udph;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint32_t dlen;
|
uint32_t dlen;
|
||||||
|
|
||||||
int ret = udp4_payload_split((uint8_t *)pkt, pktlen,
|
int ret = udp_payload_split((uint8_t *)pkt, pktlen,
|
||||||
(struct iphdr **)&iph, &iph_len,
|
(void **)&iph, &iph_len,
|
||||||
(struct udphdr **)&udph,
|
(struct udphdr **)&udph,
|
||||||
(uint8_t **)&data, &dlen);
|
(uint8_t **)&data, &dlen);
|
||||||
|
|
||||||
|
2
mangle.h
2
mangle.h
@ -53,7 +53,7 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len);
|
|||||||
* Processes the UDP packet.
|
* Processes the UDP packet.
|
||||||
* Returns verdict.
|
* Returns verdict.
|
||||||
*/
|
*/
|
||||||
int process_udp4_packet(const uint8_t *pkt, uint32_t pktlen);
|
int process_udp_packet(const uint8_t *pkt, uint32_t pktlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends fake client hello.
|
* Sends fake client hello.
|
||||||
|
54
utils.c
54
utils.c
@ -277,6 +277,60 @@ int udp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int udp6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
struct udphdr **udph,
|
||||||
|
uint8_t **payload, uint32_t *plen) {
|
||||||
|
struct ip6_hdr *hdr;
|
||||||
|
uint32_t hdr_len;
|
||||||
|
struct udphdr *uhdr;
|
||||||
|
uint32_t uhdr_len;
|
||||||
|
|
||||||
|
uint8_t *ip_ph;
|
||||||
|
uint32_t ip_phlen;
|
||||||
|
|
||||||
|
if (ip6_payload_split(pkt, buflen, &hdr, &hdr_len,
|
||||||
|
&ip_ph, &ip_phlen)){
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
hdr->ip6_nxt != IPPROTO_UDP ||
|
||||||
|
ip_phlen < sizeof(struct udphdr)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uhdr = (struct udphdr *)(ip_ph);
|
||||||
|
if (uhdr->len != 0 && ntohs(uhdr->len) != ip_phlen) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iph) *iph = hdr;
|
||||||
|
if (iph_len) *iph_len = hdr_len;
|
||||||
|
if (udph) *udph = uhdr;
|
||||||
|
if (payload) *payload = ip_ph + sizeof(struct udphdr);
|
||||||
|
if (plen) *plen = ip_phlen - sizeof(struct udphdr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int udp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
void **iph, uint32_t *iph_len,
|
||||||
|
struct udphdr **udph,
|
||||||
|
uint8_t **payload, uint32_t *plen) {
|
||||||
|
int netvers = netproto_version(pkt, buflen);
|
||||||
|
if (netvers == IP4VERSION) {
|
||||||
|
return udp4_payload_split(pkt, buflen, (struct iphdr **)iph, iph_len, udph, payload, plen);
|
||||||
|
} else if (netvers == IP6VERSION) {
|
||||||
|
return udp6_payload_split(pkt, buflen, (struct ip6_hdr **)iph, iph_len, udph, payload, plen);
|
||||||
|
} else {
|
||||||
|
lgerror("Internet Protocol version is unsupported", -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// split packet to two ipv4 fragments.
|
// split packet to two ipv4 fragments.
|
||||||
int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||||
uint8_t *frag1, uint32_t *f1len,
|
uint8_t *frag1, uint32_t *f1len,
|
||||||
|
10
utils.h
10
utils.h
@ -81,6 +81,16 @@ int udp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
struct udphdr **udph,
|
struct udphdr **udph,
|
||||||
uint8_t **payload, uint32_t *plen);
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
int udp6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
struct udphdr **udph,
|
||||||
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
int udp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
void **iph, uint32_t *iph_len,
|
||||||
|
struct udphdr **udph,
|
||||||
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph);
|
void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph);
|
||||||
void ip4_set_checksum(struct iphdr *iph);
|
void ip4_set_checksum(struct iphdr *iph);
|
||||||
void ip6_set_checksum(struct ip6_hdr *iph);
|
void ip6_set_checksum(struct ip6_hdr *iph);
|
||||||
|
Loading…
Reference in New Issue
Block a user