mirror of
https://github.com/ValdikSS/GoodbyeDPI.git
synced 2025-12-17 12:54:36 +03:00
Compare commits
5 Commits
EgorWeders
...
0.2.3rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2784dd79e | ||
|
|
bc95b6f598 | ||
|
|
985a09c73d | ||
|
|
15793fb84f | ||
|
|
f0d42129aa |
@@ -64,6 +64,13 @@ Usage: goodbyedpi.exe [OPTION...]
|
|||||||
--reverse-frag fragment (split) the packets just as --native-frag, but send them in the
|
--reverse-frag fragment (split) the packets just as --native-frag, but send them in the
|
||||||
reversed order. Works with the websites which could not handle segmented
|
reversed order. Works with the websites which could not handle segmented
|
||||||
HTTPS TLS ClientHello (because they receive the TCP flow "combined").
|
HTTPS TLS ClientHello (because they receive the TCP flow "combined").
|
||||||
|
--fake-from-hex <value> Load fake packets for Fake Request Mode from HEX values (like 1234abcDEF).
|
||||||
|
This option can be supplied multiple times, in this case each fake packet
|
||||||
|
would be sent on every request in the command line argument order.
|
||||||
|
--fake-gen <value> Generate random-filled fake packets for Fake Request Mode, value of them
|
||||||
|
(up to 30).
|
||||||
|
--fake-resend <value> Send each fake packet value number of times.
|
||||||
|
Default: 1 (send each packet once).
|
||||||
--max-payload [value] packets with TCP payload data more than [value] won't be processed.
|
--max-payload [value] packets with TCP payload data more than [value] won't be processed.
|
||||||
Use this option to reduce CPU usage by skipping huge amount of data
|
Use this option to reduce CPU usage by skipping huge amount of data
|
||||||
(like file transfers) in already established sessions.
|
(like file transfers) in already established sessions.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#define _CRT_RAND_S
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <in6addr.h>
|
#include <in6addr.h>
|
||||||
@@ -7,6 +9,15 @@
|
|||||||
#include "windivert.h"
|
#include "windivert.h"
|
||||||
#include "goodbyedpi.h"
|
#include "goodbyedpi.h"
|
||||||
|
|
||||||
|
struct fake_t {
|
||||||
|
const unsigned char* data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct fake_t *fakes[30] = {0};
|
||||||
|
int fakes_count = 0;
|
||||||
|
int fakes_resend = 1;
|
||||||
|
|
||||||
static const unsigned char fake_http_request[] = "GET / HTTP/1.1\r\nHost: www.w3.org\r\n"
|
static const unsigned char fake_http_request[] = "GET / HTTP/1.1\r\nHost: www.w3.org\r\n"
|
||||||
"User-Agent: curl/7.65.3\r\nAccept: */*\r\n"
|
"User-Agent: curl/7.65.3\r\nAccept: */*\r\n"
|
||||||
"Accept-Encoding: deflate, gzip, br\r\n\r\n";
|
"Accept-Encoding: deflate, gzip, br\r\n\r\n";
|
||||||
@@ -54,7 +65,8 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
const BOOL is_https,
|
const BOOL is_https,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum,
|
const BYTE set_checksum,
|
||||||
const BYTE set_seq
|
const BYTE set_seq,
|
||||||
|
const struct fake_t *fake_data
|
||||||
) {
|
) {
|
||||||
char packet_fake[MAX_PACKET_SIZE];
|
char packet_fake[MAX_PACKET_SIZE];
|
||||||
WINDIVERT_ADDRESS addr_new;
|
WINDIVERT_ADDRESS addr_new;
|
||||||
@@ -66,6 +78,10 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
PWINDIVERT_TCPHDR ppTcpHdr;
|
PWINDIVERT_TCPHDR ppTcpHdr;
|
||||||
unsigned const char *fake_request_data = is_https ? fake_https_request : fake_http_request;
|
unsigned const char *fake_request_data = is_https ? fake_https_request : fake_http_request;
|
||||||
UINT fake_request_size = is_https ? sizeof(fake_https_request) : sizeof(fake_http_request) - 1;
|
UINT fake_request_size = is_https ? sizeof(fake_https_request) : sizeof(fake_http_request) - 1;
|
||||||
|
if (fake_data) {
|
||||||
|
fake_request_data = fake_data->data;
|
||||||
|
fake_request_size = fake_data->size;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS));
|
memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS));
|
||||||
memcpy(packet_fake, pkt, packetLen);
|
memcpy(packet_fake, pkt, packetLen);
|
||||||
@@ -148,22 +164,26 @@ static int send_fake_request(const HANDLE w_filter,
|
|||||||
const BOOL is_https,
|
const BOOL is_https,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum,
|
const BYTE set_checksum,
|
||||||
const BYTE set_seq
|
const BYTE set_seq,
|
||||||
|
const struct fake_t *fake_data
|
||||||
) {
|
) {
|
||||||
if (set_ttl) {
|
if (set_ttl) {
|
||||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
is_ipv6, is_https,
|
is_ipv6, is_https,
|
||||||
set_ttl, FALSE, FALSE);
|
set_ttl, FALSE, FALSE,
|
||||||
|
fake_data);
|
||||||
}
|
}
|
||||||
if (set_checksum) {
|
if (set_checksum) {
|
||||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
is_ipv6, is_https,
|
is_ipv6, is_https,
|
||||||
FALSE, set_checksum, FALSE);
|
FALSE, set_checksum, FALSE,
|
||||||
|
fake_data);
|
||||||
}
|
}
|
||||||
if (set_seq) {
|
if (set_seq) {
|
||||||
send_fake_data(w_filter, addr, pkt, packetLen,
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
is_ipv6, is_https,
|
is_ipv6, is_https,
|
||||||
FALSE, FALSE, set_seq);
|
FALSE, FALSE, set_seq,
|
||||||
|
fake_data);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -177,9 +197,18 @@ int send_fake_http_request(const HANDLE w_filter,
|
|||||||
const BYTE set_checksum,
|
const BYTE set_checksum,
|
||||||
const BYTE set_seq
|
const BYTE set_seq
|
||||||
) {
|
) {
|
||||||
return send_fake_request(w_filter, addr, pkt, packetLen,
|
int ret = 0;
|
||||||
is_ipv6, FALSE,
|
for (int i=0; i<fakes_count || i == 0; i++) {
|
||||||
set_ttl, set_checksum, set_seq);
|
for (int j=0; j<fakes_resend; j++)
|
||||||
|
if (send_fake_request(w_filter, addr, pkt, packetLen,
|
||||||
|
is_ipv6, FALSE,
|
||||||
|
set_ttl, set_checksum, set_seq,
|
||||||
|
fakes[i]))
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_fake_https_request(const HANDLE w_filter,
|
int send_fake_https_request(const HANDLE w_filter,
|
||||||
@@ -191,7 +220,94 @@ int send_fake_https_request(const HANDLE w_filter,
|
|||||||
const BYTE set_checksum,
|
const BYTE set_checksum,
|
||||||
const BYTE set_seq
|
const BYTE set_seq
|
||||||
) {
|
) {
|
||||||
return send_fake_request(w_filter, addr, pkt, packetLen,
|
int ret = 0;
|
||||||
|
for (int i=0; i<fakes_count || i == 0; i++) {
|
||||||
|
for (int j=0; j<fakes_resend; j++)
|
||||||
|
if (send_fake_request(w_filter, addr, pkt, packetLen,
|
||||||
is_ipv6, TRUE,
|
is_ipv6, TRUE,
|
||||||
set_ttl, set_checksum, set_seq);
|
set_ttl, set_checksum, set_seq,
|
||||||
|
fakes[i]))
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fake_add(const unsigned char *data, size_t size) {
|
||||||
|
struct fake_t *fake = malloc(sizeof(struct fake_t));
|
||||||
|
fake->size = size;
|
||||||
|
fake->data = data;
|
||||||
|
|
||||||
|
for (size_t k = 0; k <= sizeof(fakes) / sizeof(*fakes); k++) {
|
||||||
|
if (!fakes[k]) {
|
||||||
|
fakes[k] = fake;
|
||||||
|
fakes_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fake_load_from_hex(const char *data) {
|
||||||
|
size_t len = strlen(data);
|
||||||
|
if (len < 2 || len % 2 || len > 1420)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
unsigned char *finaldata = calloc((len + 2) / 2, 1);
|
||||||
|
|
||||||
|
for (size_t i = 0; i<len - 1; i+=2) {
|
||||||
|
char num1 = data[i];
|
||||||
|
char num2 = data[i+1];
|
||||||
|
debug("Current num1: %X, num2: %X\n", num1, num2);
|
||||||
|
unsigned char finalchar = 0;
|
||||||
|
char curchar = num1;
|
||||||
|
|
||||||
|
for (int j=0; j<=1; j++) {
|
||||||
|
if (curchar >= '0' && curchar <= '9')
|
||||||
|
curchar -= '0';
|
||||||
|
else if (curchar >= 'a' && curchar <= 'f')
|
||||||
|
curchar -= 'a' - 0xA;
|
||||||
|
else if (curchar >= 'A' && curchar <= 'F')
|
||||||
|
curchar -= 'A' - 0xA;
|
||||||
|
else
|
||||||
|
return 2; // incorrect character, not a hex data
|
||||||
|
|
||||||
|
if (!j) {
|
||||||
|
num1 = curchar;
|
||||||
|
curchar = num2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
num2 = curchar;
|
||||||
|
}
|
||||||
|
debug("Processed num1: %X, num2: %X\n", num1, num2);
|
||||||
|
finalchar = (num1 << 4) | num2;
|
||||||
|
debug("Final char: %X\n", finalchar);
|
||||||
|
finaldata[i/2] = finalchar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fake_add(finaldata, len / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fake_load_random(unsigned int count, unsigned int maxsize) {
|
||||||
|
if (count < 1 || count > sizeof(fakes) / sizeof(*fakes))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
unsigned int random = 0;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<count; i++) {
|
||||||
|
unsigned int len = 0;
|
||||||
|
if (rand_s(&len))
|
||||||
|
return 1;
|
||||||
|
len = 8 + (len % maxsize);
|
||||||
|
|
||||||
|
unsigned char *data = calloc(len, 1);
|
||||||
|
for (unsigned int j=0; j<len; j++) {
|
||||||
|
rand_s(&random);
|
||||||
|
data[j] = random % 0xFF;
|
||||||
|
}
|
||||||
|
if (fake_add(data, len))
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
extern int fakes_count;
|
||||||
|
extern int fakes_resend;
|
||||||
int send_fake_http_request(const HANDLE w_filter,
|
int send_fake_http_request(const HANDLE w_filter,
|
||||||
const PWINDIVERT_ADDRESS addr,
|
const PWINDIVERT_ADDRESS addr,
|
||||||
const char *pkt,
|
const char *pkt,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
// My mingw installation does not load inet_pton definition for some reason
|
// 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);
|
WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, LPCSTR pStringBuf, PVOID pAddr);
|
||||||
|
|
||||||
#define GOODBYEDPI_VERSION "v0.2.3"
|
#define GOODBYEDPI_VERSION "v0.2.3rc2"
|
||||||
|
|
||||||
#define die() do { sleep(20); exit(EXIT_FAILURE); } while (0)
|
#define die() do { sleep(20); exit(EXIT_FAILURE); } while (0)
|
||||||
|
|
||||||
@@ -188,6 +188,9 @@ static struct option long_options[] = {
|
|||||||
{"native-frag", no_argument, 0, '*' },
|
{"native-frag", no_argument, 0, '*' },
|
||||||
{"reverse-frag",no_argument, 0, '(' },
|
{"reverse-frag",no_argument, 0, '(' },
|
||||||
{"max-payload", optional_argument, 0, '|' },
|
{"max-payload", optional_argument, 0, '|' },
|
||||||
|
{"fake-from-hex", required_argument, 0, 'u' },
|
||||||
|
{"fake-gen", required_argument, 0, 'j' },
|
||||||
|
{"fake-resend", required_argument, 0, 't' },
|
||||||
{"debug-exit", optional_argument, 0, 'x' },
|
{"debug-exit", optional_argument, 0, 'x' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
@@ -940,6 +943,25 @@ int main(int argc, char *argv[]) {
|
|||||||
else
|
else
|
||||||
max_payload_size = 1200;
|
max_payload_size = 1200;
|
||||||
break;
|
break;
|
||||||
|
case 'u': // --fake-from-hex
|
||||||
|
if (fake_load_from_hex(optarg)) {
|
||||||
|
printf("WARNING: bad fake HEX value %s\n", optarg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'j': // --fake-gen
|
||||||
|
if (fake_load_random(atoub(optarg, "Fake generator parameter error!"))) {
|
||||||
|
puts("WARNING: fake generator has failed!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 't': // --fake-resend
|
||||||
|
fakes_resend = atoub(optarg, "Fake resend parameter error!");
|
||||||
|
if (fakes_resend == 1)
|
||||||
|
puts("WARNING: fake-resend is 1, no resending is in place!");
|
||||||
|
else if (!fakes_resend)
|
||||||
|
puts("WARNING: fake-resend is 0, fake packet mode is disabled!");
|
||||||
|
else if (fakes_resend > 100)
|
||||||
|
puts("WARNING: fake-resend value is a little too high, don't you think?");
|
||||||
|
break;
|
||||||
case 'x': // --debug-exit
|
case 'x': // --debug-exit
|
||||||
debug_exit = true;
|
debug_exit = true;
|
||||||
break;
|
break;
|
||||||
@@ -988,6 +1010,13 @@ int main(int argc, char *argv[]) {
|
|||||||
" --reverse-frag fragment (split) the packets just as --native-frag, but send them in the\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"
|
" reversed order. Works with the websites which could not handle segmented\n"
|
||||||
" HTTPS TLS ClientHello (because they receive the TCP flow \"combined\").\n"
|
" HTTPS TLS ClientHello (because they receive the TCP flow \"combined\").\n"
|
||||||
|
" --fake-from-hex <value> Load fake packets for Fake Request Mode from HEX values (like 1234abcDEF).\n"
|
||||||
|
" This option can be supplied multiple times, in this case each fake packet\n"
|
||||||
|
" would be sent on every request in the command line argument order.\n"
|
||||||
|
" --fake-gen <value> Generate random-filled fake packets for Fake Request Mode, value of them\n"
|
||||||
|
" (up to 30).\n"
|
||||||
|
" --fake-resend <value> Send each fake packet value number of times.\n"
|
||||||
|
" Default: 1 (send each packet once).\n"
|
||||||
" --max-payload [value] packets with TCP payload data more than [value] won't be processed.\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"
|
" Use this option to reduce CPU usage by skipping huge amount of data\n"
|
||||||
" (like file transfers) in already established sessions.\n"
|
" (like file transfers) in already established sessions.\n"
|
||||||
@@ -1047,7 +1076,9 @@ int main(int argc, char *argv[]) {
|
|||||||
"Fake requests, TTL: %s (fixed: %hu, auto: %hu-%hu-%hu, min distance: %hu)\n" /* 17 */
|
"Fake requests, TTL: %s (fixed: %hu, auto: %hu-%hu-%hu, min distance: %hu)\n" /* 17 */
|
||||||
"Fake requests, wrong checksum: %d\n" /* 18 */
|
"Fake requests, wrong checksum: %d\n" /* 18 */
|
||||||
"Fake requests, wrong SEQ/ACK: %d\n" /* 19 */
|
"Fake requests, wrong SEQ/ACK: %d\n" /* 19 */
|
||||||
"Max payload size: %hu\n", /* 20 */
|
"Fake requests, custom payloads: %d\n" /* 20 */
|
||||||
|
"Fake requests, resend: %d\n" /* 21 */
|
||||||
|
"Max payload size: %hu\n", /* 22 */
|
||||||
do_passivedpi, do_block_quic, /* 1 */
|
do_passivedpi, do_block_quic, /* 1 */
|
||||||
(do_fragment_http ? http_fragment_size : 0), /* 2 */
|
(do_fragment_http ? http_fragment_size : 0), /* 2 */
|
||||||
(do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */
|
(do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */
|
||||||
@@ -1069,7 +1100,9 @@ int main(int argc, char *argv[]) {
|
|||||||
do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops,
|
do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops,
|
||||||
do_wrong_chksum, /* 18 */
|
do_wrong_chksum, /* 18 */
|
||||||
do_wrong_seq, /* 19 */
|
do_wrong_seq, /* 19 */
|
||||||
max_payload_size /* 20 */
|
fakes_count, /* 20 */
|
||||||
|
fakes_resend, /* 21 */
|
||||||
|
max_payload_size /* 22 */
|
||||||
);
|
);
|
||||||
|
|
||||||
if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) {
|
if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) {
|
||||||
|
|||||||
Reference in New Issue
Block a user