nfqws: n|d|s cutoff modes

This commit is contained in:
bol-van 2021-12-27 16:51:30 +03:00
parent 2a3b9cf982
commit aece656a8d
7 changed files with 121 additions and 51 deletions

View File

@ -129,7 +129,7 @@ nfqws takes the following parameters:
--qnum=<nfqueue_number> --qnum=<nfqueue_number>
--wsize=<winsize>[:<scale_factor>] ; change window size in SYN,ACK packets. default is not to change scale factor (OBSOLETE !) --wsize=<winsize>[:<scale_factor>] ; change window size in SYN,ACK packets. default is not to change scale factor (OBSOLETE !)
--wssize=<winsize>[:<scale_factor>] ; change window size in outgoing packets. default scale factor is 0. (see CONNTRACK) --wssize=<winsize>[:<scale_factor>] ; 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 --ctrack-timeouts=S:E:F ; internal conntrack timeouts for SYN, ESTABLISHED and FIN stages. default 60:300:60
--hostcase ; change Host: => host: --hostcase ; change Host: => host:
--hostspell=HoSt ; exact spelling of the "Host" header. must be 4 chars. default is "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=<filename> ; file containing fake http request. replacement for built-in --dpi-desync-fake-http=<filename> ; file containing fake http request. replacement for built-in
--dpi-desync-fake-tls=<filename> ; file containing fake TLS ClientHello (for https). replacement for built-in --dpi-desync-fake-tls=<filename> ; file containing fake TLS ClientHello (for https). replacement for built-in
--dpi-desync-fake-unknown=<filename> ; file containing unknown protocol fake payload. default is 256 zeroes --dpi-desync-fake-unknown=<filename> ; 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=<filename> ; apply fooling only to the listed hosts (one host per line, subdomains auto apply) --hostlist=<filename> ; 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. 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. 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. `--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 `--dpi-desync-cutoff` allows you to set the threshold at which it stops applying dpi-desync.
applying dpi-desync. Useful with `--dpi-desync-any-protocol=1`. 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. If the connection falls out of the conntrack and --dpi-desync-cutoff is set, dpi desync will not be applied.
Set conntrack timeouts appropriately. Set conntrack timeouts appropriately.

View File

@ -181,7 +181,7 @@ nfqws
--qnum=N ; номер очереди N --qnum=N ; номер очереди N
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) --wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) --wssize=<winsize>[:<scale_factor>] ; менять 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 --ctrack-timeouts=S:E:F ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN. по умолчанию 60:300:60
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
@ -202,7 +202,7 @@ nfqws
--dpi-desync-fake-http=<filename> ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному w3.org --dpi-desync-fake-http=<filename> ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному w3.org
--dpi-desync-fake-tls=<filename> ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному w3.org --dpi-desync-fake-tls=<filename> ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному w3.org
--dpi-desync-fake-unknown=<filename> ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт --dpi-desync-fake-unknown=<filename> ; файл, содержащий фейковый пейлоад неизвестного протокола для 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=<filename> ; применять дурение только к хостам из листа --hostlist=<filename> ; применять дурение только к хостам из листа
Параметры манипуляции могут сочетаться в любых комбинациях. Параметры манипуляции могут сочетаться в любых комбинациях.
@ -378,8 +378,9 @@ conntrack - простенький, он не писался с учетом в
знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически.
В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет.
В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello. В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello.
Если вы имеете дело с не http(s), то вам потребуется параметр --wssize-cutoff. Он устанавливает номер исходящего Если вы имеете дело с не http(s), то вам потребуется параметр --wssize-cutoff. Он устанавливает предел, с которого действие
пакета, с которого действие wssize прекращается (нумерация с 1 по аналогии connbytes). wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number,
проще говоря количество переданных клиентом байтов + 1.
Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff. Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff.
Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр --ctrack-timeouts. Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр --ctrack-timeouts.
Таймаут по умолчанию низкий - всего 5 минут. Таймаут по умолчанию низкий - всего 5 минут.
@ -402,8 +403,9 @@ window size итоговый размер окна стал максимальн
--wssize может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы --wssize может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы
обхода DPI, лучше применять их. обхода DPI, лучше применять их.
--dpi-desync-cutoff позволяет задать предел по номеру исходящего пакета, при достижении которого прекращается --dpi-desync-cutoff позволяет задать предел, при достижении которого прекращается применение dpi-desync.
применение dpi-desync. Полезно совместно с --dpi-desync-any-protocol=1. Доступны префиксы n,d,s по аналогии с --wssize-cutoff.
Полезно совместно с --dpi-desync-any-protocol=1.
На склонных к бездействию соединениях следует изменить таймауты conntrack. На склонных к бездействию соединениях следует изменить таймауты conntrack.
Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет. Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет.

View File

@ -150,18 +150,22 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
scale = tcp_find_scale_factor(tcphdr); scale = tcp_find_scale_factor(tcphdr);
if (bReverse) if (bReverse)
{ {
t->seq_last = htonl(tcphdr->th_ack); t->pos_orig = t->seq_last = htonl(tcphdr->th_ack);
t->ack_last = htonl(tcphdr->th_seq) + len_payload; t->ack_last = htonl(tcphdr->th_seq);
t->pos_reply = t->ack_last + len_payload;
t->pcounter_reply++; t->pcounter_reply++;
t->pdcounter_reply+=!!len_payload;
t->winsize_reply = htons(tcphdr->th_win); t->winsize_reply = htons(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_reply = scale; if (scale!=SCALE_NONE) t->scale_reply = scale;
} }
else else
{ {
t->seq_last = htonl(tcphdr->th_seq) + len_payload; t->seq_last = htonl(tcphdr->th_seq);
t->ack_last = htonl(tcphdr->th_ack); t->pos_orig = t->seq_last + len_payload;
t->pos_reply = t->ack_last = htonl(tcphdr->th_ack);
t->pcounter_orig++; t->pcounter_orig++;
t->pdcounter_orig+=!!len_payload;
t->winsize_orig = htons(tcphdr->th_win); t->winsize_orig = htons(tcphdr->th_win);
if (scale!=SCALE_NONE) t->scale_orig = scale; if (scale!=SCALE_NONE) t->scale_orig = scale;
} }
@ -276,12 +280,14 @@ void ConntrackPoolPurge(t_conntrack *p)
HASH_ITER(hh, p, t, tmp) { \ HASH_ITER(hh, p, t, tmp) { \
*sa1=0; inet_ntop(AF_INET##f, &t->conn.e1.adr, sa1, sizeof(sa1)); \ *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)); \ *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, \ sa1, t->conn.e1.port, sa2, t->conn.e2.port, \
connstate_s[t->track.state], \ 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.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, \ (unsigned long long)t->track.pdcounter_orig, (unsigned long long)t->track.pcounter_orig, \
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_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_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.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); \ t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff); \

View File

@ -49,8 +49,10 @@ typedef struct
t_connstate state; t_connstate state;
time_t t_start, t_last; time_t t_start, t_last;
uint32_t seq0, ack0; // starting seq and ack 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 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 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 uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none

View File

@ -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) static void maybe_cutoff(t_ctrack *ctrack)
{ {
if (ctrack) if (ctrack)
{ {
ctrack->b_wssize_cutoff |= params.wssize_cutoff && ctrack->pcounter_orig>=params.wssize_cutoff; ctrack->b_wssize_cutoff |= cutoff_test(ctrack, params.wssize_cutoff, params.wssize_cutoff_mode);
ctrack->b_desync_cutoff |= params.desync_cutoff && ctrack->pcounter_orig>=params.desync_cutoff; ctrack->b_desync_cutoff |= cutoff_test(ctrack, params.desync_cutoff, params.desync_cutoff_mode);
ctrack->b_cutoff |= (!params.wssize || ctrack->b_wssize_cutoff) && !params.desync_cutoff; // 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) 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(&params.conntrack, ip, ip6hdr, tcphdr, len_payload, &ctrack, &bReverse)) if (ConntrackPoolFeed(&params.conntrack, ip, ip6hdr, tcphdr, len_payload, &ctrack, &bReverse))
maybe_cutoff(ctrack); maybe_cutoff(ctrack);
} }
//ConntrackPoolDump(&params.conntrack);
if (params.wsize && tcp_synack_segment(tcphdr)) if (params.wsize && tcp_synack_segment(tcphdr))
{ {
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale); 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 (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); if (ctrack)
res=modify; {
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 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; 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 (!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) 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))) if ((bIsHttp = IsHttp(data_payload,len_payload)))
{ {
DLOG("packet contains HTTP request\n") DLOG("packet contains HTTP request\n")
if (params.wssize) DLOG("forced wssize-cutoff\n");
wssize_cutoff(ctrack); wssize_cutoff(ctrack);
fake = params.fake_http; fake = params.fake_http;
fake_size = params.fake_http_size; 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)) else if (IsTLSClientHello(data_payload,len_payload))
{ {
DLOG("packet contains TLS ClientHello\n") DLOG("packet contains TLS ClientHello\n")
if (params.wssize) DLOG("forced wssize-cutoff\n");
wssize_cutoff(ctrack); wssize_cutoff(ctrack);
fake = params.fake_tls; fake = params.fake_tls;
fake_size = params.fake_tls_size; 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 (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) if (params.debug)
{ {

View File

@ -473,7 +473,7 @@ static void exithelp()
" --uid=uid[:gid]\t\t\t; drop root privs\n" " --uid=uid[:gid]\t\t\t; drop root privs\n"
" --wsize=<window_size>[:<scale_factor>]\t; set window size. 0 = do not modify. OBSOLETE !\n" " --wsize=<window_size>[:<scale_factor>]\t; set window size. 0 = do not modify. OBSOLETE !\n"
" --wssize=<window_size>[:<scale_factor>]; set window size for server. 0 = do not modify. default scale_factor = 0.\n" " --wssize=<window_size>[:<scale_factor>]; 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" " --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" " --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" " --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=<filename>\t; file containing fake http request\n" " --dpi-desync-fake-http=<filename>\t; file containing fake http request\n"
" --dpi-desync-fake-tls=<filename>\t; file containing fake TLS ClientHello (for https)\n" " --dpi-desync-fake-tls=<filename>\t; file containing fake TLS ClientHello (for https)\n"
" --dpi-desync-fake-unknown=<filename>\t; file containing unknown protocol fake payload\n" " --dpi-desync-fake-unknown=<filename>\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=<filename>\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply)\n", " --hostlist=<filename>\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, CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN,
#if defined(__linux__) || defined(SO_USER_COOKIE) #if defined(__linux__) || defined(SO_USER_COOKIE)
@ -532,6 +532,23 @@ static void exit_clean(int code)
exit(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 main(int argc, char **argv)
{ {
int result, v; int result, v;
@ -561,6 +578,7 @@ int main(int argc, char **argv)
params.desync_ttl6 = 0xFF; // unused params.desync_ttl6 = 0xFF; // unused
params.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT; params.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
params.desync_badseq_ack_increment = BADSEQ_ACK_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 ? if (can_drop_root()) // are we root ?
{ {
@ -666,7 +684,7 @@ int main(int argc, char **argv)
case 5: /* uid */ case 5: /* uid */
params.gid = 0x7FFFFFFF; // default gid. drop gid=0 params.gid = 0x7FFFFFFF; // default gid. drop gid=0
params.droproot = true; params.droproot = true;
if (!sscanf(optarg, "%u:%u", &params.uid, &params.gid)) if (sscanf(optarg, "%u:%u", &params.uid, &params.gid)<1)
{ {
fprintf(stderr, "--uid should be : uid[:gid]\n"); fprintf(stderr, "--uid should be : uid[:gid]\n");
exit_clean(1); exit_clean(1);
@ -681,7 +699,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
break; break;
case 8: /* wssize-cutoff */ case 8: /* wssize-cutoff */
if (!sscanf(optarg, "%u", &params.wssize_cutoff)) if (!parse_cutoff(optarg, &params.wssize_cutoff, &params.wssize_cutoff_mode))
{ {
fprintf(stderr, "invalid wssize-cutoff value\n"); fprintf(stderr, "invalid wssize-cutoff value\n");
exit_clean(1); exit_clean(1);
@ -753,7 +771,7 @@ int main(int argc, char **argv)
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */ case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
#if defined(__linux__) || defined(SO_USER_COOKIE) #if defined(__linux__) || defined(SO_USER_COOKIE)
params.desync_fwmark = 0; params.desync_fwmark = 0;
if (!sscanf(optarg, "0x%X", &params.desync_fwmark)) sscanf(optarg, "%u", &params.desync_fwmark); if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark);
if (!params.desync_fwmark) if (!params.desync_fwmark)
{ {
fprintf(stderr, "fwmark/sockarg should be decimal or 0xHEX and should not be zero\n"); 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; break;
case 23: /* dpi-desync-badseq-increments */ 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*)&params.desync_badseq_increment)) if (!parse_badseq_increment(optarg,&params.desync_badseq_increment))
{
if (optarg[0]=='-') params.desync_badseq_increment = -params.desync_badseq_increment;
} else if (!sscanf(optarg, "%d", (int32_t*)&params.desync_badseq_increment))
{ {
fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
} }
printf("FFF %08X\n", params.desync_badseq_increment);
break; break;
case 24: /* dpi-desync-badack-increment */ 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*)&params.desync_badseq_ack_increment)) if (!parse_badseq_increment(optarg,&params.desync_badseq_ack_increment))
{
if (optarg[0]=='-') params.desync_badseq_ack_increment = -params.desync_badseq_ack_increment;
} else if (!sscanf(optarg, "%d", (int32_t*)&params.desync_badseq_ack_increment))
{ {
fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n"); fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
@ -874,7 +887,7 @@ int main(int argc, char **argv)
} }
break; break;
case 29: /* desync-cutoff */ case 29: /* desync-cutoff */
if (!sscanf(optarg, "%u", &params.desync_cutoff)) if (!parse_cutoff(optarg, &params.desync_cutoff, &params.desync_cutoff_mode))
{ {
fprintf(stderr, "invalid desync-cutoff value\n"); fprintf(stderr, "invalid desync-cutoff value\n");
exit_clean(1); exit_clean(1);

View File

@ -25,6 +25,7 @@ struct params_s
bool debug; bool debug;
uint16_t wsize,wssize; uint16_t wsize,wssize;
uint8_t wscale,wsscale; uint8_t wscale,wsscale;
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int wssize_cutoff; unsigned int wssize_cutoff;
#ifdef __linux__ #ifdef __linux__
int qnum; int qnum;
@ -36,6 +37,7 @@ struct params_s
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
bool desync_retrans,desync_skip_nosni,desync_any_proto; bool desync_retrans,desync_skip_nosni,desync_any_proto;
int desync_repeats,desync_split_pos; int desync_repeats,desync_split_pos;
char desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int desync_cutoff; unsigned int desync_cutoff;
uint8_t desync_ttl, desync_ttl6; uint8_t desync_ttl, desync_ttl6;
uint8_t desync_tcp_fooling_mode; uint8_t desync_tcp_fooling_mode;