From 00e246a3727501ef01cb9d0d9a938540b60c5214 Mon Sep 17 00:00:00 2001 From: SashaXser <24498484+SashaXser@users.noreply.github.com> Date: Thu, 3 Aug 2023 11:43:18 +0400 Subject: [PATCH] Update goodbyedpi.c --- src/goodbyedpi.c | 1385 ---------------------------------------------- 1 file changed, 1385 deletions(-) diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index 135ec441..4c52ff46 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -1,497 +1,3 @@ -/* - * GoodbyeDPI — Passive DPI blocker and Active DPI circumvention utility. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "windivert.h" -#include "goodbyedpi.h" -#include "utils/repl_str.h" -#include "service.h" -#include "dnsredir.h" -#include "ttltrack.h" -#include "blackwhitelist.h" -#include "fakepackets.h" - -// My mingw installation does not load inet_pton definition for some reason -WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, LPCSTR pStringBuf, PVOID pAddr); - -#define GOODBYEDPI_VERSION "v0.2.2" - -#define die() do { sleep(20); exit(EXIT_FAILURE); } while (0) - -#define MAX_FILTERS 4 - -#define DIVERT_NO_LOCALNETSv4_DST "(" \ - "(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and " \ - "(ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and " \ - "(ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and " \ - "(ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and " \ - "(ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)" \ - ")" -#define DIVERT_NO_LOCALNETSv4_SRC "(" \ - "(ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and " \ - "(ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and " \ - "(ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and " \ - "(ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and " \ - "(ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255)" \ - ")" - -#define DIVERT_NO_LOCALNETSv6_DST "(" \ - "(ipv6.DstAddr > ::1) and " \ - "(ipv6.DstAddr < 2001::0 or ipv6.DstAddr > 2001:1::0) and " \ - "(ipv6.DstAddr < fc00::0 or ipv6.DstAddr > fe00::0) and " \ - "(ipv6.DstAddr < fe80::0 or ipv6.DstAddr > fec0::0) and " \ - "(ipv6.DstAddr < ff00::0 or ipv6.DstAddr > ffff::0)" \ - ")" -#define DIVERT_NO_LOCALNETSv6_SRC "(" \ - "(ipv6.SrcAddr > ::1) and " \ - "(ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr > 2001:1::0) and " \ - "(ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr > fe00::0) and " \ - "(ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr > fec0::0) and " \ - "(ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr > ffff::0)" \ - ")" - -/* #IPID# is a template to find&replace */ -#define IPID_TEMPLATE "#IPID#" -#define MAXPAYLOADSIZE_TEMPLATE "#MAXPAYLOADSIZE#" -#define FILTER_STRING_TEMPLATE \ - "(tcp and !impostor and !loopback " MAXPAYLOADSIZE_TEMPLATE " and " \ - "((inbound and (" \ - "(" \ - "(" \ - "(ipv6 or (ip.Id >= 0x0 and ip.Id <= 0xF) " IPID_TEMPLATE \ - ") and " \ - "tcp.SrcPort == 80 and tcp.Ack" \ - ") or " \ - "((tcp.SrcPort == 80 or tcp.SrcPort == 443) and tcp.Ack and tcp.Syn)" \ - ")" \ - " and (" DIVERT_NO_LOCALNETSv4_SRC " or " DIVERT_NO_LOCALNETSv6_SRC "))) or " \ - "(outbound and " \ - "(tcp.DstPort == 80 or tcp.DstPort == 443) and tcp.Ack and " \ - "(" DIVERT_NO_LOCALNETSv4_DST " or " DIVERT_NO_LOCALNETSv6_DST "))" \ - "))" -#define FILTER_PASSIVE_STRING_TEMPLATE "inbound and ip and tcp and " \ - "!impostor and !loopback and " \ - "((ip.Id <= 0xF and ip.Id >= 0x0) " IPID_TEMPLATE ") and " \ - "(tcp.SrcPort == 443 or tcp.SrcPort == 80) and tcp.Rst and " \ - DIVERT_NO_LOCALNETSv4_SRC - -#define SET_HTTP_FRAGMENT_SIZE_OPTION(fragment_size) do { \ - if (!http_fragment_size) { \ - http_fragment_size = (unsigned int)fragment_size; \ - } \ - else if (http_fragment_size != (unsigned int)fragment_size) { \ - printf( \ - "WARNING: HTTP fragment size is already set to %u, not changing.\n", \ - http_fragment_size \ - ); \ - } \ -} while (0) - -#define TCP_HANDLE_OUTGOING_TTL_PARSE_PACKET_IF() \ - if ((packet_v4 && tcp_handle_outgoing(&ppIpHdr->SrcAddr, &ppIpHdr->DstAddr, \ - ppTcpHdr->SrcPort, ppTcpHdr->DstPort, \ - &tcp_conn_info, 0)) \ - || \ - (packet_v6 && tcp_handle_outgoing(ppIpV6Hdr->SrcAddr, ppIpV6Hdr->DstAddr, \ - ppTcpHdr->SrcPort, ppTcpHdr->DstPort, \ - &tcp_conn_info, 1))) - -#define TCP_HANDLE_OUTGOING_FAKE_PACKET(func) do { \ - should_send_fake = 1; \ - if (do_auto_ttl || ttl_min_nhops) { \ - TCP_HANDLE_OUTGOING_TTL_PARSE_PACKET_IF() { \ - if (do_auto_ttl) { \ - /* If Auto TTL mode */ \ - ttl_of_fake_packet = tcp_get_auto_ttl(tcp_conn_info.ttl, auto_ttl_1, auto_ttl_2, \ - ttl_min_nhops, auto_ttl_max); \ - if (do_tcp_verb) { \ - printf("Connection TTL = %d, Fake TTL = %d\n", tcp_conn_info.ttl, ttl_of_fake_packet); \ - } \ - } \ - else if (ttl_min_nhops) { \ - /* If not Auto TTL mode but --min-ttl is set */ \ - if (!tcp_get_auto_ttl(tcp_conn_info.ttl, 0, 0, ttl_min_nhops, 0)) { \ - /* Send only if nhops >= min_ttl */ \ - should_send_fake = 0; \ - } \ - } \ - } \ - } \ - if (should_send_fake) \ - func(w_filter, &addr, packet, packetLen, packet_v6, \ - ttl_of_fake_packet, do_wrong_chksum, do_wrong_seq); \ -} while (0) - - -static int running_from_service = 0; -static int exiting = 0; -static HANDLE filters[MAX_FILTERS]; -static int filter_num = 0; -static const char http10_redirect_302[] = "HTTP/1.0 302 "; -static const char http11_redirect_302[] = "HTTP/1.1 302 "; -static const char http_host_find[] = "\r\nHost: "; -static const char http_host_replace[] = "\r\nhoSt: "; -static const char http_useragent_find[] = "\r\nUser-Agent: "; -static const char location_http[] = "\r\nLocation: http://"; -static const char connection_close[] = "\r\nConnection: close"; -static const char *http_methods[] = { - "GET ", - "HEAD ", - "POST ", - "PUT ", - "DELETE ", - "CONNECT ", - "OPTIONS ", -}; - -static struct option long_options[] = { - {"port", required_argument, 0, 'z' }, - {"dns-addr", required_argument, 0, 'd' }, - {"dns-port", required_argument, 0, 'g' }, - {"dnsv6-addr", required_argument, 0, '!' }, - {"dnsv6-port", required_argument, 0, '@' }, - {"dns-verb", no_argument, 0, 'v' }, - {"blacklist", required_argument, 0, 'b' }, - {"allow-no-sni",no_argument, 0, ']' }, - {"ip-id", required_argument, 0, 'i' }, - {"set-ttl", required_argument, 0, '$' }, - {"min-ttl", required_argument, 0, '[' }, - {"auto-ttl", optional_argument, 0, '+' }, - {"wrong-chksum",no_argument, 0, '%' }, - {"wrong-seq", no_argument, 0, ')' }, - {"native-frag", no_argument, 0, '*' }, - {"reverse-frag",no_argument, 0, '(' }, - {"max-payload", optional_argument, 0, '|' }, - {0, 0, 0, 0 } -}; - -static char *filter_string = NULL; -static char *filter_passive_string = NULL; - -static void add_filter_str(int proto, int port) { - const char *udp = " or (udp and !impostor and !loopback and " \ - "(udp.SrcPort == %d or udp.DstPort == %d))"; - const char *tcp = " or (tcp and !impostor and !loopback " MAXPAYLOADSIZE_TEMPLATE " and " \ - "(tcp.SrcPort == %d or tcp.DstPort == %d))"; - - char *current_filter = filter_string; - size_t new_filter_size = strlen(current_filter) + - (proto == IPPROTO_UDP ? strlen(udp) : strlen(tcp)) + 16; - char *new_filter = malloc(new_filter_size); - - strcpy(new_filter, current_filter); - if (proto == IPPROTO_UDP) - sprintf(new_filter + strlen(new_filter), udp, port, port); - else - sprintf(new_filter + strlen(new_filter), tcp, port, port); - - filter_string = new_filter; - free(current_filter); -} - -static void add_ip_id_str(int id) { - char *newstr; - const char *ipid = " or ip.Id == %d"; - char *addfilter = malloc(strlen(ipid) + 16); - - sprintf(addfilter, ipid, id); - - newstr = repl_str(filter_string, IPID_TEMPLATE, addfilter); - free(filter_string); - filter_string = newstr; - - newstr = repl_str(filter_passive_string, IPID_TEMPLATE, addfilter); - free(filter_passive_string); - filter_passive_string = newstr; -} - -static void add_maxpayloadsize_str(unsigned short maxpayload) { - char *newstr; - /* 0x47455420 is "GET ", 0x504F5354 is "POST", big endian. */ - const char *maxpayloadsize_str = "and (tcp.PayloadLength ? tcp.PayloadLength < %hu or tcp.Payload32[0] == 0x47455420 or tcp.Payload32[0] == 0x504F5354 : true)"; - char *addfilter = malloc(strlen(maxpayloadsize_str) + 16); - - sprintf(addfilter, maxpayloadsize_str, maxpayload); - - newstr = repl_str(filter_string, MAXPAYLOADSIZE_TEMPLATE, addfilter); - free(filter_string); - filter_string = newstr; -} - -static void finalize_filter_strings() { - char *newstr, *newstr2; - - newstr2 = repl_str(filter_string, IPID_TEMPLATE, ""); - newstr = repl_str(newstr2, MAXPAYLOADSIZE_TEMPLATE, ""); - free(filter_string); - free(newstr2); - filter_string = newstr; - - newstr = repl_str(filter_passive_string, IPID_TEMPLATE, ""); - free(filter_passive_string); - filter_passive_string = newstr; -} - -static char* dumb_memmem(const char* haystack, unsigned int hlen, - const char* needle, unsigned int nlen) -{ - // naive implementation - if (nlen > hlen) return NULL; - size_t i; - for (i=0; i limitValue) { - puts(msg); - exit(EXIT_FAILURE); - } - return (unsigned short int)res; -} - -BYTE atoub(const char *str, const char *msg) { - long unsigned int res = strtoul(str, NULL, 10u); - enum { - limitValue=0xFFu - }; - - if(res > limitValue) { - puts(msg); - exit(EXIT_FAILURE); - } - return (BYTE)res; -} - - -static HANDLE init(char *filter, UINT64 flags) { - LPTSTR errormessage = NULL; - DWORD errorcode = 0; - filter = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, 0, flags); - if (filter != INVALID_HANDLE_VALUE) - return filter; - errorcode = GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorcode, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), - (LPTSTR)&errormessage, 0, NULL); - printf("Error opening filter: %s", errormessage); - LocalFree(errormessage); - if (errorcode == 577) - printf("Windows Server 2016 systems must have secure boot disabled to be " - "able to load WinDivert driver.\n" - "Windows 7 systems must be up-to-date or at least have KB3033929 installed.\n" - "https://www.microsoft.com/en-us/download/details.aspx?id=46078\n\n" - "WARNING! If you see this error on Windows 7, it means your system is horribly " - "outdated and SHOULD NOT BE USED TO ACCESS THE INTERNET!\n" - "Most probably, you don't have security patches installed and anyone in you LAN or " - "public Wi-Fi network can get full access to your computer (MS17-010 and others).\n" - "You should install updates IMMEDIATELY.\n"); - return NULL; -} - -static int deinit(HANDLE handle) { - if (handle) { - WinDivertShutdown(handle, WINDIVERT_SHUTDOWN_BOTH); - WinDivertClose(handle); - return TRUE; - } - return FALSE; -} - -void deinit_all() { - for (int i = 0; i < filter_num; i++) { - deinit(filters[i]); - } -} - -static void sigint_handler(int sig __attribute__((unused))) { - exiting = 1; - deinit_all(); - exit(EXIT_SUCCESS); -} - -static void mix_case(char *pktdata, unsigned int pktlen) { - unsigned int i; - - if (pktlen <= 0) return; - for (i = 0; i < pktlen; i++) { - if (i % 2) { - pktdata[i] = (char) toupper(pktdata[i]); - } - } -} - -static int is_passivedpi_redirect(const char *pktdata, unsigned int pktlen) { - const char *redirect_302 = http11_redirect_302; - const char *location = location_http; - const char *connection = connection_close; - - // Check if this is HTTP 302 redirect using bitwise comparison - if (((*(unsigned int*)pktdata) & 0xFFFFFF) == (*(unsigned int*)redirect_302 & 0xFFFFFF)) { - // Combine the pattern checks into a single search using the KMP algorithm - if (kmp_search(pktdata, pktlen, location, sizeof(location_http)-1) && - kmp_search(pktdata, pktlen, connection, sizeof(connection_close)-1)) { - return TRUE; - } - } - return FALSE; -} - - - -static int find_header_and_get_info(const char *pktdata, unsigned int pktlen, - const char *hdrname, - char **hdrnameaddr, - char **hdrvalueaddr, unsigned int *hdrvaluelen) { - const char *hdr_begin = NULL; - const char *hdr_end = NULL; - - *hdrvaluelen = 0u; - *hdrnameaddr = NULL; - *hdrvalueaddr = NULL; - - // Search for the header using Boyer-Moore algorithm - hdr_begin = boyer_moore_search(pktdata, pktlen, hdrname, strlen(hdrname)); - if (!hdr_begin) { - return FALSE; - } - - // Set header address - *hdrnameaddr = (char*)hdr_begin; - *hdrvalueaddr = (char*)(hdr_begin + strlen(hdrname)); - - // Search for header end (\r\n) using Boyer-Moore algorithm - hdr_end = boyer_moore_search(*hdrvalueaddr, pktlen - (unsigned int)(*hdrvalueaddr - pktdata), "\r\n", 2); - if (hdr_end) { - *hdrvaluelen = (unsigned int)(hdr_end - *hdrvalueaddr); - if (*hdrvaluelen >= 3 && *hdrvaluelen <= HOST_MAXLEN) { - return TRUE; - } - } - - return FALSE; -} - - -/** - * Very crude Server Name Indication (TLS ClientHello hostname) extractor. - */ -static int extract_sni(const char *pktdata, unsigned int pktlen, - char **hostnameaddr, unsigned int *hostnamelen) { - unsigned int ptr = 0; - unsigned const char *d = (unsigned const char *)pktdata; - unsigned const char *hnaddr = 0; - int hnlen = 0; - - // Boyer-Moore algorithm for searching the SNI - while (ptr + 8 < pktlen) { - if (d[ptr+3] - d[ptr+5] == 2 && d[ptr+5] - d[ptr+8] == 3) { - if (ptr + 8 + d[ptr+8] > pktlen) { - return FALSE; - } - hnaddr = &d[ptr+9]; - hnlen = d[ptr+8]; - if (hnlen < 3 || hnlen > HOST_MAXLEN) { - return FALSE; - } - for (int i = 0; i < hnlen; i++) { - if (!((hnaddr[i] >= '0' && hnaddr[i] <= '9') || - (hnaddr[i] >= 'a' && hnaddr[i] <= 'z') || - hnaddr[i] == '.' || hnaddr[i] == '-')) { - return FALSE; - } - } - *hostnameaddr = (char*)hnaddr; - *hostnamelen = (unsigned int)hnlen; - return TRUE; - } - // Calculate the skip distance using the Boyer-Moore algorithm - int skip = 1; - if (d[ptr+8] > 0) { - skip = d[ptr+8]; - } else { - skip = 9; - } - ptr += skip; - } - return FALSE; -} - -static inline void change_window_size(const PWINDIVERT_TCPHDR ppTcpHdr, unsigned int size) { - if (size >= 1 && size <= 0xFFFFu) { - ppTcpHdr->Window = htons((u_short)size); - } -} - -/* HTTP method end without trailing space */ -static const char *find_http_method_end(const char *pkt, unsigned int http_frag, int *is_fragmented) { - static const struct { - char first_char; - int length; - int offset; - } http_methods[] = { - {'G', 3, 0}, - {'P', 4, 0}, - {'H', 4, 0}, - {'O', 7, 0}, - {'D', 6, 0}, - {'T', 5, 0}, - {'C', 7, 0}, - {'E', 2, 1}, - {'S', 2, 1}, - {'A', 2, 1}, - {'N', 2, 1}, - {'L', 2, 1}, - {'R', 4, 1}, - {'O', 6, 1} - }; - - char first_char = *pkt; - int num_methods = sizeof(http_methods) / sizeof(http_methods[0]); - - for (int i = 0; i < num_methods; i++) { - if (http_methods[i].first_char == first_char) { - int length = http_methods[i].length; - int offset = http_methods[i].offset; - - if (strncmp(pkt, pkt + offset, length) == 0) { - if (is_fragmented) { - *is_fragmented = (http_frag == 1 || http_frag == 2); - } - return pkt + length; - } - } - } - - return NULL; -} - - - -/** Fragment and send the packet. - * - * This function cuts off the end of the packet (step=0) or - * the beginning of the packet (step=1) with fragment_size bytes. - */ static void send_native_fragment(HANDLE w_filter, WINDIVERT_ADDRESS addr, char *packet, UINT packetLen, PVOID packet_data, UINT packet_dataLen, int packet_v4, int packet_v6, @@ -554,894 +60,3 @@ static void send_native_fragment(HANDLE w_filter, WINDIVERT_ADDRESS addr, ); memcpy(packet, packet_bak, orig_packetLen); } - - -int main(int argc, char *argv[]) { - static enum packet_type_e { - unknown, - ipv4_tcp, ipv4_tcp_data, ipv4_udp_data, - ipv6_tcp, ipv6_tcp_data, ipv6_udp_data - } packet_type; - int i, should_reinject, should_recalc_checksum = 0; - int sni_ok = 0; - int opt; - int packet_v4, packet_v6; - HANDLE w_filter = NULL; - WINDIVERT_ADDRESS addr; - char packet[MAX_PACKET_SIZE]; - PVOID packet_data; - UINT packetLen; - UINT packet_dataLen; - PWINDIVERT_IPHDR ppIpHdr; - PWINDIVERT_IPV6HDR ppIpV6Hdr; - PWINDIVERT_TCPHDR ppTcpHdr; - PWINDIVERT_UDPHDR ppUdpHdr; - conntrack_info_t dns_conn_info; - tcp_conntrack_info_t tcp_conn_info; - - int do_passivedpi = 0, do_fragment_http = 0, - do_fragment_http_persistent = 0, - do_fragment_http_persistent_nowait = 0, - do_fragment_https = 0, do_host = 0, - do_host_removespace = 0, do_additional_space = 0, - do_http_allports = 0, - do_host_mixedcase = 0, - do_dnsv4_redirect = 0, do_dnsv6_redirect = 0, - do_dns_verb = 0, do_tcp_verb = 0, do_blacklist = 0, - do_allow_no_sni = 0, - do_fake_packet = 0, - do_auto_ttl = 0, - do_wrong_chksum = 0, - do_wrong_seq = 0, - do_native_frag = 0, do_reverse_frag = 0; - unsigned int http_fragment_size = 0; - unsigned int https_fragment_size = 0; - unsigned int current_fragment_size = 0; - unsigned short max_payload_size = 0; - BYTE should_send_fake = 0; - BYTE ttl_of_fake_packet = 0; - BYTE ttl_min_nhops = 0; - BYTE auto_ttl_1 = 0; - BYTE auto_ttl_2 = 0; - BYTE auto_ttl_max = 0; - uint32_t dnsv4_addr = 0; - struct in6_addr dnsv6_addr = {0}; - struct in6_addr dns_temp_addr = {0}; - uint16_t dnsv4_port = htons(53); - uint16_t dnsv6_port = htons(53); - char *host_addr, *useragent_addr, *method_addr; - unsigned int host_len, useragent_len; - int http_req_fragmented; - - char *hdr_name_addr = NULL, *hdr_value_addr = NULL; - unsigned int hdr_value_len; - - // Make sure to search DLLs only in safe path, not in current working dir. - SetDllDirectory(""); - SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT); - - if (!running_from_service) { - running_from_service = 1; - if (service_register(argc, argv)) { - /* We've been called as a service. Register service - * and exit this thread. main() would be called from - * service.c next time. - * - * Note that if service_register() succeedes it does - * not return until the service is stopped. - * That is why we should set running_from_service - * before calling service_register and unset it - * afterwards. - */ - return 0; - } - running_from_service = 0; - } - - if (filter_string == NULL) - filter_string = strdup(FILTER_STRING_TEMPLATE); - if (filter_passive_string == NULL) - filter_passive_string = strdup(FILTER_PASSIVE_STRING_TEMPLATE); - - printf( - "GoodbyeDPI " GOODBYEDPI_VERSION - ": Passive DPI blocker and Active DPI circumvention utility\n" - "https://github.com/ValdikSS/GoodbyeDPI\n\n" - ); - - if (argc == 1) { - /* enable mode -5 by default */ - do_fragment_http = do_fragment_https = 1; - do_reverse_frag = do_native_frag = 1; - http_fragment_size = https_fragment_size = 2; - do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; - do_fake_packet = 1; - do_auto_ttl = 1; - max_payload_size = 1200; - } - - while ((opt = getopt_long(argc, argv, "123456prsaf:e:mwk:n", long_options, NULL)) != -1) { - switch (opt) { - case '1': - do_passivedpi = do_host = do_host_removespace \ - = do_fragment_http = do_fragment_https \ - = do_fragment_http_persistent \ - = do_fragment_http_persistent_nowait = 1; - break; - case '2': - do_passivedpi = do_host = do_host_removespace \ - = do_fragment_http = do_fragment_https \ - = do_fragment_http_persistent \ - = do_fragment_http_persistent_nowait = 1; - https_fragment_size = 40u; - break; - case '3': - do_passivedpi = do_host = do_host_removespace \ - = do_fragment_https = 1; - https_fragment_size = 40u; - break; - case '4': - do_passivedpi = do_host = do_host_removespace = 1; - break; - case '5': - do_fragment_http = do_fragment_https = 1; - do_reverse_frag = do_native_frag = 1; - http_fragment_size = https_fragment_size = 2; - do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; - do_fake_packet = 1; - do_auto_ttl = 1; - max_payload_size = 1200; - break; - case '6': - do_fragment_http = do_fragment_https = 1; - do_reverse_frag = do_native_frag = 1; - http_fragment_size = https_fragment_size = 2; - do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; - do_fake_packet = 1; - do_wrong_seq = 1; - max_payload_size = 1200; - break; - case 'p': - do_passivedpi = 1; - break; - case 'r': - do_host = 1; - break; - case 's': - do_host_removespace = 1; - break; - case 'a': - do_additional_space = 1; - do_host_removespace = 1; - break; - case 'm': - do_host_mixedcase = 1; - break; - case 'f': - do_fragment_http = 1; - SET_HTTP_FRAGMENT_SIZE_OPTION(atousi(optarg, "Fragment size should be in range [0 - 0xFFFF]\n")); - break; - case 'k': - do_fragment_http_persistent = 1; - do_native_frag = 1; - SET_HTTP_FRAGMENT_SIZE_OPTION(atousi(optarg, "Fragment size should be in range [0 - 0xFFFF]\n")); - break; - case 'n': - do_fragment_http_persistent = 1; - do_fragment_http_persistent_nowait = 1; - do_native_frag = 1; - break; - case 'e': - do_fragment_https = 1; - https_fragment_size = atousi(optarg, "Fragment size should be in range [0 - 65535]\n"); - break; - case 'w': - do_http_allports = 1; - break; - case 'z': // --port - /* i is used as a temporary variable here */ - i = atoi(optarg); - if (i <= 0 || i > 65535) { - printf("Port parameter error!\n"); - exit(EXIT_FAILURE); - } - if (i != 80 && i != 443) - add_filter_str(IPPROTO_TCP, i); - i = 0; - break; - case 'i': // --ip-id - /* i is used as a temporary variable here */ - i = atousi(optarg, "IP ID parameter error!\n"); - add_ip_id_str(i); - i = 0; - break; - case 'd': // --dns-addr - if ((inet_pton(AF_INET, optarg, dns_temp_addr.s6_addr) == 1) && - !do_dnsv4_redirect) - { - do_dnsv4_redirect = 1; - if (inet_pton(AF_INET, optarg, &dnsv4_addr) != 1) { - puts("DNS address parameter error!"); - exit(EXIT_FAILURE); - } - add_filter_str(IPPROTO_UDP, 53); - flush_dns_cache(); - break; - } - puts("DNS address parameter error!"); - exit(EXIT_FAILURE); - break; - case '!': // --dnsv6-addr - if ((inet_pton(AF_INET6, optarg, dns_temp_addr.s6_addr) == 1) && - !do_dnsv6_redirect) - { - do_dnsv6_redirect = 1; - if (inet_pton(AF_INET6, optarg, dnsv6_addr.s6_addr) != 1) { - puts("DNS address parameter error!"); - exit(EXIT_FAILURE); - } - add_filter_str(IPPROTO_UDP, 53); - flush_dns_cache(); - break; - } - puts("DNS address parameter error!"); - exit(EXIT_FAILURE); - break; - case 'g': // --dns-port - if (!do_dnsv4_redirect) { - puts("--dns-port should be used with --dns-addr!\n" - "Make sure you use --dns-addr and pass it before " - "--dns-port"); - exit(EXIT_FAILURE); - } - dnsv4_port = atousi(optarg, "DNS port parameter error!"); - if (dnsv4_port != 53) { - add_filter_str(IPPROTO_UDP, dnsv4_port); - } - dnsv4_port = htons(dnsv4_port); - break; - case '@': // --dnsv6-port - if (!do_dnsv6_redirect) { - puts("--dnsv6-port should be used with --dnsv6-addr!\n" - "Make sure you use --dnsv6-addr and pass it before " - "--dnsv6-port"); - exit(EXIT_FAILURE); - } - dnsv6_port = atousi(optarg, "DNS port parameter error!"); - if (dnsv6_port != 53) { - add_filter_str(IPPROTO_UDP, dnsv6_port); - } - dnsv6_port = htons(dnsv6_port); - break; - case 'v': - do_dns_verb = 1; - do_tcp_verb = 1; - break; - case 'b': // --blacklist - do_blacklist = 1; - if (!blackwhitelist_load_list(optarg)) { - printf("Can't load blacklist from file!\n"); - exit(EXIT_FAILURE); - } - break; - case ']': // --allow-no-sni - do_allow_no_sni = 1; - break; - case '$': // --set-ttl - do_auto_ttl = auto_ttl_1 = auto_ttl_2 = auto_ttl_max = 0; - do_fake_packet = 1; - ttl_of_fake_packet = atoub(optarg, "Set TTL parameter error!"); - break; - case '[': // --min-ttl - do_fake_packet = 1; - ttl_min_nhops = atoub(optarg, "Set Minimum TTL number of hops parameter error!"); - break; - case '+': // --auto-ttl - do_fake_packet = 1; - do_auto_ttl = 1; - - if (!optarg && argv[optind] && argv[optind][0] != '-') - optarg = argv[optind]; - - if (optarg) { - char *autottl_copy = strdup(optarg); - if (strchr(autottl_copy, '-')) { - // token "-" found, start X-Y parser - char *autottl_current = strtok(autottl_copy, "-"); - auto_ttl_1 = atoub(autottl_current, "Set Auto TTL parameter error!"); - autottl_current = strtok(NULL, "-"); - if (!autottl_current) { - puts("Set Auto TTL parameter error!"); - exit(EXIT_FAILURE); - } - auto_ttl_2 = atoub(autottl_current, "Set Auto TTL parameter error!"); - autottl_current = strtok(NULL, "-"); - if (!autottl_current) { - puts("Set Auto TTL parameter error!"); - exit(EXIT_FAILURE); - } - auto_ttl_max = atoub(autottl_current, "Set Auto TTL parameter error!"); - } - else { - // single digit parser - auto_ttl_2 = atoub(optarg, "Set Auto TTL parameter error!"); - auto_ttl_1 = auto_ttl_2; - } - free(autottl_copy); - } - break; - case '%': // --wrong-chksum - do_fake_packet = 1; - do_wrong_chksum = 1; - break; - case ')': // --wrong-seq - do_fake_packet = 1; - do_wrong_seq = 1; - break; - case '*': // --native-frag - do_native_frag = 1; - do_fragment_http_persistent = 1; - do_fragment_http_persistent_nowait = 1; - break; - case '(': // --reverse-frag - do_reverse_frag = 1; - do_native_frag = 1; - do_fragment_http_persistent = 1; - do_fragment_http_persistent_nowait = 1; - break; - case '|': // --max-payload - if (!optarg && argv[optind] && argv[optind][0] != '-') - optarg = argv[optind]; - if (optarg) - max_payload_size = atousi(optarg, "Max payload size parameter error!"); - else - max_payload_size = 1200; - break; - default: - puts("Usage: goodbyedpi.exe [OPTION...]\n" - " -p block passive DPI\n" - " -r replace Host with hoSt\n" - " -s remove space between host header and its value\n" - " -a additional space between Method and Request-URI (enables -s, may break sites)\n" - " -m mix Host header case (test.com -> tEsT.cOm)\n" - " -f set HTTP fragmentation to value\n" - " -k enable HTTP persistent (keep-alive) fragmentation and set it to value\n" - " -n do not wait for first segment ACK when -k is enabled\n" - " -e set HTTPS fragmentation to value\n" - " -w try to find and parse HTTP traffic on all processed ports (not only on port 80)\n" - " --port additional TCP port to perform fragmentation on (and HTTP tricks with -w)\n" - " --ip-id handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID).\n" - " --dns-addr redirect UDPv4 DNS requests to the supplied IPv4 address (experimental)\n" - " --dns-port redirect UDPv4 DNS requests to the supplied port (53 by default)\n" - " --dnsv6-addr redirect UDPv6 DNS requests to the supplied IPv6 address (experimental)\n" - " --dnsv6-port redirect UDPv6 DNS requests to the supplied port (53 by default)\n" - " --dns-verb print verbose DNS redirection messages\n" - " --blacklist perform circumvention tricks only to host names and subdomains from\n" - " supplied text file (HTTP Host/TLS SNI).\n" - " This option can be supplied multiple times.\n" - " --allow-no-sni perform circumvention if TLS SNI can't be detected with --blacklist enabled.\n" - " --set-ttl activate Fake Request Mode and send it with supplied TTL value.\n" - " DANGEROUS! May break websites in unexpected ways. Use with care (or --blacklist).\n" - " --auto-ttl [a1-a2-m] activate Fake Request Mode, automatically detect TTL and decrease\n" - " it based on a distance. If the distance is shorter than a2, TTL is decreased\n" - " by a2. If it's longer, (a1; a2) scale is used with the distance as a weight.\n" - " If the resulting TTL is more than m(ax), set it to m.\n" - " Default (if set): --auto-ttl 1-4-10. Also sets --min-ttl 3.\n" - " DANGEROUS! May break websites in unexpected ways. Use with care (or --blacklist).\n" - " --min-ttl minimum TTL distance (128/64 - TTL) for which to send Fake Request\n" - " in --set-ttl and --auto-ttl modes.\n" - " --wrong-chksum activate Fake Request Mode and send it with incorrect TCP checksum.\n" - " May not work in a VM or with some routers, but is safer than set-ttl.\n" - " Could be combined with --set-ttl\n" - " --wrong-seq activate Fake Request Mode and send it with TCP SEQ/ACK in the past.\n" - " --native-frag fragment (split) the packets by sending them in smaller packets, without\n" - " shrinking the Window Size. Works faster (does not slow down the connection)\n" - " and better.\n" - " --reverse-frag fragment (split) the packets just as --native-frag, but send them in the\n" - " reversed order. Works with the websites which could not handle segmented\n" - " HTTPS TLS ClientHello (because they receive the TCP flow \"combined\").\n" - " --max-payload [value] packets with TCP payload data more than [value] won't be processed.\n" - " Use this option to reduce CPU usage by skipping huge amount of data\n" - " (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" - "\n"); - puts("LEGACY modesets:\n" - " -1 -p -r -s -f 2 -k 2 -n -e 2 (most compatible mode)\n" - " -2 -p -r -s -f 2 -k 2 -n -e 40 (better speed for HTTPS yet still compatible)\n" - " -3 -p -r -s -e 40 (better speed for HTTP and HTTPS)\n" - " -4 -p -r -s (best speed)" - "\n" - "Modern modesets (more stable, more compatible, faster):\n" - " -5 -f 2 -e 2 --auto-ttl --reverse-frag --max-payload (this is the default)\n" - " -6 -f 2 -e 2 --wrong-seq --reverse-frag --max-payload\n"); - exit(EXIT_FAILURE); - } - } - - if (!http_fragment_size) - http_fragment_size = 2; - if (!https_fragment_size) - https_fragment_size = 2; - if (!auto_ttl_1) - auto_ttl_1 = 1; - if (!auto_ttl_2) - auto_ttl_2 = 4; - if (do_auto_ttl) { - if (!ttl_min_nhops) - ttl_min_nhops = 3; - if (!auto_ttl_max) - auto_ttl_max = 10; - } - - printf("Block passive: %d\n" /* 1 */ - "Fragment HTTP: %u\n" /* 2 */ - "Fragment persistent HTTP: %u\n" /* 3 */ - "Fragment HTTPS: %u\n" /* 4 */ - "Native fragmentation (splitting): %d\n" /* 5 */ - "Fragments sending in reverse: %d\n" /* 6 */ - "hoSt: %d\n" /* 7 */ - "Host no space: %d\n" /* 8 */ - "Additional space: %d\n" /* 9 */ - "Mix Host: %d\n" /* 10 */ - "HTTP AllPorts: %d\n" /* 11 */ - "HTTP Persistent Nowait: %d\n" /* 12 */ - "DNS redirect: %d\n" /* 13 */ - "DNSv6 redirect: %d\n" /* 14 */ - "Allow missing SNI: %d\n" /* 15 */ - "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 */ - do_passivedpi, /* 1 */ - (do_fragment_http ? http_fragment_size : 0), /* 2 */ - (do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */ - (do_fragment_https ? https_fragment_size : 0), /* 4 */ - do_native_frag, /* 5 */ - do_reverse_frag, /* 6 */ - do_host, /* 7 */ - do_host_removespace, /* 8 */ - do_additional_space, /* 9 */ - do_host_mixedcase, /* 10 */ - do_http_allports, /* 11 */ - do_fragment_http_persistent_nowait, /* 12 */ - do_dnsv4_redirect, /* 13 */ - do_dnsv6_redirect, /* 14 */ - do_allow_no_sni, /* 15 */ - do_auto_ttl ? "auto" : (do_fake_packet ? "fixed" : "disabled"), /* 16 */ - ttl_of_fake_packet, do_auto_ttl ? auto_ttl_1 : 0, do_auto_ttl ? auto_ttl_2 : 0, - do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops, - do_wrong_chksum, /* 17 */ - do_wrong_seq, /* 18 */ - max_payload_size /* 19 */ - ); - - if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) { - puts("\nWARNING: HTTP fragmentation values > 2 are not fully compatible " - "with other options. Please use values <= 2 or disable HTTP fragmentation " - "completely."); - } - - if (do_native_frag && !(do_fragment_http || do_fragment_https)) { - puts("\nERROR: Native fragmentation is enabled but fragment sizes are not set.\n" - "Fragmentation has no effect."); - die(); - } - - if (max_payload_size) - add_maxpayloadsize_str(max_payload_size); - finalize_filter_strings(); - puts("\nOpening filter"); - filter_num = 0; - - if (do_passivedpi) { - /* IPv4 only filter for inbound RST packets with ID [0x0; 0xF] */ - filters[filter_num] = init( - filter_passive_string, - WINDIVERT_FLAG_DROP); - if (filters[filter_num] == NULL) - die(); - filter_num++; - } - - /* - * IPv4 & IPv6 filter for inbound HTTP redirection packets and - * active DPI circumvention - */ - filters[filter_num] = init(filter_string, 0); - - w_filter = filters[filter_num]; - filter_num++; - - for (i = 0; i < filter_num; i++) { - if (filters[i] == NULL) - die(); - } - - printf("Filter activated, GoodbyeDPI is now running!\n"); - signal(SIGINT, sigint_handler); - - while (1) { - if (WinDivertRecv(w_filter, packet, sizeof(packet), &packetLen, &addr)) { - debug("Got %s packet, len=%d!\n", addr.Outbound ? "outbound" : "inbound", - packetLen); - should_reinject = 1; - should_recalc_checksum = 0; - - ppIpHdr = (PWINDIVERT_IPHDR)NULL; - ppIpV6Hdr = (PWINDIVERT_IPV6HDR)NULL; - ppTcpHdr = (PWINDIVERT_TCPHDR)NULL; - ppUdpHdr = (PWINDIVERT_UDPHDR)NULL; - packet_v4 = packet_v6 = 0; - packet_type = unknown; - - // Parse network packet and set it's type - if (WinDivertHelperParsePacket(packet, packetLen, &ppIpHdr, - &ppIpV6Hdr, NULL, NULL, NULL, &ppTcpHdr, &ppUdpHdr, &packet_data, &packet_dataLen, - NULL, NULL)) - { - if (ppIpHdr) { - packet_v4 = 1; - if (ppTcpHdr) { - packet_type = ipv4_tcp; - if (packet_data) { - packet_type = ipv4_tcp_data; - } - } - else if (ppUdpHdr && packet_data) { - packet_type = ipv4_udp_data; - } - } - - else if (ppIpV6Hdr) { - packet_v6 = 1; - if (ppTcpHdr) { - packet_type = ipv6_tcp; - if (packet_data) { - packet_type = ipv6_tcp_data; - } - } - else if (ppUdpHdr && packet_data) { - packet_type = ipv6_udp_data; - } - } - } - - debug("packet_type: %d, packet_v4: %d, packet_v6: %d\n", packet_type, packet_v4, packet_v6); - - if (packet_type == ipv4_tcp_data || packet_type == ipv6_tcp_data) { - //printf("Got parsed packet, len=%d!\n", packet_dataLen); - /* Got a TCP packet WITH DATA */ - - /* Handle INBOUND packet with data and find HTTP REDIRECT in there */ - if (!addr.Outbound && packet_dataLen > 16) { - /* If INBOUND packet with DATA (tcp.Ack) */ - - /* Drop packets from filter with HTTP 30x Redirect */ - if (do_passivedpi && is_passivedpi_redirect(packet_data, packet_dataLen)) { - if (packet_v4) { - //printf("Dropping HTTP Redirect packet!\n"); - should_reinject = 0; - } - else if (packet_v6 && WINDIVERT_IPV6HDR_GET_FLOWLABEL(ppIpV6Hdr) == 0x0) { - /* Contrary to IPv4 where we get only packets with IP ID 0x0-0xF, - * for IPv6 we got all the incoming data packets since we can't - * filter them in a driver. - * - * Handle only IPv6 Flow Label == 0x0 for now - */ - //printf("Dropping HTTP Redirect packet!\n"); - should_reinject = 0; - } - } - } - /* Handle OUTBOUND packet on port 443, search for something that resembles - * TLS handshake, send fake request. - */ - else if (addr.Outbound && - ((do_fragment_https ? packet_dataLen == https_fragment_size : 0) || - packet_dataLen > 16) && - ppTcpHdr->DstPort != htons(80) && - (do_fake_packet || do_native_frag) - ) - { - /** - * In case of Window Size fragmentation=2, we'll receive only 2 byte packet. - * 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)) - { - if (do_blacklist) { - sni_ok = extract_sni(packet_data, packet_dataLen, - &host_addr, &host_len); - } - if ( - (do_blacklist && sni_ok && - blackwhitelist_check_hostname(host_addr, host_len) - ) || - (do_blacklist && !sni_ok && do_allow_no_sni) || - (!do_blacklist) - ) - { -#ifdef DEBUG - char lsni[HOST_MAXLEN + 1] = {0}; - extract_sni(packet_data, packet_dataLen, - &host_addr, &host_len); - memcpy(lsni, host_addr, host_len); - printf("Blocked HTTPS website SNI: %s\n", lsni); -#endif - if (do_fake_packet) { - TCP_HANDLE_OUTGOING_FAKE_PACKET(send_fake_https_request); - } - if (do_native_frag) { - // Signal for native fragmentation code handler - should_recalc_checksum = 1; - } - } - } - } - /* Handle OUTBOUND packet on port 80, search for Host header */ - else if (addr.Outbound && - packet_dataLen > 16 && - (do_http_allports ? 1 : (ppTcpHdr->DstPort == htons(80))) && - find_http_method_end(packet_data, - (do_fragment_http ? http_fragment_size : 0u), - &http_req_fragmented) && - (do_host || do_host_removespace || - do_host_mixedcase || do_fragment_http_persistent || - do_fake_packet)) - { - - /* Find Host header */ - if (find_header_and_get_info(packet_data, packet_dataLen, - http_host_find, &hdr_name_addr, &hdr_value_addr, &hdr_value_len) && - hdr_value_len > 0 && hdr_value_len <= HOST_MAXLEN && - (do_blacklist ? blackwhitelist_check_hostname(hdr_value_addr, hdr_value_len) : 1)) - { - host_addr = hdr_value_addr; - host_len = hdr_value_len; -#ifdef DEBUG - char lhost[HOST_MAXLEN + 1] = {0}; - memcpy(lhost, host_addr, host_len); - printf("Blocked HTTP website Host: %s\n", lhost); -#endif - - if (do_native_frag) { - // Signal for native fragmentation code handler - should_recalc_checksum = 1; - } - - if (do_fake_packet) { - TCP_HANDLE_OUTGOING_FAKE_PACKET(send_fake_http_request); - } - - if (do_host_mixedcase) { - mix_case(host_addr, host_len); - should_recalc_checksum = 1; - } - - if (do_host) { - /* Replace "Host: " with "hoSt: " */ - memcpy(hdr_name_addr, http_host_replace, strlen(http_host_replace)); - should_recalc_checksum = 1; - //printf("Replaced Host header!\n"); - } - - /* If removing space between host header and its value - * and adding additional space between Method and Request-URI */ - if (do_additional_space && do_host_removespace) { - /* End of "Host:" without trailing space */ - method_addr = find_http_method_end(packet_data, - (do_fragment_http ? http_fragment_size : 0), - NULL); - - if (method_addr) { - memmove(method_addr + 1, method_addr, - (size_t)(host_addr - method_addr - 1)); - should_recalc_checksum = 1; - } - } - /* If just removing space between host header and its value */ - else if (do_host_removespace) { - if (find_header_and_get_info(packet_data, packet_dataLen, - http_useragent_find, &hdr_name_addr, - &hdr_value_addr, &hdr_value_len)) - { - useragent_addr = hdr_value_addr; - useragent_len = hdr_value_len; - - /* We move Host header value by one byte to the left and then - * "insert" stolen space to the end of User-Agent value because - * some web servers are not tolerant to additional space in the - * end of Host header. - * - * Nothing is done if User-Agent header is missing. - */ - if (useragent_addr && useragent_len > 0) { - /* useragent_addr is in the beginning of User-Agent value */ - - if (useragent_addr > host_addr) { - /* Move one byte to the LEFT from "Host:" - * to the end of User-Agent - */ - memmove(host_addr - 1, host_addr, - (size_t)(useragent_addr + useragent_len - host_addr)); - host_addr -= 1; - /* Put space in the end of User-Agent header */ - *(char*)((unsigned char*)useragent_addr + useragent_len - 1) = ' '; - should_recalc_checksum = 1; - //printf("Replaced Host header!\n"); - } - else { - /* User-Agent goes BEFORE Host header */ - - /* Move one byte to the RIGHT from the end of User-Agent - * to the "Host:" - */ - memmove(useragent_addr + useragent_len + 1, - useragent_addr + useragent_len, - (size_t)(host_addr - 1 - (useragent_addr + useragent_len))); - /* Put space in the end of User-Agent header */ - *(char*)((unsigned char*)useragent_addr + useragent_len) = ' '; - should_recalc_checksum = 1; - //printf("Replaced Host header!\n"); - } - } /* if (host_len <= HOST_MAXLEN && useragent_addr) */ - } /* if (find_header_and_get_info http_useragent) */ - } /* else if (do_host_removespace) */ - } /* if (find_header_and_get_info http_host) */ - } /* Handle OUTBOUND packet with data */ - - /* - * should_recalc_checksum mean we have detected a packet to handle and - * modified it in some way. - * Handle native fragmentation here, incl. sending the packet. - */ - if (should_reinject && should_recalc_checksum && do_native_frag) - { - current_fragment_size = 0; - if (do_fragment_http && ppTcpHdr->DstPort == htons(80)) { - current_fragment_size = http_fragment_size; - } - else if (do_fragment_https && ppTcpHdr->DstPort != htons(80)) { - current_fragment_size = https_fragment_size; - } - - if (current_fragment_size) { - send_native_fragment(w_filter, addr, packet, packetLen, packet_data, - packet_dataLen,packet_v4, packet_v6, - ppIpHdr, ppIpV6Hdr, ppTcpHdr, - current_fragment_size, do_reverse_frag); - - send_native_fragment(w_filter, addr, packet, packetLen, packet_data, - packet_dataLen,packet_v4, packet_v6, - ppIpHdr, ppIpV6Hdr, ppTcpHdr, - current_fragment_size, !do_reverse_frag); - continue; - } - } - } /* Handle TCP packet with data */ - - /* Else if we got TCP packet without data */ - else if (packet_type == ipv4_tcp || packet_type == ipv6_tcp) { - /* If we got INBOUND SYN+ACK packet */ - if (!addr.Outbound && - ppTcpHdr->Syn == 1 && ppTcpHdr->Ack == 1) { - //printf("Changing Window Size!\n"); - /* - * Window Size is changed even if do_fragment_http_persistent - * is enabled as there could be non-HTTP data on port 80 - */ - - if (do_fake_packet && (do_auto_ttl || ttl_min_nhops)) { - if (!((packet_v4 && tcp_handle_incoming(&ppIpHdr->SrcAddr, &ppIpHdr->DstAddr, - ppTcpHdr->SrcPort, ppTcpHdr->DstPort, - 0, ppIpHdr->TTL)) - || - (packet_v6 && tcp_handle_incoming((uint32_t*)&ppIpV6Hdr->SrcAddr, - (uint32_t*)&ppIpV6Hdr->DstAddr, - ppTcpHdr->SrcPort, ppTcpHdr->DstPort, - 1, ppIpV6Hdr->HopLimit)))) - { - if (do_tcp_verb) - puts("[TCP WARN] Can't add TCP connection record."); - } - } - - if (!do_native_frag) { - if (do_fragment_http && ppTcpHdr->SrcPort == htons(80)) { - change_window_size(ppTcpHdr, http_fragment_size); - should_recalc_checksum = 1; - } - else if (do_fragment_https && ppTcpHdr->SrcPort != htons(80)) { - change_window_size(ppTcpHdr, https_fragment_size); - should_recalc_checksum = 1; - } - } - } - } - - /* Else if we got UDP packet with data */ - else if ((do_dnsv4_redirect && (packet_type == ipv4_udp_data)) || - (do_dnsv6_redirect && (packet_type == ipv6_udp_data))) - { - if (!addr.Outbound) { - if ((packet_v4 && dns_handle_incoming(&ppIpHdr->DstAddr, ppUdpHdr->DstPort, - packet_data, packet_dataLen, - &dns_conn_info, 0)) - || - (packet_v6 && dns_handle_incoming(ppIpV6Hdr->DstAddr, ppUdpHdr->DstPort, - packet_data, packet_dataLen, - &dns_conn_info, 1))) - { - /* Changing source IP and port to the values - * from DNS conntrack */ - if (packet_v4) - ppIpHdr->SrcAddr = dns_conn_info.dstip[0]; - else if (packet_v6) - ipv6_copy_addr(ppIpV6Hdr->SrcAddr, dns_conn_info.dstip); - ppUdpHdr->DstPort = dns_conn_info.srcport; - ppUdpHdr->SrcPort = dns_conn_info.dstport; - should_recalc_checksum = 1; - } - else { - if (dns_is_dns_packet(packet_data, packet_dataLen, 0)) - should_reinject = 0; - - if (do_dns_verb && !should_reinject) { - printf("[DNS] Error handling incoming packet: srcport = %hu, dstport = %hu\n", - ntohs(ppUdpHdr->SrcPort), ntohs(ppUdpHdr->DstPort)); - } - } - } - - else if (addr.Outbound) { - if ((packet_v4 && dns_handle_outgoing(&ppIpHdr->SrcAddr, ppUdpHdr->SrcPort, - &ppIpHdr->DstAddr, ppUdpHdr->DstPort, - packet_data, packet_dataLen, 0)) - || - (packet_v6 && dns_handle_outgoing(ppIpV6Hdr->SrcAddr, ppUdpHdr->SrcPort, - ppIpV6Hdr->DstAddr, ppUdpHdr->DstPort, - packet_data, packet_dataLen, 1))) - { - /* Changing destination IP and port to the values - * from configuration */ - if (packet_v4) { - ppIpHdr->DstAddr = dnsv4_addr; - ppUdpHdr->DstPort = dnsv4_port; - } - else if (packet_v6) { - ipv6_copy_addr(ppIpV6Hdr->DstAddr, (uint32_t*)dnsv6_addr.s6_addr); - ppUdpHdr->DstPort = dnsv6_port; - } - should_recalc_checksum = 1; - } - else { - if (dns_is_dns_packet(packet_data, packet_dataLen, 1)) - should_reinject = 0; - - if (do_dns_verb && !should_reinject) { - printf("[DNS] Error handling outgoing packet: srcport = %hu, dstport = %hu\n", - ntohs(ppUdpHdr->SrcPort), ntohs(ppUdpHdr->DstPort)); - } - } - } - } - - if (should_reinject) { - //printf("Re-injecting!\n"); - if (should_recalc_checksum) { - WinDivertHelperCalcChecksums(packet, packetLen, &addr, (UINT64)0LL); - } - WinDivertSend(w_filter, packet, packetLen, NULL, &addr); - } - } - else { - // error, ignore - if (!exiting) - printf("Error receiving packet!\n"); - break; - } - } -}