diff --git a/docs/readme.eng.md b/docs/readme.eng.md index 4872e77..8762d53 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -129,7 +129,7 @@ nfqws takes the following parameters: --qnum= --wsize=[:] ; change window size in SYN,ACK packets. default is not to change scale factor (OBSOLETE !) --wssize=[:] ; change window size in outgoing packets. default scale factor is 0. (see CONNTRACK) - --wssize-cutoff=N ; apply server wsize only to packet numbers less than N + --wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --ctrack-timeouts=S:E:F ; internal conntrack timeouts for SYN, ESTABLISHED and FIN stages. default 60:300:60 --hostcase ; change Host: => host: --hostspell=HoSt ; exact spelling of the "Host" header. must be 4 chars. default is "host" @@ -154,7 +154,7 @@ nfqws takes the following parameters: --dpi-desync-fake-http= ; file containing fake http request. replacement for built-in --dpi-desync-fake-tls= ; file containing fake TLS ClientHello (for https). replacement for built-in --dpi-desync-fake-unknown= ; file containing unknown protocol fake payload. default is 256 zeroes - --dpi-desync-cutoff=N ; apply dpi desync only to packet numbers less than N + --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --hostlist= ; apply fooling only to the listed hosts (one host per line, subdomains auto apply) ``` @@ -337,9 +337,10 @@ Linux can overcome this using connbytes filter but other OS may not include simi In http(s) case wssize stops after the first http request or TLS ClientHello. -If you deal with a non-http(s) protocol you need `--wssize-cutoff`. It sets the number of the outgoing packet where wssize stops. +If you deal with a non-http(s) protocol you need `--wssize-cutoff`. It sets the threshold where wssize stops. -(numbering starts from 1). +Threshold can be prefixed with 'n' (packet number starting from 1), 'd' (data packet number starting from 1), +'s' (relative sequence number - sent by client bytes + 1). If a http request or TLS ClientHello packet is detected wssize stops immediately ignoring wssize-cutoff option. @@ -373,8 +374,9 @@ to extract the host name. `--wssize` may slow down sites and/or increase response time. It's desired to use another methods if possible. -`--dpi-desync-cutoff` allows you to set the limit on the number of the outgoing packet, at which it stops -applying dpi-desync. Useful with `--dpi-desync-any-protocol=1`. +`--dpi-desync-cutoff` allows you to set the threshold at which it stops applying dpi-desync. +Can be prefixed with 'n', 'd', 's' symbol the same way as `--wssize-cutoff`. +Useful with `--dpi-desync-any-protocol=1`. If the connection falls out of the conntrack and --dpi-desync-cutoff is set, dpi desync will not be applied. Set conntrack timeouts appropriately. diff --git a/docs/readme.txt b/docs/readme.txt index c3138f5..049a757 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -181,7 +181,7 @@ nfqws --qnum=N ; номер очереди N --wsize=[:] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) --wssize=[:] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) - --wssize-cutoff=N ; изменять server window size в исходящих пакетах по номеру меньше N + --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --ctrack-timeouts=S:E:F ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN. по умолчанию 60:300:60 --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета @@ -202,7 +202,7 @@ nfqws --dpi-desync-fake-http= ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному w3.org --dpi-desync-fake-tls= ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному w3.org --dpi-desync-fake-unknown= ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт - --dpi-desync-cutoff=N ; применять dpi desync только к исходящим пакетам по номеру меньше N + --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --hostlist= ; применять дурение только к хостам из листа Параметры манипуляции могут сочетаться в любых комбинациях. @@ -378,8 +378,9 @@ conntrack - простенький, он не писался с учетом в знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello. -Если вы имеете дело с не http(s), то вам потребуется параметр --wssize-cutoff. Он устанавливает номер исходящего -пакета, с которого действие wssize прекращается (нумерация с 1 по аналогии connbytes). +Если вы имеете дело с не http(s), то вам потребуется параметр --wssize-cutoff. Он устанавливает предел, с которого действие +wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number, +проще говоря количество переданных клиентом байтов + 1. Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff. Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр --ctrack-timeouts. Таймаут по умолчанию низкий - всего 5 минут. @@ -402,8 +403,9 @@ window size итоговый размер окна стал максимальн --wssize может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы обхода DPI, лучше применять их. ---dpi-desync-cutoff позволяет задать предел по номеру исходящего пакета, при достижении которого прекращается -применение dpi-desync. Полезно совместно с --dpi-desync-any-protocol=1. +--dpi-desync-cutoff позволяет задать предел, при достижении которого прекращается применение dpi-desync. +Доступны префиксы n,d,s по аналогии с --wssize-cutoff. +Полезно совместно с --dpi-desync-any-protocol=1. На склонных к бездействию соединениях следует изменить таймауты conntrack. Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет. diff --git a/nfq/conntrack.c b/nfq/conntrack.c index a1b396d..d9ed424 100644 --- a/nfq/conntrack.c +++ b/nfq/conntrack.c @@ -150,18 +150,22 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr scale = tcp_find_scale_factor(tcphdr); if (bReverse) { - t->seq_last = htonl(tcphdr->th_ack); - t->ack_last = htonl(tcphdr->th_seq) + len_payload; + t->pos_orig = t->seq_last = htonl(tcphdr->th_ack); + t->ack_last = htonl(tcphdr->th_seq); + t->pos_reply = t->ack_last + len_payload; t->pcounter_reply++; + t->pdcounter_reply+=!!len_payload; t->winsize_reply = htons(tcphdr->th_win); if (scale!=SCALE_NONE) t->scale_reply = scale; } else { - t->seq_last = htonl(tcphdr->th_seq) + len_payload; - t->ack_last = htonl(tcphdr->th_ack); + t->seq_last = htonl(tcphdr->th_seq); + t->pos_orig = t->seq_last + len_payload; + t->pos_reply = t->ack_last = htonl(tcphdr->th_ack); t->pcounter_orig++; + t->pdcounter_orig+=!!len_payload; t->winsize_orig = htons(tcphdr->th_win); if (scale!=SCALE_NONE) t->scale_orig = scale; } @@ -276,12 +280,14 @@ void ConntrackPoolPurge(t_conntrack *p) HASH_ITER(hh, p, t, tmp) { \ *sa1=0; inet_ntop(AF_INET##f, &t->conn.e1.adr, sa1, sizeof(sa1)); \ *sa2=0; inet_ntop(AF_INET##f, &t->conn.e2.adr, sa2, sizeof(sa2)); \ - printf("[%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu packets_orig=%llu packets_reply=%llu seq0=%u rseq=%u ack0=%u rack=%u wsize_orig=%u:%d wsize_reply=%u:%d cutoff=%u wss_cutoff=%u d_cutoff=%u\n", \ + printf("[%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu packets_orig=d%llu/n%llu packets_reply=d%llu/n%llu seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d cutoff=%u wss_cutoff=%u d_cutoff=%u\n", \ sa1, t->conn.e1.port, sa2, t->conn.e2.port, \ connstate_s[t->track.state], \ (unsigned long long)t->track.t_start, (unsigned long long)(t->track.t_last - t->track.t_start), (unsigned long long)(tnow - t->track.t_last), \ - (unsigned long long)t->track.pcounter_orig, (unsigned long long)t->track.pcounter_reply, \ - t->track.seq0, t->track.seq_last - t->track.seq0, t->track.ack0, t->track.ack_last - t->track.ack0, \ + (unsigned long long)t->track.pdcounter_orig, (unsigned long long)t->track.pcounter_orig, \ + (unsigned long long)t->track.pdcounter_reply, (unsigned long long)t->track.pcounter_reply,\ + t->track.seq0, t->track.seq_last - t->track.seq0, t->track.pos_orig - t->track.seq0, \ + t->track.ack0, t->track.ack_last - t->track.ack0, t->track.pos_reply - t->track.ack0, \ t->track.winsize_orig, t->track.scale_orig==SCALE_NONE ? -1 : t->track.scale_orig, \ t->track.winsize_reply, t->track.scale_reply==SCALE_NONE ? -1 : t->track.scale_reply, \ t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff); \ diff --git a/nfq/conntrack.h b/nfq/conntrack.h index d062a77..9f63af1 100644 --- a/nfq/conntrack.h +++ b/nfq/conntrack.h @@ -49,8 +49,10 @@ typedef struct t_connstate state; time_t t_start, t_last; uint32_t seq0, ack0; // starting seq and ack - uint32_t seq_last, ack_last; // current seq and ack + uint32_t seq_last, ack_last; // last seen seq and ack + uint32_t pos_orig, pos_reply; // seq_last+payload, ack_last+payload uint64_t pcounter_orig, pcounter_reply; // packet counter + uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload) uint16_t winsize_orig, winsize_reply; // last seen window size uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none diff --git a/nfq/desync.c b/nfq/desync.c index 618eade..a2b5e5e 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -106,14 +106,29 @@ static bool rawsend_rep(const struct sockaddr* dst,uint32_t fwmark,const void *d } +static uint64_t cutoff_get_limit(t_ctrack *ctrack, char mode) +{ + switch(mode) + { + case 'n': return ctrack->pcounter_orig; + case 'd': return ctrack->pdcounter_orig; + case 's': return ctrack->seq_last - ctrack->seq0; + default: return 0; + } +} +static bool cutoff_test(t_ctrack *ctrack, uint64_t cutoff, char mode) +{ + return cutoff && cutoff_get_limit(ctrack, mode)>=cutoff; +} static void maybe_cutoff(t_ctrack *ctrack) { if (ctrack) { - ctrack->b_wssize_cutoff |= params.wssize_cutoff && ctrack->pcounter_orig>=params.wssize_cutoff; - ctrack->b_desync_cutoff |= params.desync_cutoff && ctrack->pcounter_orig>=params.desync_cutoff; - - ctrack->b_cutoff |= (!params.wssize || ctrack->b_wssize_cutoff) && !params.desync_cutoff; + ctrack->b_wssize_cutoff |= cutoff_test(ctrack, params.wssize_cutoff, params.wssize_cutoff_mode); + ctrack->b_desync_cutoff |= cutoff_test(ctrack, params.desync_cutoff, params.desync_cutoff_mode); + + // we do not need conntrack entry anymore if all cutoff conditions are either not defined or reached + ctrack->b_cutoff |= (!params.wssize || ctrack->b_wssize_cutoff) && (!params.desync_cutoff || ctrack->b_desync_cutoff); } } static void wssize_cutoff(t_ctrack *ctrack) @@ -146,6 +161,9 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (ConntrackPoolFeed(¶ms.conntrack, ip, ip6hdr, tcphdr, len_payload, &ctrack, &bReverse)) maybe_cutoff(ctrack); } + + //ConntrackPoolDump(¶ms.conntrack); + if (params.wsize && tcp_synack_segment(tcphdr)) { tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale); @@ -154,10 +172,25 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if (bReverse) return res; // nothing to do. do not waste cpu - if (params.wssize && (ctrack && !ctrack->b_wssize_cutoff)) + if (params.wssize) { - tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale); - res=modify; + if (ctrack) + { + if (ctrack->b_wssize_cutoff) + { + DLOG("not changing wssize. wssize-cutoff reached\n"); + } + else + { + if (params.wssize_cutoff) DLOG("wssize-cutoff not reached (mode %c): %llu/%u\n", params.wssize_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.wssize_cutoff_mode), params.wssize_cutoff); + tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale); + res=modify; + } + } + else + { + DLOG("not changing wssize. wssize is set but conntrack entry is missing\n"); + } } if (params.desync_mode0!=DESYNC_NONE || params.desync_mode!=DESYNC_NONE) // save some cpu @@ -186,6 +219,24 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc return res; } + if (params.desync_cutoff) + { + if (ctrack) + { + if (ctrack->b_desync_cutoff) + { + DLOG("not desyncing. desync-cutoff reached (mode %c): %llu/%u\n", params.desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.desync_cutoff_mode), params.desync_cutoff); + return res; + } + DLOG("desync-cutoff not reached (mode %c): %llu/%u\n", params.desync_cutoff_mode, (unsigned long long)cutoff_get_limit(ctrack,params.desync_cutoff_mode), params.desync_cutoff); + } + else + { + DLOG("not desyncing. desync-cutoff is set but conntrack entry is missing\n"); + return res; + } + } + if (!params.wssize && params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu if (!(tcphdr->th_flags & TH_SYN) && len_payload) @@ -200,6 +251,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc if ((bIsHttp = IsHttp(data_payload,len_payload))) { DLOG("packet contains HTTP request\n") + if (params.wssize) DLOG("forced wssize-cutoff\n"); wssize_cutoff(ctrack); fake = params.fake_http; fake_size = params.fake_http_size; @@ -213,6 +265,7 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc else if (IsTLSClientHello(data_payload,len_payload)) { DLOG("packet contains TLS ClientHello\n") + if (params.wssize) DLOG("forced wssize-cutoff\n"); wssize_cutoff(ctrack); fake = params.fake_tls; fake_size = params.fake_tls_size; @@ -280,16 +333,6 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc } if (params.desync_mode==DESYNC_NONE) return res; - if (ctrack && ctrack->b_desync_cutoff) - { - DLOG("not desyncing. cutoff reached : %llu/%u\n", (unsigned long long)ctrack->pcounter_orig, params.desync_cutoff); - return res; - } - if (!ctrack && params.desync_cutoff) - { - DLOG("not desyncing. desync_cutoff is set but conntrack entry is missing\n"); - return res; - } if (params.debug) { diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 882f5e6..699632b 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -473,7 +473,7 @@ static void exithelp() " --uid=uid[:gid]\t\t\t; drop root privs\n" " --wsize=[:]\t; set window size. 0 = do not modify. OBSOLETE !\n" " --wssize=[:]; set window size for server. 0 = do not modify. default scale_factor = 0.\n" - " --wssize-cutoff=N\t\t\t; apply server wsize only to packet numbers less than N\n" + " --wssize-cutoff=[n|d|s]N\t\t; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n" " --ctrack-timeouts=S:E:F\t\t; internal conntrack timeouts for SYN, ESTABLISHED and FIN stage. default %u:%u:%u\n" " --hostcase\t\t\t\t; change Host: => host:\n" " --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" @@ -500,7 +500,7 @@ static void exithelp() " --dpi-desync-fake-http=\t; file containing fake http request\n" " --dpi-desync-fake-tls=\t; file containing fake TLS ClientHello (for https)\n" " --dpi-desync-fake-unknown=\t; file containing unknown protocol fake payload\n" - " --dpi-desync-cutoff=N\t\t\t; apply dpi desync only to packet numbers less than N\n" + " --dpi-desync-cutoff=[n|d|s]N\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n" " --hostlist=\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply)\n", CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, #if defined(__linux__) || defined(SO_USER_COOKIE) @@ -532,6 +532,23 @@ static void exit_clean(int code) exit(code); } +static bool parse_cutoff(const char *opt, unsigned int *value, char *mode) +{ + *mode = (*opt=='n' || *opt=='d' || *opt=='s') ? *opt++ : 'n'; + return sscanf(opt, "%u", value)>0; +} +static bool parse_badseq_increment(const char *opt, uint32_t *value) +{ + if ((opt[0]=='0' && opt[1]=='x' || opt[0]=='-' && opt[1]=='0' && opt[2]=='x') && sscanf(opt+2+(opt[0]=='-'), "%X", (int32_t*)value)>0) + { + if (opt[0]=='-') params.desync_badseq_increment = -params.desync_badseq_increment; + return true; + } + else + { + return sscanf(opt, "%d", (int32_t*)value)>0; + } +} int main(int argc, char **argv) { int result, v; @@ -561,6 +578,7 @@ int main(int argc, char **argv) params.desync_ttl6 = 0xFF; // unused params.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT; params.desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT; + params.wssize_cutoff_mode = params.desync_cutoff_mode = 'n'; // packet number by default if (can_drop_root()) // are we root ? { @@ -666,7 +684,7 @@ int main(int argc, char **argv) case 5: /* uid */ params.gid = 0x7FFFFFFF; // default gid. drop gid=0 params.droproot = true; - if (!sscanf(optarg, "%u:%u", ¶ms.uid, ¶ms.gid)) + if (sscanf(optarg, "%u:%u", ¶ms.uid, ¶ms.gid)<1) { fprintf(stderr, "--uid should be : uid[:gid]\n"); exit_clean(1); @@ -681,7 +699,7 @@ int main(int argc, char **argv) exit_clean(1); break; case 8: /* wssize-cutoff */ - if (!sscanf(optarg, "%u", ¶ms.wssize_cutoff)) + if (!parse_cutoff(optarg, ¶ms.wssize_cutoff, ¶ms.wssize_cutoff_mode)) { fprintf(stderr, "invalid wssize-cutoff value\n"); exit_clean(1); @@ -753,7 +771,7 @@ int main(int argc, char **argv) case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */ #if defined(__linux__) || defined(SO_USER_COOKIE) params.desync_fwmark = 0; - if (!sscanf(optarg, "0x%X", ¶ms.desync_fwmark)) sscanf(optarg, "%u", ¶ms.desync_fwmark); + if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark)<=0) sscanf(optarg, "%u", ¶ms.desync_fwmark); if (!params.desync_fwmark) { fprintf(stderr, "fwmark/sockarg should be decimal or 0xHEX and should not be zero\n"); @@ -827,20 +845,15 @@ int main(int argc, char **argv) } break; case 23: /* dpi-desync-badseq-increments */ - if ((optarg[0]=='0' && optarg[1]=='x' || optarg[0]=='-' && optarg[1]=='0' && optarg[2]=='x') && sscanf(optarg+2+(optarg[0]=='-'), "%X", (int32_t*)¶ms.desync_badseq_increment)) - { - if (optarg[0]=='-') params.desync_badseq_increment = -params.desync_badseq_increment; - } else if (!sscanf(optarg, "%d", (int32_t*)¶ms.desync_badseq_increment)) + if (!parse_badseq_increment(optarg,¶ms.desync_badseq_increment)) { fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); } +printf("FFF %08X\n", params.desync_badseq_increment); break; case 24: /* dpi-desync-badack-increment */ - if ((optarg[0]=='0' && optarg[1]=='x' || optarg[0]=='-' && optarg[1]=='0' && optarg[2]=='x') && sscanf(optarg+2+(optarg[0]=='-'), "%X", (int32_t*)¶ms.desync_badseq_ack_increment)) - { - if (optarg[0]=='-') params.desync_badseq_ack_increment = -params.desync_badseq_ack_increment; - } else if (!sscanf(optarg, "%d", (int32_t*)¶ms.desync_badseq_ack_increment)) + if (!parse_badseq_increment(optarg,¶ms.desync_badseq_ack_increment)) { fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n"); exit_clean(1); @@ -874,7 +887,7 @@ int main(int argc, char **argv) } break; case 29: /* desync-cutoff */ - if (!sscanf(optarg, "%u", ¶ms.desync_cutoff)) + if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode)) { fprintf(stderr, "invalid desync-cutoff value\n"); exit_clean(1); diff --git a/nfq/params.h b/nfq/params.h index 30272ee..83298e3 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -25,6 +25,7 @@ struct params_s bool debug; uint16_t wsize,wssize; uint8_t wscale,wsscale; + char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence unsigned int wssize_cutoff; #ifdef __linux__ int qnum; @@ -36,6 +37,7 @@ struct params_s enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; bool desync_retrans,desync_skip_nosni,desync_any_proto; int desync_repeats,desync_split_pos; + char desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence unsigned int desync_cutoff; uint8_t desync_ttl, desync_ttl6; uint8_t desync_tcp_fooling_mode;