mirror of
https://github.com/ValdikSS/GoodbyeDPI.git
synced 2024-12-22 14:26:08 +00:00
Merge branch 'badseq_for_master' into master
This commit is contained in:
commit
88d4a60cdf
25
README.md
25
README.md
@ -17,27 +17,30 @@ Usage: goodbyedpi.exe [OPTION...]
|
|||||||
-r replace Host with hoSt
|
-r replace Host with hoSt
|
||||||
-s remove space between host header and its value
|
-s remove space between host header and its value
|
||||||
-m mix Host header case (test.com -> tEsT.cOm)
|
-m mix Host header case (test.com -> tEsT.cOm)
|
||||||
-f [value] set HTTP fragmentation to value
|
-f <value> set HTTP fragmentation to value
|
||||||
-k [value] enable HTTP persistent (keep-alive) fragmentation and set it to value
|
-k <value> enable HTTP persistent (keep-alive) fragmentation and set it to value
|
||||||
-n do not wait for first segment ACK when -k is enabled
|
-n do not wait for first segment ACK when -k is enabled
|
||||||
-e [value] set HTTPS fragmentation to value
|
-e <value> set HTTPS fragmentation to value
|
||||||
-a additional space between Method and Request-URI (enables -s, may break sites)
|
-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)
|
-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)
|
--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).
|
--ip-id <value> handle additional IP ID (decimal, drop redirects and TCP RSTs with this ID).
|
||||||
This option can be supplied multiple times.
|
This option can be supplied multiple times.
|
||||||
--dns-addr [value] redirect UDP DNS requests to the supplied IP address (experimental)
|
--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-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-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)
|
--dnsv6-port <value> redirect UDPv6 DNS requests to the supplied port (53 by default)
|
||||||
--dns-verb print verbose DNS redirection messages
|
--dns-verb print verbose DNS redirection messages
|
||||||
--blacklist [txtfile] perform circumvention tricks only to host names and subdomains from
|
--blacklist <txtfile> perform circumvention tricks only to host names and subdomains from
|
||||||
supplied text file (HTTP Host/TLS SNI).
|
supplied text file (HTTP Host/TLS SNI).
|
||||||
This option can be supplied multiple times.
|
This option can be supplied multiple times.
|
||||||
--set-ttl [value] activate Fake Request Mode and send it with supplied TTL value.
|
--set-ttl <value> activate Fake Request Mode and send it with supplied TTL value.
|
||||||
DANGEROUS! May break websites in unexpected ways. Use with care.
|
DANGEROUS! May break websites in unexpected ways. Use with care.
|
||||||
|
--auto-ttl [decttl] activate Fake Request Mode, automatically detect TTL and decrease
|
||||||
|
it from standard 64 or 128 by decttl (128/64 - TTL - 2 by default).
|
||||||
--wrong-chksum activate Fake Request Mode and send it with incorrect TCP checksum.
|
--wrong-chksum activate Fake Request Mode and send it with incorrect TCP checksum.
|
||||||
May not work in a VM or with some routers, but is safer than set-ttl.
|
May not work in a VM or with some routers, but is safer than set-ttl.
|
||||||
|
--wrong-seq activate Fake Request Mode and send it with TCP SEQ/ACK in the past.
|
||||||
--native-frag fragment (split) the packets by sending them in smaller packets, without
|
--native-frag fragment (split) the packets by sending them in smaller packets, without
|
||||||
shrinking the Window Size. Works faster (does not slow down the connection)
|
shrinking the Window Size. Works faster (does not slow down the connection)
|
||||||
and better.
|
and better.
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef _DNSREDIR_H
|
||||||
|
#define _DNSREDIR_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct conntrack_info {
|
typedef struct conntrack_info {
|
||||||
@ -34,3 +36,4 @@ int dns_handle_outgoing(const uint32_t srcip[4], const uint16_t srcport,
|
|||||||
|
|
||||||
void flush_dns_cache();
|
void flush_dns_cache();
|
||||||
int dns_is_dns_packet(const char *packet_data, const UINT packet_dataLen, const int outgoing);
|
int dns_is_dns_packet(const char *packet_data, const UINT packet_dataLen, const int outgoing);
|
||||||
|
#endif
|
||||||
|
@ -53,7 +53,8 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
const BOOL is_ipv6,
|
const BOOL is_ipv6,
|
||||||
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
|
||||||
) {
|
) {
|
||||||
char packet_fake[MAX_PACKET_SIZE];
|
char packet_fake[MAX_PACKET_SIZE];
|
||||||
WINDIVERT_ADDRESS addr_new;
|
WINDIVERT_ADDRESS addr_new;
|
||||||
@ -69,6 +70,9 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS));
|
memcpy(&addr_new, addr, sizeof(WINDIVERT_ADDRESS));
|
||||||
memcpy(packet_fake, pkt, packetLen);
|
memcpy(packet_fake, pkt, packetLen);
|
||||||
|
|
||||||
|
addr_new.PseudoTCPChecksum = 0;
|
||||||
|
addr_new.PseudoIPChecksum = 0;
|
||||||
|
|
||||||
if (!is_ipv6) {
|
if (!is_ipv6) {
|
||||||
// IPv4 TCP Data packet
|
// IPv4 TCP Data packet
|
||||||
if (!WinDivertHelperParsePacket(packet_fake, packetLen, &ppIpHdr,
|
if (!WinDivertHelperParsePacket(packet_fake, packetLen, &ppIpHdr,
|
||||||
@ -107,8 +111,15 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
ppIpV6Hdr->HopLimit = set_ttl;
|
ppIpV6Hdr->HopLimit = set_ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set_seq) {
|
||||||
|
// This is the smallest ACK drift Linux can't handle already, since at least v2.6.18.
|
||||||
|
// https://github.com/torvalds/linux/blob/v2.6.18/net/netfilter/nf_conntrack_proto_tcp.c#L395
|
||||||
|
ppTcpHdr->AckNum = htonl(ntohl(ppTcpHdr->AckNum) - 66000);
|
||||||
|
// This is just random, no specifics about this value.
|
||||||
|
ppTcpHdr->SeqNum = htonl(ntohl(ppTcpHdr->SeqNum) - 10000);
|
||||||
|
}
|
||||||
|
|
||||||
// Recalculate the checksum
|
// Recalculate the checksum
|
||||||
addr_new.PseudoTCPChecksum = 0;
|
|
||||||
WinDivertHelperCalcChecksums(packet_fake, packetLen_new, &addr_new, NULL);
|
WinDivertHelperCalcChecksums(packet_fake, packetLen_new, &addr_new, NULL);
|
||||||
|
|
||||||
if (set_checksum) {
|
if (set_checksum) {
|
||||||
@ -127,23 +138,46 @@ static int send_fake_data(const HANDLE w_filter,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int send_fake_request(const HANDLE w_filter,
|
||||||
|
const PWINDIVERT_ADDRESS addr,
|
||||||
|
const char *pkt,
|
||||||
|
const UINT packetLen,
|
||||||
|
const BOOL is_ipv6,
|
||||||
|
const BOOL is_https,
|
||||||
|
const BYTE set_ttl,
|
||||||
|
const BYTE set_checksum,
|
||||||
|
const BYTE set_seq
|
||||||
|
) {
|
||||||
|
if (set_ttl) {
|
||||||
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
|
is_ipv6, is_https,
|
||||||
|
set_ttl, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
if (set_checksum) {
|
||||||
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
|
is_ipv6, is_https,
|
||||||
|
FALSE, set_checksum, FALSE);
|
||||||
|
}
|
||||||
|
if (set_seq) {
|
||||||
|
send_fake_data(w_filter, addr, pkt, packetLen,
|
||||||
|
is_ipv6, is_https,
|
||||||
|
FALSE, FALSE, set_seq);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
const UINT packetLen,
|
const UINT packetLen,
|
||||||
const BOOL is_ipv6,
|
const BOOL is_ipv6,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum
|
const BYTE set_checksum,
|
||||||
|
const BYTE set_seq
|
||||||
) {
|
) {
|
||||||
return send_fake_data(w_filter,
|
return send_fake_request(w_filter, addr, pkt, packetLen,
|
||||||
addr,
|
is_ipv6, FALSE,
|
||||||
pkt,
|
set_ttl, set_checksum, set_seq);
|
||||||
packetLen,
|
|
||||||
is_ipv6,
|
|
||||||
FALSE,
|
|
||||||
set_ttl,
|
|
||||||
set_checksum
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_fake_https_request(const HANDLE w_filter,
|
int send_fake_https_request(const HANDLE w_filter,
|
||||||
@ -152,15 +186,10 @@ int send_fake_https_request(const HANDLE w_filter,
|
|||||||
const UINT packetLen,
|
const UINT packetLen,
|
||||||
const BOOL is_ipv6,
|
const BOOL is_ipv6,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum
|
const BYTE set_checksum,
|
||||||
|
const BYTE set_seq
|
||||||
) {
|
) {
|
||||||
return send_fake_data(w_filter,
|
return send_fake_request(w_filter, addr, pkt, packetLen,
|
||||||
addr,
|
is_ipv6, TRUE,
|
||||||
pkt,
|
set_ttl, set_checksum, set_seq);
|
||||||
packetLen,
|
|
||||||
is_ipv6,
|
|
||||||
TRUE,
|
|
||||||
set_ttl,
|
|
||||||
set_checksum
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@ int send_fake_http_request(const HANDLE w_filter,
|
|||||||
const UINT packetLen,
|
const UINT packetLen,
|
||||||
const BOOL is_ipv6,
|
const BOOL is_ipv6,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum
|
const BYTE set_checksum,
|
||||||
|
const BYTE set_seq
|
||||||
);
|
);
|
||||||
int send_fake_https_request(const HANDLE w_filter,
|
int send_fake_https_request(const HANDLE w_filter,
|
||||||
const PWINDIVERT_ADDRESS addr,
|
const PWINDIVERT_ADDRESS addr,
|
||||||
@ -12,5 +13,6 @@ int send_fake_https_request(const HANDLE w_filter,
|
|||||||
const UINT packetLen,
|
const UINT packetLen,
|
||||||
const BOOL is_ipv6,
|
const BOOL is_ipv6,
|
||||||
const BYTE set_ttl,
|
const BYTE set_ttl,
|
||||||
const BYTE set_checksum
|
const BYTE set_checksum,
|
||||||
|
const BYTE set_seq
|
||||||
);
|
);
|
||||||
|
103
src/goodbyedpi.c
103
src/goodbyedpi.c
@ -16,6 +16,7 @@
|
|||||||
#include "utils/repl_str.h"
|
#include "utils/repl_str.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "dnsredir.h"
|
#include "dnsredir.h"
|
||||||
|
#include "ttltrack.h"
|
||||||
#include "blackwhitelist.h"
|
#include "blackwhitelist.h"
|
||||||
#include "fakepackets.h"
|
#include "fakepackets.h"
|
||||||
|
|
||||||
@ -94,6 +95,22 @@ WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, LPCSTR pStringBuf, PVOID pA
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define TCP_HANDLE_OUTGOING_ADJUST_TTL() do { \
|
||||||
|
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))) \
|
||||||
|
{ \
|
||||||
|
ttl_of_fake_packet = tcp_get_auto_ttl(tcp_conn_info.ttl, do_auto_ttl); \
|
||||||
|
if (do_tcp_verb) { \
|
||||||
|
printf("Connection TTL = %d, Fake TTL = %d\n", tcp_conn_info.ttl, ttl_of_fake_packet); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static int running_from_service = 0;
|
static int running_from_service = 0;
|
||||||
static HANDLE filters[MAX_FILTERS];
|
static HANDLE filters[MAX_FILTERS];
|
||||||
static int filter_num = 0;
|
static int filter_num = 0;
|
||||||
@ -124,7 +141,9 @@ static struct option long_options[] = {
|
|||||||
{"blacklist", required_argument, 0, 'b' },
|
{"blacklist", required_argument, 0, 'b' },
|
||||||
{"ip-id", required_argument, 0, 'i' },
|
{"ip-id", required_argument, 0, 'i' },
|
||||||
{"set-ttl", required_argument, 0, '$' },
|
{"set-ttl", required_argument, 0, '$' },
|
||||||
|
{"auto-ttl", optional_argument, 0, '+' },
|
||||||
{"wrong-chksum",no_argument, 0, '%' },
|
{"wrong-chksum",no_argument, 0, '%' },
|
||||||
|
{"wrong-seq", no_argument, 0, ')' },
|
||||||
{"native-frag", no_argument, 0, '*' },
|
{"native-frag", no_argument, 0, '*' },
|
||||||
{"reverse-frag",no_argument, 0, '(' },
|
{"reverse-frag",no_argument, 0, '(' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
@ -487,6 +506,7 @@ int main(int argc, char *argv[]) {
|
|||||||
PWINDIVERT_TCPHDR ppTcpHdr;
|
PWINDIVERT_TCPHDR ppTcpHdr;
|
||||||
PWINDIVERT_UDPHDR ppUdpHdr;
|
PWINDIVERT_UDPHDR ppUdpHdr;
|
||||||
conntrack_info_t dns_conn_info;
|
conntrack_info_t dns_conn_info;
|
||||||
|
tcp_conntrack_info_t tcp_conn_info;
|
||||||
|
|
||||||
int do_passivedpi = 0, do_fragment_http = 0,
|
int do_passivedpi = 0, do_fragment_http = 0,
|
||||||
do_fragment_http_persistent = 0,
|
do_fragment_http_persistent = 0,
|
||||||
@ -496,9 +516,11 @@ int main(int argc, char *argv[]) {
|
|||||||
do_http_allports = 0,
|
do_http_allports = 0,
|
||||||
do_host_mixedcase = 0,
|
do_host_mixedcase = 0,
|
||||||
do_dnsv4_redirect = 0, do_dnsv6_redirect = 0,
|
do_dnsv4_redirect = 0, do_dnsv6_redirect = 0,
|
||||||
do_dns_verb = 0, do_blacklist = 0,
|
do_dns_verb = 0, do_tcp_verb = 0, do_blacklist = 0,
|
||||||
do_fake_packet = 0,
|
do_fake_packet = 0,
|
||||||
|
do_auto_ttl = 0,
|
||||||
do_wrong_chksum = 0,
|
do_wrong_chksum = 0,
|
||||||
|
do_wrong_seq = 0,
|
||||||
do_native_frag = 0, do_reverse_frag = 0;
|
do_native_frag = 0, do_reverse_frag = 0;
|
||||||
unsigned int http_fragment_size = 0;
|
unsigned int http_fragment_size = 0;
|
||||||
unsigned int https_fragment_size = 0;
|
unsigned int https_fragment_size = 0;
|
||||||
@ -695,6 +717,7 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
do_dns_verb = 1;
|
do_dns_verb = 1;
|
||||||
|
do_tcp_verb = 1;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
do_blacklist = 1;
|
do_blacklist = 1;
|
||||||
@ -707,10 +730,23 @@ int main(int argc, char *argv[]) {
|
|||||||
do_fake_packet = 1;
|
do_fake_packet = 1;
|
||||||
ttl_of_fake_packet = atoub(optarg, "Set TTL parameter error!");
|
ttl_of_fake_packet = atoub(optarg, "Set TTL parameter error!");
|
||||||
break;
|
break;
|
||||||
|
case '+':
|
||||||
|
do_fake_packet = 1;
|
||||||
|
do_auto_ttl = 2;
|
||||||
|
if (optarg) {
|
||||||
|
do_auto_ttl = atoub(optarg, "Set Auto TTL parameter error!");
|
||||||
|
} else if (argv[optind] && argv[optind][0] != '-') {
|
||||||
|
do_auto_ttl = atoub(argv[optind], "Set Auto TTL parameter error!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
do_fake_packet = 1;
|
do_fake_packet = 1;
|
||||||
do_wrong_chksum = 1;
|
do_wrong_chksum = 1;
|
||||||
break;
|
break;
|
||||||
|
case ')':
|
||||||
|
do_fake_packet = 1;
|
||||||
|
do_wrong_seq = 1;
|
||||||
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
do_native_frag = 1;
|
do_native_frag = 1;
|
||||||
do_fragment_http_persistent = 1;
|
do_fragment_http_persistent = 1;
|
||||||
@ -729,27 +765,29 @@ int main(int argc, char *argv[]) {
|
|||||||
" -s remove space between host header and its value\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"
|
" -a additional space between Method and Request-URI (enables -s, may break sites)\n"
|
||||||
" -m mix Host header case (test.com -> tEsT.cOm)\n"
|
" -m mix Host header case (test.com -> tEsT.cOm)\n"
|
||||||
" -f [value] set HTTP fragmentation to value\n"
|
" -f <value> set HTTP fragmentation to value\n"
|
||||||
" -k [value] enable HTTP persistent (keep-alive) fragmentation and set it to value\n"
|
" -k <value> 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"
|
" -n do not wait for first segment ACK when -k is enabled\n"
|
||||||
" -e [value] set HTTPS fragmentation to value\n"
|
" -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"
|
" -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"
|
" --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"
|
" --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-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"
|
" --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"
|
" --dnsv6-addr <value> redirect UDPv6 DNS requests to the supplied IPv6 address (experimental)\n"
|
||||||
" --dnsv6-port [value] redirect UDPv6 DNS requests to the supplied port (53 by default)\n"
|
" --dnsv6-port <value> redirect UDPv6 DNS requests to the supplied port (53 by default)\n"
|
||||||
" --dns-verb print verbose DNS redirection messages\n"
|
" --dns-verb print verbose DNS redirection messages\n"
|
||||||
" --blacklist [txtfile] perform circumvention tricks only to host names and subdomains from\n"
|
" --blacklist <txtfile> perform circumvention tricks only to host names and subdomains from\n"
|
||||||
" supplied text file (HTTP Host/TLS SNI).\n"
|
" supplied text file (HTTP Host/TLS SNI).\n"
|
||||||
" This option can be supplied multiple times.\n"
|
" This option can be supplied multiple times.\n"
|
||||||
" --set-ttl [value] activate Fake Request Mode and send it with supplied TTL value.\n"
|
" --set-ttl <value> activate Fake Request Mode and send it with supplied TTL value.\n"
|
||||||
" DANGEROUS! May break websites in unexpected ways. Use with care.\n"
|
" DANGEROUS! May break websites in unexpected ways. Use with care.\n"
|
||||||
" Could be combined with --wrong-chksum.\n"
|
" --auto-ttl [decttl] activate Fake Request Mode, automatically detect TTL and decrease\n"
|
||||||
|
" it from standard 64 or 128 by decttl (128/64 - TTL - 2 by default).\n"
|
||||||
" --wrong-chksum activate Fake Request Mode and send it with incorrect TCP checksum.\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"
|
" May not work in a VM or with some routers, but is safer than set-ttl.\n"
|
||||||
" Could be combined with --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"
|
" --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"
|
" shrinking the Window Size. Works faster (does not slow down the connection)\n"
|
||||||
" and better.\n"
|
" and better.\n"
|
||||||
@ -776,14 +814,16 @@ int main(int argc, char *argv[]) {
|
|||||||
"hoSt: %d\nHost no space: %d\nAdditional space: %d\n"
|
"hoSt: %d\nHost no space: %d\nAdditional space: %d\n"
|
||||||
"Mix Host: %d\nHTTP AllPorts: %d\nHTTP Persistent Nowait: %d\n"
|
"Mix Host: %d\nHTTP AllPorts: %d\nHTTP Persistent Nowait: %d\n"
|
||||||
"DNS redirect: %d\nDNSv6 redirect: %d\n"
|
"DNS redirect: %d\nDNSv6 redirect: %d\n"
|
||||||
"Fake requests, TTL: %hu\nFake requests, wrong checksum: %d\n",
|
"Fake requests, TTL: %hu (auto: %hu)\nFake requests, wrong checksum: %d\n"
|
||||||
|
"Fake requests, wrong SEQ/ACK: %d\n",
|
||||||
do_passivedpi, (do_fragment_http ? http_fragment_size : 0),
|
do_passivedpi, (do_fragment_http ? http_fragment_size : 0),
|
||||||
(do_fragment_http_persistent ? http_fragment_size : 0),
|
(do_fragment_http_persistent ? http_fragment_size : 0),
|
||||||
(do_fragment_https ? https_fragment_size : 0),
|
(do_fragment_https ? https_fragment_size : 0),
|
||||||
do_native_frag, do_reverse_frag,
|
do_native_frag, do_reverse_frag,
|
||||||
do_host, do_host_removespace, do_additional_space, do_host_mixedcase,
|
do_host, do_host_removespace, do_additional_space, do_host_mixedcase,
|
||||||
do_http_allports, do_fragment_http_persistent_nowait, do_dnsv4_redirect,
|
do_http_allports, do_fragment_http_persistent_nowait, do_dnsv4_redirect,
|
||||||
do_dnsv6_redirect, ttl_of_fake_packet, do_wrong_chksum
|
do_dnsv6_redirect, ttl_of_fake_packet, do_auto_ttl,
|
||||||
|
do_wrong_chksum, do_wrong_seq
|
||||||
);
|
);
|
||||||
|
|
||||||
if (do_fragment_http && http_fragment_size > 2) {
|
if (do_fragment_http && http_fragment_size > 2) {
|
||||||
@ -922,8 +962,11 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("Blocked HTTPS website SNI: %s\n", lsni);
|
printf("Blocked HTTPS website SNI: %s\n", lsni);
|
||||||
#endif
|
#endif
|
||||||
if (do_fake_packet) {
|
if (do_fake_packet) {
|
||||||
|
if (do_auto_ttl) {
|
||||||
|
TCP_HANDLE_OUTGOING_ADJUST_TTL();
|
||||||
|
}
|
||||||
send_fake_https_request(w_filter, &addr, packet, packetLen, packet_v6,
|
send_fake_https_request(w_filter, &addr, packet, packetLen, packet_v6,
|
||||||
ttl_of_fake_packet, do_wrong_chksum);
|
ttl_of_fake_packet, do_wrong_chksum, do_wrong_seq);
|
||||||
}
|
}
|
||||||
if (do_native_frag) {
|
if (do_native_frag) {
|
||||||
// Signal for native fragmentation code handler
|
// Signal for native fragmentation code handler
|
||||||
@ -963,9 +1006,13 @@ int main(int argc, char *argv[]) {
|
|||||||
should_recalc_checksum = 1;
|
should_recalc_checksum = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_fake_packet)
|
if (do_fake_packet) {
|
||||||
|
if (do_auto_ttl) {
|
||||||
|
TCP_HANDLE_OUTGOING_ADJUST_TTL();
|
||||||
|
}
|
||||||
send_fake_http_request(w_filter, &addr, packet, packetLen, packet_v6,
|
send_fake_http_request(w_filter, &addr, packet, packetLen, packet_v6,
|
||||||
ttl_of_fake_packet, do_wrong_chksum);
|
ttl_of_fake_packet, do_wrong_chksum, do_wrong_seq);
|
||||||
|
}
|
||||||
|
|
||||||
if (do_host_mixedcase) {
|
if (do_host_mixedcase) {
|
||||||
mix_case(host_addr, host_len);
|
mix_case(host_addr, host_len);
|
||||||
@ -1078,13 +1125,28 @@ int main(int argc, char *argv[]) {
|
|||||||
else if (packet_type == ipv4_tcp || packet_type == ipv6_tcp) {
|
else if (packet_type == ipv4_tcp || packet_type == ipv6_tcp) {
|
||||||
/* If we got INBOUND SYN+ACK packet */
|
/* If we got INBOUND SYN+ACK packet */
|
||||||
if (addr.Direction == WINDIVERT_DIRECTION_INBOUND &&
|
if (addr.Direction == WINDIVERT_DIRECTION_INBOUND &&
|
||||||
ppTcpHdr->Syn == 1 && ppTcpHdr->Ack == 1 &&
|
ppTcpHdr->Syn == 1 && ppTcpHdr->Ack == 1) {
|
||||||
!do_native_frag) {
|
|
||||||
//printf("Changing Window Size!\n");
|
//printf("Changing Window Size!\n");
|
||||||
/*
|
/*
|
||||||
* Window Size is changed even if do_fragment_http_persistent
|
* Window Size is changed even if do_fragment_http_persistent
|
||||||
* is enabled as there could be non-HTTP data on port 80
|
* is enabled as there could be non-HTTP data on port 80
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (do_fake_packet && do_auto_ttl) {
|
||||||
|
if (!((packet_v4 && tcp_handle_incoming(&ppIpHdr->SrcAddr, &ppIpHdr->DstAddr,
|
||||||
|
ppTcpHdr->SrcPort, ppTcpHdr->DstPort,
|
||||||
|
0, ppIpHdr->TTL))
|
||||||
|
||
|
||||||
|
(packet_v6 && tcp_handle_incoming(&ppIpV6Hdr->SrcAddr, &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)) {
|
if (do_fragment_http && ppTcpHdr->SrcPort == htons(80)) {
|
||||||
change_window_size(ppTcpHdr, http_fragment_size);
|
change_window_size(ppTcpHdr, http_fragment_size);
|
||||||
should_recalc_checksum = 1;
|
should_recalc_checksum = 1;
|
||||||
@ -1095,6 +1157,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Else if we got UDP packet with data */
|
/* Else if we got UDP packet with data */
|
||||||
else if ((do_dnsv4_redirect && (packet_type == ipv4_udp_data)) ||
|
else if ((do_dnsv4_redirect && (packet_type == ipv4_udp_data)) ||
|
||||||
|
235
src/ttltrack.c
Normal file
235
src/ttltrack.c
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/**
|
||||||
|
* TCP (TTL) Connection Tracker for GoodbyeDPI
|
||||||
|
*
|
||||||
|
* Monitors SYN/ACK only, to extract the TTL value of the remote server.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "goodbyedpi.h"
|
||||||
|
#include "ttltrack.h"
|
||||||
|
#include "utils/uthash.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* key ('4' for IPv4 or '6' for IPv6 + srcip[16] + dstip[16] + srcport[2] + dstport[2]) */
|
||||||
|
#define TCP_CONNRECORD_KEY_LEN 37
|
||||||
|
|
||||||
|
#define TCP_CLEANUP_INTERVAL_SEC 30
|
||||||
|
|
||||||
|
/* HACK!
|
||||||
|
* uthash uses strlen() for HASH_FIND_STR.
|
||||||
|
* We have null bytes in our key, so we can't use strlen()
|
||||||
|
* And since it's always TCP_CONNRECORD_KEY_LEN bytes long,
|
||||||
|
* we don't need to use any string function to determine length.
|
||||||
|
*/
|
||||||
|
#undef uthash_strlen
|
||||||
|
#define uthash_strlen(s) TCP_CONNRECORD_KEY_LEN
|
||||||
|
|
||||||
|
typedef struct tcp_connrecord {
|
||||||
|
/* key ('4' for IPv4 or '6' for IPv6 + srcip[16] + dstip[16] + srcport[2] + dstport[2]) */
|
||||||
|
char key[TCP_CONNRECORD_KEY_LEN];
|
||||||
|
time_t time; /* time when this record was added */
|
||||||
|
uint16_t ttl;
|
||||||
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
|
} tcp_connrecord_t;
|
||||||
|
|
||||||
|
static time_t last_cleanup = 0;
|
||||||
|
static tcp_connrecord_t *conntrack = NULL;
|
||||||
|
|
||||||
|
inline static void fill_key_data(char *key, const uint8_t is_ipv6, const uint32_t srcip[4],
|
||||||
|
const uint32_t dstip[4], const uint16_t srcport, const uint16_t dstport)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
if (is_ipv6) {
|
||||||
|
*(uint8_t*)(key) = '6';
|
||||||
|
offset += sizeof(uint8_t);
|
||||||
|
ipv6_copy_addr((uint32_t*)(key + offset), srcip);
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
ipv6_copy_addr((uint32_t*)(key + offset), dstip);
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*(uint8_t*)(key) = '4';
|
||||||
|
offset += sizeof(uint8_t);
|
||||||
|
ipv4_copy_addr((uint32_t*)(key + offset), srcip);
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
ipv4_copy_addr((uint32_t*)(key + offset), dstip);
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(uint16_t*)(key + offset) = srcport;
|
||||||
|
offset += sizeof(srcport);
|
||||||
|
*(uint16_t*)(key + offset) = dstport;
|
||||||
|
offset += sizeof(dstport);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void fill_data_from_key(uint8_t *is_ipv6, uint32_t srcip[4], uint32_t dstip[4],
|
||||||
|
uint16_t *srcport, uint16_t *dstport, const char *key)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
if (key[0] == '6') {
|
||||||
|
*is_ipv6 = 1;
|
||||||
|
offset += sizeof(uint8_t);
|
||||||
|
ipv6_copy_addr(srcip, (uint32_t*)(key + offset));
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
ipv6_copy_addr(dstip, (uint32_t*)(key + offset));
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*is_ipv6 = 0;
|
||||||
|
offset += sizeof(uint8_t);
|
||||||
|
ipv4_copy_addr(srcip, (uint32_t*)(key + offset));
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
ipv4_copy_addr(dstip, (uint32_t*)(key + offset));
|
||||||
|
offset += sizeof(uint32_t) * 4;
|
||||||
|
}
|
||||||
|
*srcport = *(uint16_t*)(key + offset);
|
||||||
|
offset += sizeof(*srcport);
|
||||||
|
*dstport = *(uint16_t*)(key + offset);
|
||||||
|
offset += sizeof(*dstport);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void construct_key(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
char *key, const uint8_t is_ipv6)
|
||||||
|
{
|
||||||
|
debug("Construct key enter\n");
|
||||||
|
if (key) {
|
||||||
|
debug("Constructing key\n");
|
||||||
|
fill_key_data(key, is_ipv6, srcip, dstip, srcport, dstport);
|
||||||
|
}
|
||||||
|
debug("Construct key end\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void deconstruct_key(const char *key, const tcp_connrecord_t *connrecord,
|
||||||
|
tcp_conntrack_info_t *conn_info)
|
||||||
|
{
|
||||||
|
debug("Deconstruct key enter\n");
|
||||||
|
if (key && conn_info) {
|
||||||
|
debug("Deconstructing key\n");
|
||||||
|
fill_data_from_key(&conn_info->is_ipv6,
|
||||||
|
conn_info->srcip, conn_info->dstip,
|
||||||
|
&conn_info->srcport, &conn_info->dstport,
|
||||||
|
key);
|
||||||
|
|
||||||
|
conn_info->ttl = connrecord->ttl;
|
||||||
|
}
|
||||||
|
debug("Deconstruct key end\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_get_tcp_conntrack_key(const char *key, tcp_connrecord_t **connrecord) {
|
||||||
|
tcp_connrecord_t *tmp_connrecord = NULL;
|
||||||
|
if (!conntrack) return FALSE;
|
||||||
|
|
||||||
|
HASH_FIND_STR(conntrack, key, tmp_connrecord);
|
||||||
|
if (tmp_connrecord) {
|
||||||
|
if (connrecord)
|
||||||
|
*connrecord = tmp_connrecord;
|
||||||
|
debug("check_get_tcp_conntrack_key found key\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
debug("check_get_tcp_conntrack_key key not found\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_tcp_conntrack(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
const uint8_t is_ipv6, const uint8_t ttl
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!(srcip && srcport && dstip && dstport))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
tcp_connrecord_t *tmp_connrecord = malloc(sizeof(tcp_connrecord_t));
|
||||||
|
construct_key(srcip, dstip, srcport, dstport, tmp_connrecord->key, is_ipv6);
|
||||||
|
|
||||||
|
if (!check_get_tcp_conntrack_key(tmp_connrecord->key, NULL)) {
|
||||||
|
tmp_connrecord->time = time(NULL);
|
||||||
|
tmp_connrecord->ttl = ttl;
|
||||||
|
HASH_ADD_STR(conntrack, key, tmp_connrecord);
|
||||||
|
debug("Added TCP conntrack %u:%hu - %u:%hu\n", srcip[0], ntohs(srcport), dstip[0], ntohs(dstport));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
debug("Not added TCP conntrack %u:%hu - %u:%hu\n", srcip[0], ntohs(srcport), dstip[0], ntohs(dstport));
|
||||||
|
free(tmp_connrecord);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcp_cleanup() {
|
||||||
|
tcp_connrecord_t *tmp_connrecord, *tmp_connrecord2 = NULL;
|
||||||
|
|
||||||
|
if (last_cleanup == 0) {
|
||||||
|
last_cleanup = time(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (difftime(time(NULL), last_cleanup) >= TCP_CLEANUP_INTERVAL_SEC) {
|
||||||
|
last_cleanup = time(NULL);
|
||||||
|
|
||||||
|
HASH_ITER(hh, conntrack, tmp_connrecord, tmp_connrecord2) {
|
||||||
|
if (difftime(last_cleanup, tmp_connrecord->time) >= TCP_CLEANUP_INTERVAL_SEC) {
|
||||||
|
HASH_DEL(conntrack, tmp_connrecord);
|
||||||
|
free(tmp_connrecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_handle_incoming(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
const uint8_t is_ipv6, const uint8_t ttl)
|
||||||
|
{
|
||||||
|
tcp_cleanup();
|
||||||
|
|
||||||
|
debug("trying to add TCP srcport = %hu, dstport = %hu\n", ntohs(srcport), ntohs(dstport));
|
||||||
|
return add_tcp_conntrack(srcip, dstip, srcport, dstport, is_ipv6, ttl);
|
||||||
|
|
||||||
|
debug("____tcp_handle_incoming FALSE: srcport = %hu, dstport = %hu\n", ntohs(srcport), ntohs(dstport));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_handle_outgoing(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
tcp_conntrack_info_t *conn_info,
|
||||||
|
const uint8_t is_ipv6)
|
||||||
|
{
|
||||||
|
char key[TCP_CONNRECORD_KEY_LEN];
|
||||||
|
tcp_connrecord_t *tmp_connrecord = NULL;
|
||||||
|
|
||||||
|
if (!conn_info)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
tcp_cleanup();
|
||||||
|
construct_key(dstip, srcip, dstport, srcport, key, is_ipv6);
|
||||||
|
if (check_get_tcp_conntrack_key(key, &tmp_connrecord) && tmp_connrecord) {
|
||||||
|
/* Connection exists in conntrack, moving on */
|
||||||
|
deconstruct_key(key, tmp_connrecord, conn_info);
|
||||||
|
HASH_DEL(conntrack, tmp_connrecord);
|
||||||
|
free(tmp_connrecord);
|
||||||
|
debug("____tcp_handle_outgoing TRUE: srcport = %hu\n", ntohs(srcport));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("____tcp_handle_outgoing FALSE: srcport = %hu\n", ntohs(srcport));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_get_auto_ttl(const uint8_t ttl, const uint8_t decrease_for) {
|
||||||
|
uint8_t ttl_of_fake_packet = 0;
|
||||||
|
|
||||||
|
if (ttl > 64 && ttl < 128) {
|
||||||
|
ttl_of_fake_packet = 128 - ttl - decrease_for;
|
||||||
|
}
|
||||||
|
else if (ttl > 34 && ttl < 64) {
|
||||||
|
ttl_of_fake_packet = 64 - ttl - decrease_for;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ttl_of_fake_packet = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ttl_of_fake_packet;
|
||||||
|
}
|
25
src/ttltrack.h
Normal file
25
src/ttltrack.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef _TTLTRACK_H
|
||||||
|
#define _TTLTRACK_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "dnsredir.h"
|
||||||
|
|
||||||
|
typedef struct tcp_conntrack_info {
|
||||||
|
uint8_t is_ipv6;
|
||||||
|
uint8_t ttl;
|
||||||
|
uint32_t srcip[4];
|
||||||
|
uint16_t srcport;
|
||||||
|
uint32_t dstip[4];
|
||||||
|
uint16_t dstport;
|
||||||
|
} tcp_conntrack_info_t;
|
||||||
|
|
||||||
|
int tcp_handle_incoming(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
const uint8_t is_ipv6, const uint8_t ttl);
|
||||||
|
|
||||||
|
int tcp_handle_outgoing(const uint32_t srcip[4], const uint32_t dstip[4],
|
||||||
|
const uint16_t srcport, const uint16_t dstport,
|
||||||
|
tcp_conntrack_info_t *conn_info,
|
||||||
|
const uint8_t is_ipv6);
|
||||||
|
|
||||||
|
int tcp_get_auto_ttl(const uint8_t ttl, const uint8_t decrease_for);
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user