From ecc681a60b5e78905495f116d025eb1929419186 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Thu, 21 Jul 2022 14:47:13 +0300 Subject: [PATCH] OpenVPN detection & fragmentation/fake packet support --- src/Makefile | 2 +- src/goodbyedpi.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index d6c7829..c924745 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ CFLAGS = -std=c99 -pie -fPIE -pipe -I$(WINDIVERTHEADERS) -L$(WINDIVERTLIBS) \ -Wnull-dereference -Warray-bounds=2 -Wimplicit-fallthrough=3 \ -Wstringop-overflow=4 \ -Wformat-signedness -Wstrict-overflow=2 -Wcast-align=strict \ - -Wfloat-equal -Wcast-align -Wsign-conversion \ + -Wfloat-equal -Wcast-align -Wsign-conversion -Wno-stringop-overflow -Wno-stringop-overread \ #-fstack-protector-strong LDFLAGS = -fstack-protector -Wl,-O1,-pie,--dynamicbase,--nxcompat,--sort-common,--as-needed \ -Wl,--image-base,0x140000000 -Wl,--disable-auto-image-base diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index 7f54e9e..f149b1e 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -171,6 +171,7 @@ static struct option long_options[] = { {"native-frag", no_argument, 0, '*' }, {"reverse-frag",no_argument, 0, '(' }, {"max-payload", optional_argument, 0, '|' }, + {"openvpn", no_argument, 0, '#' }, {0, 0, 0, 0 } }; @@ -433,6 +434,16 @@ static int extract_sni(const char *pktdata, unsigned int pktlen, return FALSE; } +static inline int is_openvpn_handshake(const char *pktdata, unsigned int pktlen) { + /* + * 0x38 is P_CONTROL_HARD_RESET_CLIENT_V2 + peer_id(0), + * 0x50 is P_CONTROL_HARD_RESET_CLIENT_V3 + peer_id(0) + */ + return pktlen >= 16 + && ntohs(((uint16_t*)pktdata)[0]) == pktlen - 2 + && (pktdata[2] == '\x38' || pktdata[2] == '\x50'); +} + static inline void change_window_size(const PWINDIVERT_TCPHDR ppTcpHdr, unsigned int size) { if (size >= 1 && size <= 0xFFFFu) { ppTcpHdr->Window = htons((u_short)size); @@ -543,6 +554,7 @@ int main(int argc, char *argv[]) { } packet_type; int i, should_reinject, should_recalc_checksum = 0; int sni_ok = 0; + int openvpn_handshake = 0; int opt; int packet_v4, packet_v6; HANDLE w_filter = NULL; @@ -569,6 +581,7 @@ int main(int argc, char *argv[]) { do_dns_verb = 0, do_tcp_verb = 0, do_blacklist = 0, do_allow_no_sni = 0, do_fake_packet = 0, + do_openvpn = 0, do_auto_ttl = 0, do_wrong_chksum = 0, do_wrong_seq = 0, @@ -849,6 +862,9 @@ int main(int argc, char *argv[]) { free(autottl_copy); } break; + case '#': // --openvpn + do_openvpn = 1; + break; case '%': // --wrong-chksum do_fake_packet = 1; do_wrong_chksum = 1; @@ -924,6 +940,7 @@ int main(int argc, char *argv[]) { " (like file transfers) in already established sessions.\n" " May skip some huge HTTP requests from being processed.\n" " Default (if set): --max-payload 1200.\n" + " --openvpn Detect OpenVPN TCP and fragment/send fake packet.\n" "\n"); puts("LEGACY modesets:\n" " -1 -p -r -s -f 2 -k 2 -n -e 2 (most compatible mode)\n" @@ -971,7 +988,8 @@ int main(int argc, char *argv[]) { "Fake requests, TTL: %s (fixed: %hu, auto: %hu-%hu-%hu, min distance: %hu)\n" /* 16 */ "Fake requests, wrong checksum: %d\n" /* 17 */ "Fake requests, wrong SEQ/ACK: %d\n" /* 18 */ - "Max payload size: %hu\n", /* 19 */ + "Max payload size: %hu\n" /* 19 */ + "OpenVPN: %d\n", /* 20 */ do_passivedpi, /* 1 */ (do_fragment_http ? http_fragment_size : 0), /* 2 */ (do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */ @@ -992,7 +1010,8 @@ int main(int argc, char *argv[]) { do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops, do_wrong_chksum, /* 17 */ do_wrong_seq, /* 18 */ - max_payload_size /* 19 */ + max_payload_size, /* 19 */ + do_openvpn /* 20 */ ); if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) { @@ -1119,7 +1138,7 @@ int main(int argc, char *argv[]) { */ else if (addr.Outbound && ((do_fragment_https ? packet_dataLen == https_fragment_size : 0) || - packet_dataLen > 16) && + packet_dataLen >= 16) && ppTcpHdr->DstPort != htons(80) && (do_fake_packet || do_native_frag) ) @@ -1129,7 +1148,9 @@ int main(int argc, char *argv[]) { * But if the packet is more than 2 bytes, check ClientHello byte. */ if ((packet_dataLen == 2 && memcmp(packet_data, "\x16\x03", 2) == 0) || - (packet_dataLen >= 3 && memcmp(packet_data, "\x16\x03\x01", 3) == 0)) + (packet_dataLen >= 3 && memcmp(packet_data, "\x16\x03\x01", 3) == 0) || + (do_openvpn && (openvpn_handshake = is_openvpn_handshake(packet_data, packet_dataLen))) + ) { if (do_blacklist) { sni_ok = extract_sni(packet_data, packet_dataLen, @@ -1140,6 +1161,7 @@ int main(int argc, char *argv[]) { blackwhitelist_check_hostname(host_addr, host_len) ) || (do_blacklist && !sni_ok && do_allow_no_sni) || + (do_openvpn && openvpn_handshake) || (!do_blacklist) ) {