mirror of
https://github.com/ValdikSS/GoodbyeDPI.git
synced 2025-12-17 12:54:36 +03:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4d0ba1297 | ||
|
|
d6c2b825aa | ||
|
|
aad03f2e4a | ||
|
|
a028cb01f4 | ||
|
|
38b1ff1a92 | ||
|
|
3bd92d67ac | ||
|
|
464bbcbb6b | ||
|
|
50e70ace76 | ||
|
|
135c97ae69 | ||
|
|
c377119136 | ||
|
|
185a0e0211 | ||
|
|
aa28d3e12a | ||
|
|
dc4d0a36d9 | ||
|
|
cc770d302c | ||
|
|
2e23d93762 | ||
|
|
14ae107b53 | ||
|
|
1bdfbb8c45 | ||
|
|
5eddb5f18a | ||
|
|
f638e23ab6 | ||
|
|
bb8fc64f18 | ||
|
|
490525387d |
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
37
Makefile
37
Makefile
@@ -1,37 +0,0 @@
|
||||
ifndef MSYSTEM
|
||||
CPREFIX = x86_64-w64-mingw32-
|
||||
endif
|
||||
|
||||
WINDIVERTHEADERS = ../../include
|
||||
WINDIVERTLIBS = ../binary
|
||||
|
||||
TARGET = goodbyedpi.exe
|
||||
LIBS = -L$(WINDIVERTLIBS) -lWinDivert -lws2_32
|
||||
CC = $(CPREFIX)gcc
|
||||
CCWINDRES = $(CPREFIX)windres
|
||||
CFLAGS = -Wall -Wextra -I$(WINDIVERTHEADERS) -L$(WINDIVERTLIBS) \
|
||||
-O2 -pie -fPIE -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2
|
||||
LDFLAGS = -Wl,-O1,--sort-common,--as-needed
|
||||
|
||||
.PHONY: default all clean
|
||||
|
||||
default: manifest $(TARGET)
|
||||
all: default
|
||||
|
||||
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c)) goodbyedpi-rc.o
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
%.o: %.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
manifest:
|
||||
$(CCWINDRES) goodbyedpi-rc.rc goodbyedpi-rc.o
|
||||
|
||||
.PRECIOUS: $(TARGET) $(OBJECTS)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(OBJECTS) -Wall $(LDFLAGS) $(LIBS) -s -o $@
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
-rm -f $(TARGET)
|
||||
29
README.md
29
README.md
@@ -23,12 +23,16 @@ Usage: goodbyedpi.exe [OPTION...]
|
||||
-e [value] set HTTPS fragmentation to value
|
||||
-a additional space between Method and Request-URI (enables -s, may break sites)
|
||||
-w try to find and parse HTTP traffic on all processed ports (not only on port 80)
|
||||
--port [value] additional TCP port to perform fragmentation on (and HTTP tricks with -w)
|
||||
--dns-addr [value] redirect UDP DNS requests to the supplied IP address (experimental)
|
||||
--dns-port [value] redirect UDP DNS requests to the supplied port (53 by default)
|
||||
--dns-verb print verbose DNS redirection messages
|
||||
--blacklist [txtfile] perform HTTP tricks only to host names and subdomains from
|
||||
supplied text file. This option can be supplied multiple times.
|
||||
--port [value] additional TCP port to perform fragmentation on (and HTTP tricks with -w)
|
||||
--ip-id [value] handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID).
|
||||
This option can be supplied multiple times.
|
||||
--dns-addr [value] redirect UDP DNS requests to the supplied IP address (experimental)
|
||||
--dns-port [value] redirect UDP DNS requests to the supplied port (53 by default)
|
||||
--dnsv6-addr [value] redirect UDPv6 DNS requests to the supplied IPv6 address (experimental)
|
||||
--dnsv6-port [value] redirect UDPv6 DNS requests to the supplied port (53 by default)
|
||||
--dns-verb print verbose DNS redirection messages
|
||||
--blacklist [txtfile] perform HTTP tricks only to host names and subdomains from
|
||||
supplied text file. This option can be supplied multiple times.
|
||||
|
||||
-1 -p -r -s -f 2 -k 2 -n -e 2 (most compatible mode, default)
|
||||
-2 -p -r -s -f 2 -k 2 -n -e 40 (better speed for HTTPS yet still compatible)
|
||||
@@ -48,11 +52,11 @@ Use `goodbyedpi.exe -4` if it works for your ISP's DPI. This is the fastest mode
|
||||
|
||||
### Passive DPI
|
||||
|
||||
Most Passive DPI send HTTP 302 Redirect if you try to access blocked website over HTTP and TCP Reset in case of HTTPS, faster than destination website. Packets sent by DPI always have IP Identification field equal to `0x0000` or `0x0001`, as seen with Russian providers. These packets, if they redirect you to another website (censorship page), are blocked by GoodbyeDPI.
|
||||
Most Passive DPI send HTTP 302 Redirect if you try to access blocked website over HTTP and TCP Reset in case of HTTPS, faster than destination website. Packets sent by DPI usually have IP Identification field equal to `0x0000` or `0x0001`, as seen with Russian providers. These packets, if they redirect you to another website (censorship page), are blocked by GoodbyeDPI.
|
||||
|
||||
### Active DPI
|
||||
|
||||
Active DPI is more tricky to fool. Currently the software uses 4 methods to circumvent Active DPI:
|
||||
Active DPI is more tricky to fool. Currently the software uses 6 methods to circumvent Active DPI:
|
||||
|
||||
* TCP-level fragmentation for first data packet
|
||||
* TCP-level fragmentation for persistent (keep-alive) HTTP sessions
|
||||
@@ -75,13 +79,20 @@ To build x86 exe run:
|
||||
|
||||
And for x86_64:
|
||||
|
||||
`make CPREFIX=x86_64-w64-mingw32- WINDIVERTHEADERS=/path/to/windivert/include WINDIVERTLIBS=/path/to/windivert/amd64`
|
||||
`make CPREFIX=x86_64-w64-mingw32- BIT64=1 WINDIVERTHEADERS=/path/to/windivert/include WINDIVERTLIBS=/path/to/windivert/amd64`
|
||||
|
||||
# How to install as Windows Service
|
||||
|
||||
Use `service_install_russia_blacklist.cmd`, `service_install_russia_blacklist_dnsredir.cmd` and `service_remove.cmd` scripts.
|
||||
Modify them according to your own needs.
|
||||
|
||||
# Known issues
|
||||
|
||||
* Horribly outdated Windows 7 installations are not able to load WinDivert driver due to missing support for SHA256 digital signatures. Install [KB3033929](https://www.microsoft.com/en-us/download/details.aspx?id=46078), or better, update the whole system using Windows Update.
|
||||
* DNS redirection doesn't work with MalwareBytes Web Protection enabled. Bug: [#53](https://github.com/ValdikSS/GoodbyeDPI/issues/53).
|
||||
* Some SSL/TLS stacks unable to process fragmented ClientHello packets, and HTTPS websites won't open. Bug: [#4](https://github.com/ValdikSS/GoodbyeDPI/issues/4), [#64](https://github.com/ValdikSS/GoodbyeDPI/issues/64).
|
||||
|
||||
|
||||
# Similar projects
|
||||
|
||||
[zapret](https://github.com/bol-van/zapret) by @bol-van (for Linux).
|
||||
|
||||
50
src/Makefile
Normal file
50
src/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
ifndef MSYSTEM
|
||||
CPREFIX = x86_64-w64-mingw32-
|
||||
endif
|
||||
|
||||
WINDIVERTHEADERS = ../../../include
|
||||
WINDIVERTLIBS = ../../binary
|
||||
MINGWLIB = /usr/x86_64-w64-mingw32/lib/
|
||||
|
||||
TARGET = goodbyedpi.exe
|
||||
# Linking SSP does not work for some reason, the executable doesn't start.
|
||||
#LIBS = -L$(WINDIVERTLIBS) -Wl,-Bstatic -lssp -Wl,-Bdynamic -lWinDivert -lws2_32
|
||||
LIBS = -L$(WINDIVERTLIBS) -lWinDivert -lws2_32
|
||||
CC = $(CPREFIX)gcc
|
||||
CCWINDRES = $(CPREFIX)windres
|
||||
CFLAGS = -std=c99 -pie -fPIE -pipe -I$(WINDIVERTHEADERS) -L$(WINDIVERTLIBS) \
|
||||
-O2 -D_FORTIFY_SOURCE=2 \
|
||||
-Wall -Wextra -Wpedantic -Wformat=2 -Wshadow -Wstrict-aliasing=1 -Werror=format-security \
|
||||
-Wfloat-equal -Wcast-align -Wsign-conversion \
|
||||
#-fstack-protector-strong
|
||||
LDFLAGS = -Wl,-O1,-pie,--dynamicbase,--nxcompat,--sort-common,--as-needed \
|
||||
-Wl,--image-base,0x140000000 -Wl,--disable-auto-image-base
|
||||
|
||||
ifdef BIT64
|
||||
LDFLAGS += -Wl,--high-entropy-va -Wl,--pic-executable,-e,mainCRTStartup
|
||||
else
|
||||
LDFLAGS += -Wl,--pic-executable,-e,_mainCRTStartup
|
||||
endif
|
||||
|
||||
.PHONY: default all clean
|
||||
|
||||
default: manifest $(TARGET)
|
||||
all: default
|
||||
|
||||
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c utils/*.c)) goodbyedpi-rc.o
|
||||
HEADERS = $(wildcard *.h utils/*.h)
|
||||
|
||||
%.o: %.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
manifest:
|
||||
$(CCWINDRES) goodbyedpi-rc.rc goodbyedpi-rc.o
|
||||
|
||||
.PRECIOUS: $(TARGET) $(OBJECTS)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -s -o $@
|
||||
|
||||
clean:
|
||||
-rm -f *.o utils/*.o
|
||||
-rm -f $(TARGET)
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "goodbyedpi.h"
|
||||
#include "uthash.h"
|
||||
#include "getline.h"
|
||||
#include "utils/uthash.h"
|
||||
#include "utils/getline.h"
|
||||
|
||||
typedef struct blackwhitelist_record {
|
||||
const char *host;
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <stdio.h>
|
||||
#include "goodbyedpi.h"
|
||||
#include "dnsredir.h"
|
||||
#include "uthash.h"
|
||||
#include "utils/uthash.h"
|
||||
|
||||
/* key ('4' for IPv4 or '6' for IPv6 + srcip[16] + srcport[2]) */
|
||||
#define UDP_CONNRECORD_KEY_LEN 19
|
||||
@@ -239,6 +239,6 @@ int dns_handle_incoming(const uint32_t srcip[4], const uint16_t srcport,
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
debug("____dns_handle_incoming FALSE: srcport = %hu, dstport = %hu\n", ntohs(srcport), ntohs(dstport));
|
||||
debug("____dns_handle_incoming FALSE: srcport = %hu\n", ntohs(srcport));
|
||||
return FALSE;
|
||||
}
|
||||
@@ -13,15 +13,15 @@
|
||||
#include <ws2tcpip.h>
|
||||
#include "windivert.h"
|
||||
#include "goodbyedpi.h"
|
||||
#include "utils/repl_str.h"
|
||||
#include "service.h"
|
||||
#include "dnsredir.h"
|
||||
#include "blackwhitelist.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 die() do { printf("Something went wrong!\n" \
|
||||
"Make sure you're running this program with administrator privileges\n"); \
|
||||
sleep(10); exit(EXIT_FAILURE); } while (0)
|
||||
#define die() do { sleep(20); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#define MAX_FILTERS 4
|
||||
#define MAX_PACKET_SIZE 9016
|
||||
@@ -56,6 +56,30 @@ WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, LPCSTR pStringBuf, PVOID pA
|
||||
"(ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr > ffff::0)" \
|
||||
")"
|
||||
|
||||
/* #IPID# is a template to find&replace */
|
||||
#define IPID_TEMPLATE "#IPID#"
|
||||
#define FILTER_STRING_TEMPLATE \
|
||||
"(tcp and !impostor and !loopback 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) { \
|
||||
if (fragment_size <= 0 || fragment_size > 65535) { \
|
||||
@@ -100,28 +124,18 @@ static struct option long_options[] = {
|
||||
{"dnsv6-port", required_argument, 0, '@' },
|
||||
{"dns-verb", no_argument, 0, 'v' },
|
||||
{"blacklist", required_argument, 0, 'b' },
|
||||
{"ip-id", required_argument, 0, 'i' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static char *filter_string = NULL;
|
||||
static char *filter_string_template = "(tcp and "
|
||||
"(inbound and ("
|
||||
"("
|
||||
"("
|
||||
"(ip.Id >= 0x0 and ip.Id <= 0xF) 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 "))"
|
||||
"))";
|
||||
static char *filter_passive_string = NULL;
|
||||
|
||||
static void add_filter_str(int proto, int port) {
|
||||
const char *udp = " or (udp and (udp.SrcPort == %d or udp.DstPort == %d))";
|
||||
const char *tcp = " or (tcp and (tcp.SrcPort == %d or tcp.DstPort == %d))";
|
||||
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 and " \
|
||||
"(tcp.SrcPort == %d or tcp.DstPort == %d))";
|
||||
|
||||
char *current_filter = filter_string;
|
||||
int new_filter_size = strlen(current_filter) +
|
||||
@@ -138,6 +152,34 @@ static void add_filter_str(int proto, int port) {
|
||||
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 finalize_filter_strings() {
|
||||
char *newstr;
|
||||
|
||||
newstr = repl_str(filter_string, IPID_TEMPLATE, "");
|
||||
free(filter_string);
|
||||
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, int hlen, const char* needle, int nlen) {
|
||||
// naive implementation
|
||||
if (nlen > hlen) return NULL;
|
||||
@@ -152,15 +194,27 @@ static char* dumb_memmem(const char* haystack, int hlen, const char* needle, int
|
||||
|
||||
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, GetLastError(), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
|
||||
NULL, errorcode, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&errormessage, 0, NULL);
|
||||
puts(errormessage);
|
||||
free(errormessage);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -300,8 +354,8 @@ int main(int argc, char *argv[]) {
|
||||
do_host_mixedcase = 0,
|
||||
do_dnsv4_redirect = 0, do_dnsv6_redirect = 0,
|
||||
do_dns_verb = 0, do_blacklist = 0;
|
||||
unsigned int http_fragment_size = 2;
|
||||
unsigned int https_fragment_size = 2;
|
||||
unsigned int http_fragment_size = 0;
|
||||
unsigned int https_fragment_size = 0;
|
||||
uint32_t dnsv4_addr = 0;
|
||||
struct in6_addr dnsv6_addr = {0};
|
||||
struct in6_addr dns_temp_addr = {0};
|
||||
@@ -314,6 +368,10 @@ int main(int argc, char *argv[]) {
|
||||
char *hdr_name_addr = NULL, *hdr_value_addr = NULL;
|
||||
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)) {
|
||||
@@ -333,12 +391,18 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (filter_string == NULL)
|
||||
filter_string = strdup(filter_string_template);
|
||||
filter_string = strdup(FILTER_STRING_TEMPLATE);
|
||||
if (filter_passive_string == NULL)
|
||||
filter_passive_string = strdup(FILTER_PASSIVE_STRING_TEMPLATE);
|
||||
|
||||
printf("GoodbyeDPI: Passive DPI blocker and Active DPI circumvention utility\n");
|
||||
printf(
|
||||
"GoodbyeDPI: Passive DPI blocker and Active DPI circumvention utility\n"
|
||||
"https://github.com/ValdikSS/GoodbyeDPI\n\n"
|
||||
);
|
||||
|
||||
if (argc == 1) {
|
||||
/* enable mode -1 by default */
|
||||
http_fragment_size = https_fragment_size = 2;
|
||||
do_passivedpi = do_host = do_host_removespace \
|
||||
= do_fragment_http = do_fragment_https \
|
||||
= do_fragment_http_persistent \
|
||||
@@ -417,6 +481,16 @@ int main(int argc, char *argv[]) {
|
||||
add_filter_str(IPPROTO_TCP, i);
|
||||
i = 0;
|
||||
break;
|
||||
case 'i':
|
||||
/* i is used as a temporary variable here */
|
||||
i = atoi(optarg);
|
||||
if (i < 0 || i > 65535) {
|
||||
printf("IP ID parameter error!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
add_ip_id_str(i);
|
||||
i = 0;
|
||||
break;
|
||||
case 'd':
|
||||
if ((inet_pton(AF_INET, optarg, dns_temp_addr.s6_addr) == 1) &&
|
||||
!do_dnsv4_redirect)
|
||||
@@ -506,6 +580,7 @@ int main(int argc, char *argv[]) {
|
||||
" -e [value] 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 [value] additional TCP port to perform fragmentation on (and HTTP tricks with -w)\n"
|
||||
" --ip-id [value] handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID).\n"
|
||||
" --dns-addr [value] redirect UDPv4 DNS requests to the supplied IPv4 address (experimental)\n"
|
||||
" --dns-port [value] redirect UDPv4 DNS requests to the supplied port (53 by default)\n"
|
||||
" --dnsv6-addr [value] redirect UDPv6 DNS requests to the supplied IPv6 address (experimental)\n"
|
||||
@@ -522,6 +597,11 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!http_fragment_size)
|
||||
http_fragment_size = 2;
|
||||
if (!https_fragment_size)
|
||||
https_fragment_size = 2;
|
||||
|
||||
printf("Block passive: %d, Fragment HTTP: %d, Fragment persistent HTTP: %d, "
|
||||
"Fragment HTTPS: %d, "
|
||||
"hoSt: %d, Host no space: %d, Additional space: %d, Mix Host: %d, "
|
||||
@@ -542,16 +622,16 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
printf("\nOpening filter\n");
|
||||
finalize_filter_strings();
|
||||
filter_num = 0;
|
||||
|
||||
if (do_passivedpi) {
|
||||
/* IPv4 only filter for inbound RST packets with ID = 0 or 1 */
|
||||
/* IPv4 only filter for inbound RST packets with ID [0x0; 0xF] */
|
||||
filters[filter_num] = init(
|
||||
"inbound and ip and tcp and "
|
||||
"(ip.Id >= 0x0000 and ip.Id <= 0x000F) and "
|
||||
"(tcp.SrcPort == 443 or tcp.SrcPort == 80) and tcp.Rst and "
|
||||
DIVERT_NO_LOCALNETSv4_SRC,
|
||||
filter_passive_string,
|
||||
WINDIVERT_FLAG_DROP);
|
||||
if (filters[filter_num] == NULL)
|
||||
die();
|
||||
filter_num++;
|
||||
}
|
||||
|
||||
@@ -630,8 +710,20 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
/* Drop packets from filter with HTTP 30x Redirect */
|
||||
if (do_passivedpi && is_passivedpi_redirect(packet_data, packet_dataLen)) {
|
||||
//printf("Dropping HTTP Redirect packet!\n");
|
||||
should_reinject = 0;
|
||||
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 80, search for Host header */
|
||||
@@ -681,7 +773,7 @@ int main(int argc, char *argv[]) {
|
||||
);
|
||||
|
||||
WinDivertHelperCalcChecksums(
|
||||
packet, packetLen - packet_dataLen + http_fragment_size, 0
|
||||
packet, packetLen - packet_dataLen + http_fragment_size, &addr, 0
|
||||
);
|
||||
WinDivertSend(
|
||||
w_filter, packet,
|
||||
@@ -886,11 +978,7 @@ int main(int argc, char *argv[]) {
|
||||
if (should_reinject) {
|
||||
//printf("Re-injecting!\n");
|
||||
if (should_recalc_checksum) {
|
||||
WinDivertHelperCalcChecksums(packet, packetLen, 0);
|
||||
}
|
||||
else {
|
||||
WinDivertHelperCalcChecksums(packet, packetLen,
|
||||
WINDIVERT_HELPER_NO_REPLACE);
|
||||
WinDivertHelperCalcChecksums(packet, packetLen, &addr, NULL);
|
||||
}
|
||||
WinDivertSend(w_filter, packet, packetLen, &addr, NULL);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="GoodbyeDPI" type="win32"/>
|
||||
<description>Divert</description>
|
||||
<description>GoodbyeDPI</description>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
90
src/utils/repl_str.c
Normal file
90
src/utils/repl_str.c
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if (__STDC_VERSION__ >= 199901L)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
char *repl_str(const char *str, const char *from, const char *to) {
|
||||
|
||||
/* Adjust each of the below values to suit your needs. */
|
||||
|
||||
/* Increment positions cache size initially by this number. */
|
||||
size_t cache_sz_inc = 16;
|
||||
/* Thereafter, each time capacity needs to be increased,
|
||||
* multiply the increment by this factor. */
|
||||
const size_t cache_sz_inc_factor = 3;
|
||||
/* But never increment capacity by more than this number. */
|
||||
const size_t cache_sz_inc_max = 1048576;
|
||||
|
||||
char *pret, *ret = NULL;
|
||||
const char *pstr2, *pstr = str;
|
||||
size_t i, count = 0;
|
||||
#if (__STDC_VERSION__ >= 199901L)
|
||||
uintptr_t *pos_cache_tmp, *pos_cache = NULL;
|
||||
#else
|
||||
ptrdiff_t *pos_cache_tmp, *pos_cache = NULL;
|
||||
#endif
|
||||
size_t cache_sz = 0;
|
||||
size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from);
|
||||
|
||||
/* Find all matches and cache their positions. */
|
||||
while ((pstr2 = strstr(pstr, from)) != NULL) {
|
||||
count++;
|
||||
|
||||
/* Increase the cache size when necessary. */
|
||||
if (cache_sz < count) {
|
||||
cache_sz += cache_sz_inc;
|
||||
pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz);
|
||||
if (pos_cache_tmp == NULL) {
|
||||
goto end_repl_str;
|
||||
} else pos_cache = pos_cache_tmp;
|
||||
cache_sz_inc *= cache_sz_inc_factor;
|
||||
if (cache_sz_inc > cache_sz_inc_max) {
|
||||
cache_sz_inc = cache_sz_inc_max;
|
||||
}
|
||||
}
|
||||
|
||||
pos_cache[count-1] = pstr2 - str;
|
||||
pstr = pstr2 + fromlen;
|
||||
}
|
||||
|
||||
orglen = pstr - str + strlen(pstr);
|
||||
|
||||
/* Allocate memory for the post-replacement string. */
|
||||
if (count > 0) {
|
||||
tolen = strlen(to);
|
||||
retlen = orglen + (tolen - fromlen) * count;
|
||||
} else retlen = orglen;
|
||||
ret = malloc(retlen + 1);
|
||||
if (ret == NULL) {
|
||||
goto end_repl_str;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
/* If no matches, then just duplicate the string. */
|
||||
strcpy(ret, str);
|
||||
} else {
|
||||
/* Otherwise, duplicate the string whilst performing
|
||||
* the replacements using the position cache. */
|
||||
pret = ret;
|
||||
memcpy(pret, str, pos_cache[0]);
|
||||
pret += pos_cache[0];
|
||||
for (i = 0; i < count; i++) {
|
||||
memcpy(pret, to, tolen);
|
||||
pret += tolen;
|
||||
pstr = str + pos_cache[i] + fromlen;
|
||||
cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen;
|
||||
memcpy(pret, pstr, cpylen);
|
||||
pret += cpylen;
|
||||
}
|
||||
ret[retlen] = '\0';
|
||||
}
|
||||
|
||||
end_repl_str:
|
||||
/* Free the cache and return the post-replacement string,
|
||||
* which will be NULL in the event of an error. */
|
||||
free(pos_cache);
|
||||
return ret;
|
||||
}
|
||||
1
src/utils/repl_str.h
Normal file
1
src/utils/repl_str.h
Normal file
@@ -0,0 +1 @@
|
||||
char *repl_str(const char *str, const char *from, const char *to);
|
||||
Reference in New Issue
Block a user