diff --git a/src/Makefile.xtables b/src/Makefile.xtables index 2d7d310..a5800e1 100644 --- a/src/Makefile.xtables +++ b/src/Makefile.xtables @@ -1,6 +1,5 @@ CFLAGS = -O2 -Wall -LIBS = libxt_ts3init_get_cookie.so libxt_ts3init_get_puzzle.so libxt_TS3INIT_RESET.so libxt_TS3INIT_SET_COOKIE.so - +LIBS = libxt_ts3init_get_cookie.so libxt_ts3init_get_puzzle.so libxt_TS3INIT_RESET.so libxt_TS3INIT_SET_COOKIE.so libxt_TS3INIT_MORPH_TO_GET_COOKIE.so all: $(LIBS) clean: diff --git a/src/libxt_TS3INIT_MORPH_TO_GET_COOKIE.c b/src/libxt_TS3INIT_MORPH_TO_GET_COOKIE.c new file mode 100644 index 0000000..fbdb9f5 --- /dev/null +++ b/src/libxt_TS3INIT_MORPH_TO_GET_COOKIE.c @@ -0,0 +1,53 @@ +/* + * "libxt_ts3init_reset" target extension for iptables + * Niels Werensteijn , 2016-10-03 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License; either version 2 + * or 3 of the License, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ts3init_cookie_seed.h" +#include "ts3init_target.h" + +static void ts3init_morph_to_get_cookie_help(void) +{ + printf("TS3INIT_MORPH_TO_GET_COOKIE takes no options\n\n"); +} + +static int ts3init_morph_to_get_cookie_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + return false; +} + +static void ts3init_morph_to_get_cookie_check(unsigned int flags) +{ +} + +/* register and init */ +static struct xtables_target ts3init_morph_to_get_cookie_tg_reg = +{ + .name = "TS3INIT_MORPH_TO_GET_COOKIE", + .revision = 0, + .family = NFPROTO_UNSPEC, + .version = XTABLES_VERSION, + .help = ts3init_morph_to_get_cookie_help, + .parse = ts3init_morph_to_get_cookie_parse, + .final_check = ts3init_morph_to_get_cookie_check, +}; + +static __attribute__((constructor)) void ts3init_morph_to_get_cookie_tg_ldr(void) +{ + xtables_register_target(&ts3init_morph_to_get_cookie_tg_reg); +} \ No newline at end of file diff --git a/src/ts3init_target.c b/src/ts3init_target.c index 6cf0782..c9321f6 100644 --- a/src/ts3init_target.c +++ b/src/ts3init_target.c @@ -20,6 +20,7 @@ #ifdef CONFIG_BRIDGE_NETFILTER # include #endif +#include #include #include #include @@ -378,7 +379,119 @@ static int ts3init_set_cookie_tg_check(const struct xt_tgchk_param *par) } return 0; -} +} + +static inline void +ts3init_fill_get_cookie_payload(u8 *payload) +{ + time_t current_unix_time = ts3init_get_cached_unix_time(); + payload[TS3INIT_HEADER_CLIENT_LENGTH - 1] = COMMAND_GET_COOKIE; + payload[TS3INIT_HEADER_CLIENT_LENGTH + 0] = current_unix_time << 24; + payload[TS3INIT_HEADER_CLIENT_LENGTH + 1] = current_unix_time << 16; + payload[TS3INIT_HEADER_CLIENT_LENGTH + 2] = current_unix_time << 8; + payload[TS3INIT_HEADER_CLIENT_LENGTH + 3] = current_unix_time; + get_random_bytes(&payload[TS3INIT_HEADER_CLIENT_LENGTH + 4], 4); + memset(&payload[TS3INIT_HEADER_CLIENT_LENGTH + 8], 0, 8); +} + +/* + * The 'TS3INIT_MORPH_TO_GET_COOKIE' target handler. + * Morphes the incomming packet into a TS3INIT_GET_COOKIE + */ +static unsigned int +ts3init_morph_to_get_cookie_ipv4_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + struct iphdr *ip; + struct udphdr *udp, udp_buf; + u8 *payload, payload_buf[TS3INIT_HEADER_CLIENT_LENGTH + 16]; + unsigned int data_len; + int length_difference; + + if (!skb_make_writable(skb, 0)) + return NF_DROP; + + ip = ip_hdr(skb); + udp = skb_header_pointer(skb, par->thoff, sizeof(udp_buf), &udp_buf); + if (udp == NULL) + return NF_DROP; + + if (ip->frag_off & htons(IP_OFFSET)) + return NF_DROP; + + data_len = ntohs(udp->len) - sizeof(*udp); + if (data_len < 1 || data_len > 512) + return NF_DROP; + + length_difference = sizeof(payload_buf) - data_len; + if (length_difference > 0) + skb_put(skb, length_difference); + else if (length_difference < 0) + skb_trim(skb, skb->len + length_difference); + + payload = skb_header_pointer(skb, par->thoff + sizeof(udp), sizeof(payload_buf), payload_buf); + ts3init_fill_get_cookie_payload(payload); + + udp->len = htons(sizeof(*udp) + sizeof(payload_buf)); + udp->check = 0; + udp->check = csum_tcpudp_magic(ip->saddr, ip->daddr, + ntohs(udp->len), IPPROTO_UDP, + csum_partial(udp, ntohs(udp->len), 0)); + ip->tot_len = htons(skb->len); + skb->ip_summed = CHECKSUM_NONE; + + if (skb->len > dst_mtu(skb_dst(skb))) + return NF_DROP; + + return NF_ACCEPT; +} + +/* + * The 'TS3INIT_MORPH_TO_GET_COOKIE' target handler. + * Morphes the incomming packet into a TS3INIT_GET_COOKIE + */ +static unsigned int +ts3init_morph_to_get_cookie_ipv6_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + struct ipv6hdr *ip; + struct udphdr *udp, udp_buf; + u8 *payload, payload_buf[TS3INIT_HEADER_CLIENT_LENGTH + 16]; + unsigned int data_len; + int length_difference; + + if (!skb_make_writable(skb, 0)) + return NF_DROP; + + ip = ipv6_hdr(skb); + udp = skb_header_pointer(skb, par->thoff, sizeof(udp_buf), &udp_buf); + if (udp == NULL) + return NF_DROP; + + data_len = ntohs(udp->len) - sizeof(*udp); + if (data_len < 1 || data_len > 512) + return NF_DROP; + + length_difference = sizeof(payload_buf) - data_len; + if (length_difference > 0) + skb_put(skb, length_difference); + else if (length_difference < 0) + skb_trim(skb, skb->len + length_difference); + + payload = skb_header_pointer(skb, par->thoff + sizeof(udp), sizeof(payload_buf), payload_buf); + ts3init_fill_get_cookie_payload(payload); + + udp->len = htons(sizeof(*udp) + sizeof(payload_buf)); + udp->check = 0; + udp->check = csum_ipv6_magic(&ip->saddr, &ip->daddr, + ntohs(udp->len), IPPROTO_UDP, + csum_partial(udp, ntohs(udp->len), 0)); + ip->payload_len = htons(skb->len); + skb->ip_summed = CHECKSUM_NONE; + + if (skb->len > dst_mtu(skb_dst(skb))) + return NF_DROP; + + return NF_ACCEPT; +} static struct xt_target ts3init_tg_reg[] __read_mostly = { { @@ -417,6 +530,22 @@ static struct xt_target ts3init_tg_reg[] __read_mostly = { .checkentry = ts3init_set_cookie_tg_check, .me = THIS_MODULE, }, + { + .name = "TS3INIT_MORPH_TO_GET_COOKIE", + .revision = 0, + .family = NFPROTO_IPV4, + .proto = IPPROTO_UDP, + .target = ts3init_morph_to_get_cookie_ipv4_tg, + .me = THIS_MODULE, + }, + { + .name = "TS3INIT_MORPH_TO_GET_COOKIE", + .revision = 0, + .family = NFPROTO_IPV6, + .proto = IPPROTO_UDP, + .target = ts3init_morph_to_get_cookie_ipv6_tg, + .me = THIS_MODULE, + }, }; int ts3init_target_init(void)