OpenVPN detection & fragmentation/fake packet support

This commit is contained in:
ValdikSS 2022-07-21 14:47:13 +03:00
parent 4f18a73239
commit ecc681a60b
2 changed files with 27 additions and 5 deletions

View File

@ -19,7 +19,7 @@ CFLAGS = -std=c99 -pie -fPIE -pipe -I$(WINDIVERTHEADERS) -L$(WINDIVERTLIBS) \
-Wnull-dereference -Warray-bounds=2 -Wimplicit-fallthrough=3 \
-Wstringop-overflow=4 \
-Wformat-signedness -Wstrict-overflow=2 -Wcast-align=strict \
-Wfloat-equal -Wcast-align -Wsign-conversion \
-Wfloat-equal -Wcast-align -Wsign-conversion -Wno-stringop-overflow -Wno-stringop-overread \
#-fstack-protector-strong
LDFLAGS = -fstack-protector -Wl,-O1,-pie,--dynamicbase,--nxcompat,--sort-common,--as-needed \
-Wl,--image-base,0x140000000 -Wl,--disable-auto-image-base

View File

@ -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)
)
{