From 9facead353ac21a3000d8f69903e8c8e29fbd749 Mon Sep 17 00:00:00 2001 From: SashaXser <24498484+SashaXser@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:03:22 +0400 Subject: [PATCH] test --- .github/workflows/build.yml | 8 +- src/Makefile | 3 + src/goodbyedpi.c | 611 +++++++++++------------------------- 3 files changed, 198 insertions(+), 424 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index acf27108..277d6325 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,10 +7,10 @@ on: workflow_dispatch: env: - WINDIVERT_URL: https://www.reqrypt.org/download/WinDivert-2.2.0-A.zip - WINDIVERT_NAME: WinDivert-2.2.0-A.zip - WINDIVERT_BASENAME: WinDivert-2.2.0-A - WINDIVERT_SHA256: 2a7630aac0914746fbc565ac862fa096e3e54233883ac52d17c83107496b7a7f + WINDIVERT_URL: https://reqrypt.org/download/WinDivert-2.2.2-A.zip + WINDIVERT_NAME: WinDivert-2.2.2-A.zip + WINDIVERT_BASENAME: WinDivert-2.2.2-A + WINDIVERT_SHA256: 63cb41763bb4b20f600b6de04e991a9c2be73279e317d4d82f237b150c5f3f15 jobs: build: diff --git a/src/Makefile b/src/Makefile index 2ed9ea75..0b9441a9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,6 +12,9 @@ TARGET = goodbyedpi.exe LIBS = -L$(WINDIVERTLIBS) -lWinDivert -lws2_32 -l:libssp.a CC = $(CPREFIX)gcc CCWINDRES = $(CPREFIX)windres +ifeq (, $(shell which $(CPREFIX)windres)) + CCWINDRES = windres +endif CFLAGS = -std=c99 -pie -fPIE -pipe -I$(WINDIVERTHEADERS) -L$(WINDIVERTLIBS) \ -O3 -flto -march=x86-64-v3 -D_FORTIFY_SOURCE=2 -fstack-protector \ -Wall -Wextra -Wpedantic -Wformat=2 -Wformat-overflow=2 -Wformat-truncation=2 \ diff --git a/src/goodbyedpi.c b/src/goodbyedpi.c index fca5bc1d..9517ec92 100644 --- a/src/goodbyedpi.c +++ b/src/goodbyedpi.c @@ -320,7 +320,6 @@ static void mix_case(char *pktdata, unsigned int pktlen) { } } - static int is_passivedpi_redirect(const char *pktdata, unsigned int pktlen) { /* First check if this is HTTP 302 redirect */ if (memcmp(pktdata, http11_redirect_302, sizeof(http11_redirect_302)-1) == 0 || @@ -587,7 +586,6 @@ static void send_native_fragment(HANDLE w_filter, WINDIVERT_ADDRESS addr, } } - int main(int argc, char *argv[]) { static enum packet_type_e { unknown, @@ -693,45 +691,65 @@ int main(int argc, char *argv[]) { max_payload_size = 1200; } + void set_common_flags() { + do_passivedpi = do_host = do_host_removespace = 1; + } + + void set_fragment_flags() { + do_fragment_http = do_fragment_https = 1; + do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; + } + + void set_fragment_sizes(unsigned int size) { + http_fragment_size = https_fragment_size = size; + } + + void handle_dns_addr(const char *optarg) { + 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(); + } else { + puts("DNS address parameter error!"); + exit(EXIT_FAILURE); + } + } + 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; + set_common_flags(); + set_fragment_flags(); 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; + set_common_flags(); + set_fragment_flags(); https_fragment_size = 40u; break; case '3': - do_passivedpi = do_host = do_host_removespace \ - = do_fragment_https = 1; + set_common_flags(); + do_fragment_https = 1; https_fragment_size = 40u; break; case '4': - do_passivedpi = do_host = do_host_removespace = 1; + set_common_flags(); break; case '5': - do_fragment_http = do_fragment_https = 1; + set_fragment_flags(); 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; + set_fragment_sizes(2); + do_fake_packet = do_auto_ttl = 1; max_payload_size = 1200; break; case '6': - do_fragment_http = do_fragment_https = 1; + set_fragment_flags(); 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; + set_fragment_sizes(2); + do_fake_packet = do_wrong_seq = 1; max_payload_size = 1200; break; case 'p': @@ -744,8 +762,7 @@ int main(int argc, char *argv[]) { do_host_removespace = 1; break; case 'a': - do_additional_space = 1; - do_host_removespace = 1; + do_additional_space = do_host_removespace = 1; break; case 'm': do_host_mixedcase = 1; @@ -755,14 +772,11 @@ int main(int argc, char *argv[]) { 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; + do_fragment_http_persistent = 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; + do_fragment_http_persistent = do_fragment_http_persistent_nowait = do_native_frag = 1; break; case 'e': do_fragment_https = 1; @@ -772,7 +786,6 @@ int main(int argc, char *argv[]) { 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"); @@ -783,31 +796,15 @@ int main(int argc, char *argv[]) { 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); + handle_dns_addr(optarg); break; case '!': // --dnsv6-addr - if ((inet_pton(AF_INET6, optarg, dns_temp_addr.s6_addr) == 1) && - !do_dnsv6_redirect) - { + 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!"); @@ -815,16 +812,15 @@ int main(int argc, char *argv[]) { } add_filter_str(IPPROTO_UDP, 53); flush_dns_cache(); - break; + } else { + puts("DNS address parameter error!"); + exit(EXIT_FAILURE); } - 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"); + "Make sure you use --dns-addr and pass it before --dns-port"); exit(EXIT_FAILURE); } dnsv4_port = atousi(optarg, "DNS port parameter error!"); @@ -836,8 +832,7 @@ int main(int argc, char *argv[]) { 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"); + "Make sure you use --dnsv6-addr and pass it before --dnsv6-port"); exit(EXIT_FAILURE); } dnsv6_port = atousi(optarg, "DNS port parameter error!"); @@ -847,8 +842,7 @@ int main(int argc, char *argv[]) { dnsv6_port = htons(dnsv6_port); break; case 'v': - do_dns_verb = 1; - do_tcp_verb = 1; + do_dns_verb = do_tcp_verb = 1; break; case 'b': // --blacklist do_blacklist = 1; @@ -881,9 +875,8 @@ int main(int argc, char *argv[]) { if (optarg) { char *autottl_copy = strdup(optarg); if (strchr(autottl_copy, '-')) { - // token "-" found, start X-Y parser char *autottl_current; - char *saveptr; // declare a pointer to store the state of strtok_r + char *saveptr; autottl_current = strtok_r(autottl_copy, "-", &saveptr); auto_ttl_1 = atoub(autottl_current, "Set Auto TTL parameter error!"); autottl_current = strtok_r(NULL, "-", &saveptr); @@ -898,9 +891,7 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } auto_ttl_max = atoub(autottl_current, "Set Auto TTL parameter error!"); - } - else { - // single digit parser + } else { auto_ttl_2 = atoub(optarg, "Set Auto TTL parameter error!"); auto_ttl_1 = auto_ttl_2; } @@ -908,23 +899,16 @@ int main(int argc, char *argv[]) { } break; case '%': // --wrong-chksum - do_fake_packet = 1; - do_wrong_chksum = 1; + do_fake_packet = do_wrong_chksum = 1; break; case ')': // --wrong-seq - do_fake_packet = 1; - do_wrong_seq = 1; + do_fake_packet = do_wrong_seq = 1; break; case '*': // --native-frag - do_native_frag = 1; - do_fragment_http_persistent = 1; - do_fragment_http_persistent_nowait = 1; + do_native_frag = do_fragment_http_persistent = 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; + do_reverse_frag = do_native_frag = do_fragment_http_persistent = do_fragment_http_persistent_nowait = 1; break; case '|': // --max-payload if (!optarg && argv[optind] && argv[optind][0] != '-') @@ -1097,390 +1081,177 @@ int main(int argc, char *argv[]) { 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; - sni_ok = 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; + void handle_tcp_packet(const WINDIVERT_ADDRESS addr, const UINT8 *packet_data, UINT packet_dataLen, PWINDIVERT_TCPHDR ppTcpHdr, int packet_v4, int packet_v6, int *should_reinject, int *should_recalc_checksum, int *sni_ok) { + if (packet_dataLen > 16) { + if (!addr.Outbound) { + if (do_passivedpi && is_passivedpi_redirect(packet_data, packet_dataLen)) { + if (packet_v4 || (packet_v6 && WINDIVERT_IPV6HDR_GET_FLOWLABEL(ppIpV6Hdr) == 0x0)) { + *should_reinject = 0; } } - - else if (ppIpV6Hdr) { - packet_v6 = 1; - if (ppTcpHdr) { - packet_type = ipv6_tcp; - if (packet_data) { - packet_type = ipv6_tcp_data; - } + } 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)) { + if ((packet_dataLen == 2 && memcmp(packet_data, "\x16\x03", 2) == 0) || (packet_dataLen >= 3 && contains_tls_record_with_client_hello(packet_data, packet_dataLen))) { + if (do_blacklist || do_fragment_by_sni) { + *sni_ok = extract_sni(packet_data, packet_dataLen, &host_addr, &host_len); } - 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; + if ((do_blacklist && *sni_ok && blackwhitelist_check_hostname(host_addr, host_len)) || (do_blacklist && !*sni_ok && do_allow_no_sni) || (!do_blacklist)) { + if (do_fake_packet) { + TCP_HANDLE_OUTGOING_FAKE_PACKET(send_fake_https_request); } - 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; + if (do_native_frag) { + *should_recalc_checksum = 1; } } } - /* 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 && contains_tls_record_with_client_hello(packet_data, packet_dataLen))) - { - if (do_blacklist || do_fragment_by_sni) { - sni_ok = extract_sni(packet_data, packet_dataLen, - &host_addr, &host_len); + } 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)) { + 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; + if (do_native_frag) { + *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) { + memcpy(hdr_name_addr, http_host_replace, strlen(http_host_replace)); + *should_recalc_checksum = 1; + } + if (do_additional_space && do_host_removespace) { + 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 ( - (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; + } 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; + if (useragent_addr && useragent_len > 0) { + if (useragent_addr > host_addr) { + memmove(host_addr - 1, host_addr, (size_t)(useragent_addr + useragent_len - host_addr)); + host_addr -= 1; + *(char*)((unsigned char*)useragent_addr + useragent_len - 1) = ' '; + *should_recalc_checksum = 1; + } else { + memmove(useragent_addr + useragent_len + 1, useragent_addr + useragent_len, (size_t)(host_addr - 1 - (useragent_addr + useragent_len))); + *(char*)((unsigned char*)useragent_addr + useragent_len) = ' '; + *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); - } + void handle_udp_packet(const WINDIVERT_ADDRESS addr, const UINT8 *packet_data, UINT packet_dataLen, PWINDIVERT_UDPHDR ppUdpHdr, int packet_v4, int packet_v6, int *should_reinject, int *should_recalc_checksum) { + 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))) { + 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))) { + 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 (do_host_mixedcase) { - mix_case(host_addr, host_len); - should_recalc_checksum = 1; - } + void parse_packet(UINT8 *packet, UINT packetLen, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpV6Hdr, PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 **packet_data, UINT *packet_dataLen, int *packet_v4, int *packet_v6, int *packet_type) { + *ppIpHdr = NULL; + *ppIpV6Hdr = NULL; + *ppTcpHdr = NULL; + *ppUdpHdr = NULL; + *packet_v4 = *packet_v6 = 0; + *packet_type = unknown; + + 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 = (*packet_data) ? ipv4_tcp_data : ipv4_tcp; + } else if (*ppUdpHdr && *packet_data) { + *packet_type = ipv4_udp_data; + } + } else if (*ppIpV6Hdr) { + *packet_v6 = 1; + if (*ppTcpHdr) { + *packet_type = (*packet_data) ? ipv6_tcp_data : ipv6_tcp; + } else if (*ppUdpHdr && *packet_data) { + *packet_type = ipv6_udp_data; + } + } + } + } - 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"); - } + 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; + sni_ok = 0; - /* 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 == port_80) { - current_fragment_size = http_fragment_size; - } - current_fragment_size = https_fragment_size; - if (do_fragment_by_sni && sni_ok) { - current_fragment_size = (void*)host_addr - packet_data; - } else { - current_fragment_size = https_fragment_size; - } + parse_packet(packet, packetLen, &ppIpHdr, &ppIpV6Hdr, &ppTcpHdr, &ppUdpHdr, &packet_data, &packet_dataLen, &packet_v4, &packet_v6, &packet_type); - 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 */ + debug("packet_type: %d, packet_v4: %d, packet_v6: %d\n", packet_type, packet_v4, packet_v6); - /* 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 (packet_type == ipv4_tcp_data || packet_type == ipv6_tcp_data) { + handle_tcp_packet(addr, packet_data, packet_dataLen, ppTcpHdr, packet_v4, packet_v6, &should_reinject, &should_recalc_checksum, &sni_ok); + } else if (packet_type == ipv4_tcp || packet_type == ipv6_tcp) { 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 (!((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 == port_80) { change_window_size(ppTcpHdr, http_fragment_size); should_recalc_checksum = 1; - } - else if (do_fragment_https && ppTcpHdr->SrcPort != port_80) { + } else if (do_fragment_https && ppTcpHdr->SrcPort != port_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)); - } - } - } + } else if ((do_dnsv4_redirect && (packet_type == ipv4_udp_data)) || (do_dnsv6_redirect && (packet_type == ipv6_udp_data))) { + handle_udp_packet(addr, packet_data, packet_dataLen, ppUdpHdr, packet_v4, packet_v6, &should_reinject, &should_recalc_checksum); } 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"); + } else { + if (!exiting) printf("Error receiving packet!\n"); break; } - } -} \ No newline at end of file +}