diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index 5a2881a..3fb86f4 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/arm/nfqws b/binaries/arm/nfqws index b4b3671..cc57966 100755 Binary files a/binaries/arm/nfqws and b/binaries/arm/nfqws differ diff --git a/binaries/freebsd-x64/dvtws b/binaries/freebsd-x64/dvtws index 91c4b9b..dd08c73 100755 Binary files a/binaries/freebsd-x64/dvtws and b/binaries/freebsd-x64/dvtws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index c17afd0..f013a69 100755 Binary files a/binaries/mips32r1-lsb/nfqws and b/binaries/mips32r1-lsb/nfqws differ diff --git a/binaries/mips32r1-msb/nfqws b/binaries/mips32r1-msb/nfqws index 7227c91..947a9bd 100755 Binary files a/binaries/mips32r1-msb/nfqws and b/binaries/mips32r1-msb/nfqws differ diff --git a/binaries/mips64r2-msb/nfqws b/binaries/mips64r2-msb/nfqws index f15282d..e9163e5 100755 Binary files a/binaries/mips64r2-msb/nfqws and b/binaries/mips64r2-msb/nfqws differ diff --git a/binaries/ppc/nfqws b/binaries/ppc/nfqws index 7e700cf..646ef60 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/win64/WinDivert.dll b/binaries/win64/WinDivert.dll index 50ca874..628a8b4 100644 Binary files a/binaries/win64/WinDivert.dll and b/binaries/win64/WinDivert.dll differ diff --git a/binaries/win64/ip2net.exe b/binaries/win64/ip2net.exe index 5796e9c..9020266 100644 Binary files a/binaries/win64/ip2net.exe and b/binaries/win64/ip2net.exe differ diff --git a/binaries/win64/mdig.exe b/binaries/win64/mdig.exe index 8006737..1781520 100644 Binary files a/binaries/win64/mdig.exe and b/binaries/win64/mdig.exe differ diff --git a/binaries/win64/winws.exe b/binaries/win64/winws.exe index 96acdde..2cf5c1e 100644 Binary files a/binaries/win64/winws.exe and b/binaries/win64/winws.exe differ diff --git a/binaries/win64/zapret-winws/WinDivert.dll b/binaries/win64/zapret-winws/WinDivert.dll index 50ca874..628a8b4 100644 Binary files a/binaries/win64/zapret-winws/WinDivert.dll and b/binaries/win64/zapret-winws/WinDivert.dll differ diff --git a/binaries/win64/zapret-winws/winws.exe b/binaries/win64/zapret-winws/winws.exe index 96acdde..2cf5c1e 100644 Binary files a/binaries/win64/zapret-winws/winws.exe and b/binaries/win64/zapret-winws/winws.exe differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index a7af3b6..2399df1 100755 Binary files a/binaries/x86/nfqws and b/binaries/x86/nfqws differ diff --git a/binaries/x86_64/nfqws b/binaries/x86_64/nfqws index 7ee4528..0472a7f 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/blockcheck.sh b/blockcheck.sh index 834249c..ea23927 100755 --- a/blockcheck.sh +++ b/blockcheck.sh @@ -1009,7 +1009,7 @@ pktws_check_domain_http_bypass_() ok=1 } [ "$ret" != 0 -o "$SCANLEVEL" = force ] && { - [ "$sec" = 0 ] && { + if [ "$sec" = 0 ]; then pktws_curl_test_update $1 $3 $s --hostcase && { [ "$SCANLEVEL" = quick ] && return ok=1 @@ -1022,15 +1022,14 @@ pktws_check_domain_http_bypass_() } done done - } - [ "$sec" = 1 ] && { + else for pos in sni sniext; do pktws_curl_test_update $1 $3 $s --dpi-desync-split-tls=$pos && { [ "$SCANLEVEL" = quick ] && return ok=1 } done - } + fi for pos in 1 3 4 5 10 50; do s="--dpi-desync=split2 --dpi-desync-split-pos=$pos" if pktws_curl_test_update $1 $3 $s; then @@ -1100,6 +1099,22 @@ pktws_check_domain_http_bypass_() } done + for desync in split2 disorder2; do + s="--dpi-desync=$desync" + if [ "$sec" = 0 ]; then + for pos in method host; do + pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=1 --dpi-desync-split-http-req=$pos $e && [ "$SCANLEVEL" = quick ] && return + done + else + for pos in sni sniext; do + pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=1 --dpi-desync-split-tls=$pos $e && [ "$SCANLEVEL" = quick ] && return + done + fi + for pos in 2 3 4 5 10 50; do + pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=$(($pos - 1)) --dpi-desync-split-pos=$pos $e && [ "$SCANLEVEL" = quick ] && return + done + done + s="http_iana_org.bin" [ "$sec" = 0 ] || s="tls_clienthello_iana_org.bin" for desync in syndata syndata,split2 syndata,disorder2 syndata,split2 syndata,disorder2 ; do diff --git a/docs/changes.txt b/docs/changes.txt index 50ba608..9bf80dd 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -294,3 +294,8 @@ tpws: --split-tls tpws: --tlsrec=sniext nfqws: --dpi-desync-split-http-req, --dpi-desync-split-tls. multi segment TLS support for split. blockcheck: mdig dns cache + +v60 + +blockcheck: port block test, partial ip block test +nfqws: seqovl split/disorder modes diff --git a/docs/readme.eng.md b/docs/readme.eng.md index 392f25f..635761a 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -180,6 +180,8 @@ nfqws takes the following parameters: --dpi-desync-split-pos=<1..9216> ; data payload split position --dpi-desync-split-http-req=method|host ; split at specified logical part of plain http request --dpi-desync-split-tls=sni|sniext ; split at specified logical part of TLS ClientHello + --dpi-desync-split-seqovl= ; use sequence overlap before first sent original split segment + --dpi-desync-split-seqovl-pattern=|0xHEX ; pattern for the fake part of overlap --dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8. --dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32. --dpi-desync-badseq-increment= ; badseq fooling seq signed increment. default -10000 @@ -292,6 +294,16 @@ Mode `split2` disables sending of fake segments. It can be used as a faster alte In `disorder2` and 'split2` modes no fake packets are sent, so ttl and fooling options are not required. +`seqovl` adds to the first sent original segment (1st for split, 2nd for disorder) seqovl bytes to the beginning and decreases +sequence number. +In `split2` mode this creates partially in-window packet. OS receives only in-window part. +In `disorder2` mode OS receives fake and real part of the second segment but does not pass received data to the socket until first +segment is received. First segment overwrites fake part of the second segment. Then OS passes original data to the socket. +All unix OS preserve last received data. This may not be the case for Windows servers and may not work. +Disorder requires `seqovl` to be less than `split_pos`. Either statically defined or automatically calculated. +Otherwise desync is not possible and will not happen. +Method allows to avoid separate fakes. Fakes and real data are mixed. + `hopbyhop`, `destopt` and `ipfrag1` desync modes (they're not the same as `hopbyhop` fooling !) are ipv6 only. One `hop-by-hop`, `destination options` or `fragment` header is added to all desynced packets. Extra header increases packet size and can't be applied to the maximum size packets. diff --git a/docs/readme.txt b/docs/readme.txt index 2865ff9..cfd762f 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -1,4 +1,4 @@ -zapret v.59 +zapret v.60 English ------- @@ -253,6 +253,8 @@ nfqws --dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции --dpi-desync-split-http-req=method|host ; разбивка http request на указанном логическом месте --dpi-desync-split-tls=sni|sniext ; разбивка tls client hello на указанном логическом месте + --dpi-desync-split-seqovl= ; использовать sequence overlap перед первым отсылаемым оригинальным tcp сегментом + --dpi-desync-split-seqovl-pattern=|0xHEX ; чем заполнять фейковую часть overlap --dpi-desync-badseq-increment= ; инкремент sequence number для badseq. по умолчанию -10000 --dpi-desync-badack-increment= ; инкремент ack sequence number для badseq. по умолчанию -66000 --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных @@ -379,6 +381,26 @@ fakeknown отличается от fake тем, что применяется disorder2 и split2 не предполагают отсылку фейк пакетов, поэтому опции ttl и fooling неактуальны. +seqovl добавляет в начало первой отсылаемой части оригинального пакета (1 часть для split и 2 часть для disorder) +seqovl байт со смещенным в минус sequence number на величину seqovl. +В случае split2 расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, +поэтому новая пришедшая часть лишь частично находится в пределах текущего окна (in-window). +Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и начинается с начала window, +поэтому попадает в сокет. +Серверное приложение получает все, что реально отсылает клиент, отбрасывая фейковую out-of-window часть. +Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация. + +Для disorder2 overlap идет на 2-ю часть пакета. Обязательно, чтобы seqovl был меньше split_pos, иначе +все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня. +При соблюдении этого условия 2-я часть пакета является полностью in-window, +поэтому серверная ОС принимает ее целиком, включая фейк. Но поскольку начальная часть данных из 1 пакета еще не принята, +то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение. Как только приходит 1-я часть пакета, +она переписывает фейковую часть в памяти ядра. Ядро получает данные из 1 и 2 части, поэтому далее +идет отправка в сокет приложения. Таково поведение всех unix ОС - оставлять последние принятые данные. +Для windows серверов может быть наоборот, поэтому не факт, что такой вариант будет на них работать. +Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными. +split/disorder вместо split2/disorder2 по-прежнему добавляют дополнительные отдельные фейки. + Режимы десинхронизации hopbyhop, destopt и ipfrag1 (не путать с fooling !) относятся только к ipv6 и заключается в добавлении хедера "hop-by-hop options" , "destination options" или "fragment" во все пакеты, попадающие под десинхронизацию. Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено diff --git a/nfq/desync.c b/nfq/desync.c index 5f49c65..2911a24 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -959,17 +959,41 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_DISORDER2: if (split_pos) { - uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100]; - size_t fakeseg_len; + uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; + size_t seg_len; + + if (params.desync_seqovl>=split_pos) + { + DLOG("seqovl>=split_pos. desync is not possible.\n") + return verdict; + } if (split_posth_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, + if (params.desync_seqovl) + { + seg_len = len_payload-split_pos+params.desync_seqovl; + if (seg_len>sizeof(fakeseg)) + { + DLOG("seqovl is too large\n") + return verdict; + } + fill_pattern(fakeseg,params.desync_seqovl,params.seqovl_pattern,sizeof(params.seqovl_pattern)); + memcpy(fakeseg+params.desync_seqovl,data_payload+split_pos,len_payload-split_pos); + seg = fakeseg; + } + else + { + seg = data_payload+split_pos; + seg_len = len_payload-split_pos; + } + + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(net32_add(tcphdr->th_seq,split_pos),-params.desync_seqovl), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, ttl_orig,fooling_orig,params.desync_badseq_increment,params.desync_badseq_ack_increment, - data_payload+split_pos, len_payload-split_pos, pkt1, &pkt1_len)) + seg, seg_len, pkt1, &pkt1_len)) return verdict; - DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos) - hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n") + DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ",split_pos,len_payload-1, len_payload-split_pos, params.desync_seqovl) + hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n") if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return verdict; } @@ -977,18 +1001,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (desync_mode==DESYNC_DISORDER) { - fakeseg_len = sizeof(fakeseg); + seg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, ttl_fake,params.desync_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment, - zeropkt, split_pos, fakeseg, &fakeseg_len)) + zeropkt, split_pos, fakeseg, &seg_len)) return verdict; DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n") - if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) + if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) return verdict; } - pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, ttl_orig,fooling_orig,params.desync_badseq_increment,params.desync_badseq_ack_increment, @@ -1003,7 +1026,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n") - if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) + if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len)) return verdict; } @@ -1014,8 +1037,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_SPLIT2: if (split_pos) { - uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100]; - size_t fakeseg_len; + uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; + size_t fakeseg_len,seg_len; if (desync_mode==DESYNC_SPLIT) { @@ -1030,13 +1053,30 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint return verdict; } - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, + if (params.desync_seqovl) + { + seg_len = split_pos+params.desync_seqovl; + if (seg_len>sizeof(ovlseg)) + { + DLOG("seqovl is too large") + return verdict; + } + fill_pattern(ovlseg,params.desync_seqovl,params.seqovl_pattern,sizeof(params.seqovl_pattern)); + memcpy(ovlseg+params.desync_seqovl,data_payload,split_pos); + seg = ovlseg; + } + else + { + seg = data_payload; + seg_len = split_pos; + } + + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,-params.desync_seqovl), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps, ttl_orig,fooling_orig,params.desync_badseq_increment,params.desync_badseq_ack_increment, - data_payload, split_pos, pkt1, &pkt1_len)) + seg, seg_len, pkt1, &pkt1_len)) return verdict; - DLOG("sending 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos) - hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n") + DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ",split_pos-1, split_pos, params.desync_seqovl) + hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n") if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return verdict; @@ -1047,7 +1087,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!rawsend_rep((struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len)) return verdict; } - if (split_pos\t\t; data payload split position\n" " --dpi-desync-split-http-req=method|host\t; split at specified logical part of plain http request\n" " --dpi-desync-split-tls=sni|sniext\t\t; split at specified logical part of TLS ClientHello\n" + " --dpi-desync-split-seqovl=\t\t; use sequence overlap before first sent original split segment\n" + " --dpi-desync-split-seqovl-pattern=|0xHEX ; pattern for the fake part of overlap\n" " --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" " --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" " --dpi-desync-badseq-increment=\t; badseq fooling seq signed increment. default %d\n" " --dpi-desync-badack-increment=\t; badseq fooling ackseq signed increment. default %d\n" - " --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only known protocols 1=desync any nonempty data packet\n" + " --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n" " --dpi-desync-fake-http=|0xHEX\t; file containing fake http request\n" " --dpi-desync-fake-tls=|0xHEX\t\t; file containing fake TLS ClientHello (for https)\n" " --dpi-desync-fake-unknown=|0xHEX\t; file containing unknown protocol fake payload\n" @@ -1009,42 +1011,44 @@ int main(int argc, char **argv) {"dpi-desync-split-pos",required_argument,0,0},// optidx=23 {"dpi-desync-split-http-req",required_argument,0,0 },// optidx=24 {"dpi-desync-split-tls",required_argument,0,0 },// optidx=25 - {"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=26 - {"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=27 - {"dpi-desync-badseq-increment",required_argument,0,0},// optidx=28 - {"dpi-desync-badack-increment",required_argument,0,0},// optidx=29 - {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=30 - {"dpi-desync-fake-http",required_argument,0,0},// optidx=31 - {"dpi-desync-fake-tls",required_argument,0,0},// optidx=32 - {"dpi-desync-fake-unknown",required_argument,0,0},// optidx=33 - {"dpi-desync-fake-syndata",required_argument,0,0},// optidx=34 - {"dpi-desync-fake-quic",required_argument,0,0},// optidx=35 - {"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=36 - {"dpi-desync-fake-dht",required_argument,0,0},// optidx=37 - {"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=38 - {"dpi-desync-udplen-increment",required_argument,0,0},// optidx=39 - {"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=40 - {"dpi-desync-cutoff",required_argument,0,0},// optidx=41 - {"dpi-desync-start",required_argument,0,0},// optidx=42 - {"hostlist",required_argument,0,0}, // optidx=43 - {"hostlist-exclude",required_argument,0,0}, // optidx=44 - {"hostlist-auto",required_argument,0,0}, // optidx=45 - {"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=46 - {"hostlist-auto-fail-time",required_argument,0,0}, // optidx=47 - {"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=48 - {"hostlist-auto-debug",required_argument,0,0}, // optidx=49 + {"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=26 + {"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=27 + {"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=28 + {"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=29 + {"dpi-desync-badseq-increment",required_argument,0,0},// optidx=30 + {"dpi-desync-badack-increment",required_argument,0,0},// optidx=31 + {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=32 + {"dpi-desync-fake-http",required_argument,0,0},// optidx=33 + {"dpi-desync-fake-tls",required_argument,0,0},// optidx=34 + {"dpi-desync-fake-unknown",required_argument,0,0},// optidx=35 + {"dpi-desync-fake-syndata",required_argument,0,0},// optidx=36 + {"dpi-desync-fake-quic",required_argument,0,0},// optidx=37 + {"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=38 + {"dpi-desync-fake-dht",required_argument,0,0},// optidx=39 + {"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=40 + {"dpi-desync-udplen-increment",required_argument,0,0},// optidx=41 + {"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=42 + {"dpi-desync-cutoff",required_argument,0,0},// optidx=43 + {"dpi-desync-start",required_argument,0,0},// optidx=43 + {"hostlist",required_argument,0,0}, // optidx=44 + {"hostlist-exclude",required_argument,0,0}, // optidx=45 + {"hostlist-auto",required_argument,0,0}, // optidx=46 + {"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=48 + {"hostlist-auto-fail-time",required_argument,0,0}, // optidx=49 + {"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=50 + {"hostlist-auto-debug",required_argument,0,0}, // optidx=51 #ifdef __linux__ - {"bind-fix4",no_argument,0,0}, // optidx=50 - {"bind-fix6",no_argument,0,0}, // optidx=51 + {"bind-fix4",no_argument,0,0}, // optidx=52 + {"bind-fix6",no_argument,0,0}, // optidx=53 #elif defined(__CYGWIN__) - {"wf-iface",required_argument,0,0}, // optidx=50 - {"wf-l3",required_argument,0,0}, // optidx=51 - {"wf-tcp",required_argument,0,0}, // optidx=52 - {"wf-udp",required_argument,0,0}, // optidx=53 - {"wf-raw",required_argument,0,0}, // optidx=54 - {"wf-save",required_argument,0,0}, // optidx=55 - {"ssid-filter",required_argument,0,0}, // optidx=56 + {"wf-iface",required_argument,0,0}, // optidx=52 + {"wf-l3",required_argument,0,0}, // optidx=53 + {"wf-tcp",required_argument,0,0}, // optidx=54 + {"wf-udp",required_argument,0,0}, // optidx=55 + {"wf-raw",required_argument,0,0}, // optidx=56 + {"wf-save",required_argument,0,0}, // optidx=57 + {"ssid-filter",required_argument,0,0}, // optidx=58 #endif {NULL,0,NULL,0} }; @@ -1297,7 +1301,22 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 26: /* dpi-desync-ipfrag-pos-tcp */ + case 26: /* dpi-desync-split-seqovl */ + if (sscanf(optarg,"%u",¶ms.desync_seqovl)<1) + { + fprintf(stderr, "dpi-desync-split-seqovl is not valid\n"); + exit_clean(1); + } + break; + case 27: /* dpi-desync-split-seqovl-pattern */ + { + char buf[sizeof(params.seqovl_pattern)]; + size_t sz=sizeof(buf); + load_file_or_exit(optarg,buf,&sz); + fill_pattern(params.seqovl_pattern,sizeof(params.seqovl_pattern),buf,sz); + } + break; + case 28: /* dpi-desync-ipfrag-pos-tcp */ if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_tcp)<1 || params.desync_ipfrag_pos_tcp<1 || params.desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN) { fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN); @@ -1309,7 +1328,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 27: /* dpi-desync-ipfrag-pos-udp */ + case 29: /* dpi-desync-ipfrag-pos-udp */ if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_udp)<1 || params.desync_ipfrag_pos_udp<1 || params.desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN) { fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN); @@ -1321,63 +1340,63 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 28: /* dpi-desync-badseq-increments */ + case 30: /* dpi-desync-badseq-increments */ 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); } break; - case 29: /* dpi-desync-badack-increment */ + case 31: /* dpi-desync-badack-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); } break; - case 30: /* dpi-desync-any-protocol */ + case 32: /* dpi-desync-any-protocol */ params.desync_any_proto = !optarg || atoi(optarg); break; - case 31: /* dpi-desync-fake-http */ + case 33: /* dpi-desync-fake-http */ params.fake_http_size = sizeof(params.fake_http); load_file_or_exit(optarg,params.fake_http,¶ms.fake_http_size); break; - case 32: /* dpi-desync-fake-tls */ + case 34: /* dpi-desync-fake-tls */ params.fake_tls_size = sizeof(params.fake_tls); load_file_or_exit(optarg,params.fake_tls,¶ms.fake_tls_size); break; - case 33: /* dpi-desync-fake-unknown */ + case 35: /* dpi-desync-fake-unknown */ params.fake_unknown_size = sizeof(params.fake_unknown); load_file_or_exit(optarg,params.fake_unknown,¶ms.fake_unknown_size); break; - case 34: /* dpi-desync-fake-syndata */ + case 36: /* dpi-desync-fake-syndata */ params.fake_syndata_size = sizeof(params.fake_syndata); load_file_or_exit(optarg,params.fake_syndata,¶ms.fake_syndata_size); break; - case 35: /* dpi-desync-fake-quic */ + case 37: /* dpi-desync-fake-quic */ params.fake_quic_size = sizeof(params.fake_quic); load_file_or_exit(optarg,params.fake_quic,¶ms.fake_quic_size); break; - case 36: /* dpi-desync-fake-wireguard */ + case 38: /* dpi-desync-fake-wireguard */ params.fake_wg_size = sizeof(params.fake_wg); load_file_or_exit(optarg,params.fake_wg,¶ms.fake_wg_size); break; - case 37: /* dpi-desync-fake-dht */ + case 39: /* dpi-desync-fake-dht */ params.fake_dht_size = sizeof(params.fake_dht); load_file_or_exit(optarg,params.fake_dht,¶ms.fake_dht_size); break; - case 38: /* dpi-desync-fake-unknown-udp */ + case 40: /* dpi-desync-fake-unknown-udp */ params.fake_unknown_udp_size = sizeof(params.fake_unknown_udp); load_file_or_exit(optarg,params.fake_unknown_udp,¶ms.fake_unknown_udp_size); break; - case 39: /* dpi-desync-udplen-increment */ + case 41: /* dpi-desync-udplen-increment */ if (sscanf(optarg,"%d",¶ms.udplen_increment)<1 || params.udplen_increment>0x7FFF || params.udplen_increment<-0x8000) { fprintf(stderr, "dpi-desync-udplen-increment must be integer within -32768..32767 range\n"); exit_clean(1); } break; - case 40: /* dpi-desync-udplen-pattern */ + case 42: /* dpi-desync-udplen-pattern */ { char buf[sizeof(params.udplen_pattern)]; size_t sz=sizeof(buf); @@ -1385,35 +1404,35 @@ int main(int argc, char **argv) fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz); } break; - case 41: /* desync-cutoff */ + case 43: /* desync-cutoff */ if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode)) { fprintf(stderr, "invalid desync-cutoff value\n"); exit_clean(1); } break; - case 42: /* desync-start */ + case 44: /* desync-start */ if (!parse_cutoff(optarg, ¶ms.desync_start, ¶ms.desync_start_mode)) { fprintf(stderr, "invalid desync-start value\n"); exit_clean(1); } break; - case 43: /* hostlist */ + case 45: /* hostlist */ if (!strlist_add(¶ms.hostlist_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); exit_clean(1); } break; - case 44: /* hostlist-exclude */ + case 46: /* hostlist-exclude */ if (!strlist_add(¶ms.hostlist_exclude_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); exit_clean(1); } break; - case 45: /* hostlist-auto */ + case 47: /* hostlist-auto */ if (*params.hostlist_auto_filename) { fprintf(stderr, "only one auto hostlist is supported\n"); @@ -1446,7 +1465,7 @@ int main(int argc, char **argv) strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename)); params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0'; break; - case 46: /* hostlist-auto-fail-threshold */ + case 48: /* hostlist-auto-fail-threshold */ params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20) { @@ -1454,7 +1473,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 47: /* hostlist-auto-fail-time */ + case 49: /* hostlist-auto-fail-time */ params.hostlist_auto_fail_time = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_time<1) { @@ -1462,7 +1481,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 48: /* hostlist-auto-retrans-threshold */ + case 50: /* hostlist-auto-retrans-threshold */ params.hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg); if (params.hostlist_auto_retrans_threshold<2 || params.hostlist_auto_retrans_threshold>10) { @@ -1470,7 +1489,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 49: /* hostlist-auto-debug */ + case 51: /* hostlist-auto-debug */ { FILE *F = fopen(optarg,"a+t"); if (!F) @@ -1488,28 +1507,28 @@ int main(int argc, char **argv) } break; #ifdef __linux__ - case 50: /* bind-fix4 */ + case 52: /* bind-fix4 */ params.bind_fix4 = true; break; - case 51: /* bind-fix6 */ + case 53: /* bind-fix6 */ params.bind_fix6 = true; break; #elif defined(__CYGWIN__) - case 50: /* wf-iface */ + case 52: /* wf-iface */ if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx)) { fprintf(stderr, "bad value for --wf-iface\n"); exit_clean(1); } break; - case 51: /* wf-l3 */ + case 53: /* wf-l3 */ if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6)) { fprintf(stderr, "bad value for --wf-l3\n"); exit_clean(1); } break; - case 52: /* wf-tcp */ + case 54: /* wf-tcp */ hash_wf_tcp=hash_jen(optarg,strlen(optarg)); if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) || !wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst))) @@ -1518,7 +1537,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 53: /* wf-udp */ + case 55: /* wf-udp */ hash_wf_udp=hash_jen(optarg,strlen(optarg)); if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) || !wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst))) @@ -1527,7 +1546,7 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 54: /* wf-raw */ + case 56: /* wf-raw */ hash_wf_raw=hash_jen(optarg,strlen(optarg)); if (optarg[0]=='@') { @@ -1541,11 +1560,11 @@ int main(int argc, char **argv) windivert_filter[sizeof(windivert_filter) - 1] = '\0'; } break; - case 55: /* wf-save */ + case 57: /* wf-save */ strncpy(wf_save_file, optarg, sizeof(wf_save_file)); wf_save_file[sizeof(wf_save_file) - 1] = '\0'; break; - case 56: /* ssid-filter */ + case 58: /* ssid-filter */ hash_ssid_filter=hash_jen(optarg,strlen(optarg)); { char *e,*p = optarg; @@ -1617,7 +1636,7 @@ int main(int argc, char **argv) if (hMutexArg && GetLastError()==ERROR_ALREADY_EXISTS) { CloseHandle(hMutexArg); hMutexArg = NULL; - printf("A copy of winws is already running with the same filter\n"); + fprintf(stderr, "A copy of winws is already running with the same filter\n"); goto exiterr; } diff --git a/nfq/params.h b/nfq/params.h index 9098c34..7404473 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -50,7 +50,7 @@ struct params_s char hostspell[4]; enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; bool desync_retrans,desync_skip_nosni,desync_any_proto; - unsigned int desync_repeats,desync_split_pos,desync_ipfrag_pos_tcp,desync_ipfrag_pos_udp; + unsigned int desync_repeats,desync_split_pos,desync_seqovl,desync_ipfrag_pos_tcp,desync_ipfrag_pos_udp; enum httpreqpos desync_split_http_req; enum tlspos desync_split_tls; char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence @@ -60,7 +60,7 @@ struct params_s uint32_t desync_fooling_mode; uint32_t desync_fwmark; // unused in BSD uint32_t desync_badseq_increment, desync_badseq_ack_increment; - uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460]; + uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460]; uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472]; size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size; int udplen_increment;