|
|
@ -171,6 +171,7 @@ static struct option long_options[] = { |
|
|
|
{"native-frag", no_argument, 0, '*' }, |
|
|
|
{"reverse-frag",no_argument, 0, '(' }, |
|
|
|
{"max-payload", optional_argument, 0, '|' }, |
|
|
|
{"openvpn", no_argument, 0, '#' }, |
|
|
|
{0, 0, 0, 0 } |
|
|
|
}; |
|
|
|
|
|
|
@ -433,6 +434,16 @@ static int extract_sni(const char *pktdata, unsigned int pktlen, |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
static inline int is_openvpn_handshake(const char *pktdata, unsigned int pktlen) { |
|
|
|
/*
|
|
|
|
* 0x38 is P_CONTROL_HARD_RESET_CLIENT_V2 + peer_id(0), |
|
|
|
* 0x50 is P_CONTROL_HARD_RESET_CLIENT_V3 + peer_id(0) |
|
|
|
*/ |
|
|
|
return pktlen >= 16 |
|
|
|
&& ntohs(((uint16_t*)pktdata)[0]) == pktlen - 2 |
|
|
|
&& (pktdata[2] == '\x38' || pktdata[2] == '\x50'); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void change_window_size(const PWINDIVERT_TCPHDR ppTcpHdr, unsigned int size) { |
|
|
|
if (size >= 1 && size <= 0xFFFFu) { |
|
|
|
ppTcpHdr->Window = htons((u_short)size); |
|
|
@ -543,6 +554,7 @@ int main(int argc, char *argv[]) { |
|
|
|
} packet_type; |
|
|
|
int i, should_reinject, should_recalc_checksum = 0; |
|
|
|
int sni_ok = 0; |
|
|
|
int openvpn_handshake = 0; |
|
|
|
int opt; |
|
|
|
int packet_v4, packet_v6; |
|
|
|
HANDLE w_filter = NULL; |
|
|
@ -569,6 +581,7 @@ int main(int argc, char *argv[]) { |
|
|
|
do_dns_verb = 0, do_tcp_verb = 0, do_blacklist = 0, |
|
|
|
do_allow_no_sni = 0, |
|
|
|
do_fake_packet = 0, |
|
|
|
do_openvpn = 0, |
|
|
|
do_auto_ttl = 0, |
|
|
|
do_wrong_chksum = 0, |
|
|
|
do_wrong_seq = 0, |
|
|
@ -849,6 +862,9 @@ int main(int argc, char *argv[]) { |
|
|
|
free(autottl_copy); |
|
|
|
} |
|
|
|
break; |
|
|
|
case '#': // --openvpn
|
|
|
|
do_openvpn = 1; |
|
|
|
break; |
|
|
|
case '%': // --wrong-chksum
|
|
|
|
do_fake_packet = 1; |
|
|
|
do_wrong_chksum = 1; |
|
|
@ -924,6 +940,7 @@ int main(int argc, char *argv[]) { |
|
|
|
" (like file transfers) in already established sessions.\n" |
|
|
|
" May skip some huge HTTP requests from being processed.\n" |
|
|
|
" Default (if set): --max-payload 1200.\n" |
|
|
|
" --openvpn Detect OpenVPN TCP and fragment/send fake packet.\n" |
|
|
|
"\n"); |
|
|
|
puts("LEGACY modesets:\n" |
|
|
|
" -1 -p -r -s -f 2 -k 2 -n -e 2 (most compatible mode)\n" |
|
|
@ -971,7 +988,8 @@ int main(int argc, char *argv[]) { |
|
|
|
"Fake requests, TTL: %s (fixed: %hu, auto: %hu-%hu-%hu, min distance: %hu)\n" /* 16 */ |
|
|
|
"Fake requests, wrong checksum: %d\n" /* 17 */ |
|
|
|
"Fake requests, wrong SEQ/ACK: %d\n" /* 18 */ |
|
|
|
"Max payload size: %hu\n", /* 19 */ |
|
|
|
"Max payload size: %hu\n" /* 19 */ |
|
|
|
"OpenVPN: %d\n", /* 20 */ |
|
|
|
do_passivedpi, /* 1 */ |
|
|
|
(do_fragment_http ? http_fragment_size : 0), /* 2 */ |
|
|
|
(do_fragment_http_persistent ? http_fragment_size : 0),/* 3 */ |
|
|
@ -992,7 +1010,8 @@ int main(int argc, char *argv[]) { |
|
|
|
do_auto_ttl ? auto_ttl_max : 0, ttl_min_nhops, |
|
|
|
do_wrong_chksum, /* 17 */ |
|
|
|
do_wrong_seq, /* 18 */ |
|
|
|
max_payload_size /* 19 */ |
|
|
|
max_payload_size, /* 19 */ |
|
|
|
do_openvpn /* 20 */ |
|
|
|
); |
|
|
|
|
|
|
|
if (do_fragment_http && http_fragment_size > 2 && !do_native_frag) { |
|
|
@ -1119,7 +1138,7 @@ int main(int argc, char *argv[]) { |
|
|
|
*/ |
|
|
|
else if (addr.Outbound && |
|
|
|
((do_fragment_https ? packet_dataLen == https_fragment_size : 0) || |
|
|
|
packet_dataLen > 16) && |
|
|
|
packet_dataLen >= 16) && |
|
|
|
ppTcpHdr->DstPort != htons(80) && |
|
|
|
(do_fake_packet || do_native_frag) |
|
|
|
) |
|
|
@ -1129,7 +1148,9 @@ int main(int argc, char *argv[]) { |
|
|
|
* But if the packet is more than 2 bytes, check ClientHello byte. |
|
|
|
*/ |
|
|
|
if ((packet_dataLen == 2 && memcmp(packet_data, "\x16\x03", 2) == 0) || |
|
|
|
(packet_dataLen >= 3 && memcmp(packet_data, "\x16\x03\x01", 3) == 0)) |
|
|
|
(packet_dataLen >= 3 && memcmp(packet_data, "\x16\x03\x01", 3) == 0) || |
|
|
|
(do_openvpn && (openvpn_handshake = is_openvpn_handshake(packet_data, packet_dataLen))) |
|
|
|
) |
|
|
|
{ |
|
|
|
if (do_blacklist) { |
|
|
|
sni_ok = extract_sni(packet_data, packet_dataLen, |
|
|
@ -1140,6 +1161,7 @@ int main(int argc, char *argv[]) { |
|
|
|
blackwhitelist_check_hostname(host_addr, host_len) |
|
|
|
) || |
|
|
|
(do_blacklist && !sni_ok && do_allow_no_sni) || |
|
|
|
(do_openvpn && openvpn_handshake) || |
|
|
|
(!do_blacklist) |
|
|
|
) |
|
|
|
{ |
|
|
|