diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index 09cfb98..7bb9a83 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/arm/nfqws b/binaries/arm/nfqws index 108cf31..15d484e 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 e1e9939..b3a3651 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 166bef0..c9fe48b 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 9385ced..4376be7 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 ca5cad2..1a384b3 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 d3fb237..868d6e8 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index 14729f0..3aec84f 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 22610ae..d3eeea1 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/docs/readme.eng.md b/docs/readme.eng.md index 1b34419..e5c4e11 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -138,44 +138,47 @@ For BSD systems there is dvtws. Its built from the same source and has almost th nfqws takes the following parameters: ``` - --debug=0|1 ; 1=print debug info + --debug=0|1 --qnum= - --bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets - --bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets - --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|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" - --hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size - --domcase ; mix domain case after Host: like this : TeSt.cOm - --daemon ; daemonize - --pidfile= ; write pid to file - --user= ; drop root privs - --uid=uid[:gid] ; drop root privs - --dpi-desync=[[,] ; desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen - --dpi-desync-fwmark= ; override fwmark for desync packet. default = 0x40000000 - --dpi-desync-ttl= ; set ttl for desync packet - --dpi-desync-ttl6= ; set ipv6 hop limit for desync packet. by default ttl value is used - --dpi-desync-fooling= ; can take multiple comma separated values : none md5sig badseq badsum hopbyhop hopbyhop2 - --dpi-desync-retrans=0|1 ; (fake,rst,rstack only) 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission - --dpi-desync-repeats= ; send every desync packet N times - --dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI - --dpi-desync-split-pos=<1..1500> ; (for split* and disorder* only) split TCP packet at specified position - --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 - --dpi-desync-badack-increment= ; badseq fooling ackseq signed increment. default -66000 - --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet - --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-fake-quic= ; file containing fake QUIC Initial - --dpi-desync-fake-unknown-udp= ; file containing unknown udp protocol fake payload - --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= ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) - --hostlist-exclude= ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) + --daemon ; daemonize + --pidfile= ; write pid to file + --user= ; drop root privs + --uid=uid[:gid] ; drop root privs + --bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets + --bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets + --wsize=[:] ; set window size. 0 = do not modify. OBSOLETE ! + --wssize=[:] ; set window size for server. 0 = do not modify. default scale_factor = 0. + --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[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60 + --hostcase ; change Host: => host: + --hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host" + --hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size + --domcase ; mix domain case : Host: TeSt.cOm + --dpi-desync=[,][,] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen + --dpi-desync-fwmark= ; override fwmark for desync packet. default = 0x40000000 (1073741824) + --dpi-desync-ttl= ; set ttl for desync packet + --dpi-desync-ttl6= ; set ipv6 hop limit for desync packet. by default ttl value is used. + --dpi-desync-fooling=[,] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum hopbyhop hopbyhop2 + --dpi-desync-retrans=0|1 ; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission + --dpi-desync-repeats= ; send every desync packet N times + --dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?) + --dpi-desync-split-pos=<1..9216> ; data payload split position + --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 + --dpi-desync-badack-increment= ; badseq fooling ackseq signed increment. default -66000 + --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet + --dpi-desync-fake-http=|0xHEX ; file containing fake http request + --dpi-desync-fake-tls=|0xHEX ; file containing fake TLS ClientHello (for https) + --dpi-desync-fake-unknown=|0xHEX ; file containing unknown protocol fake payload + --dpi-desync-fake-quic=|0xHEX ; file containing fake QUIC Initial + --dpi-desync-fake-wireguard=|0xHEX ; file containing fake wireguard handshake initiation + --dpi-desync-fake-unknown-udp=|0xHEX ; file containing unknown udp protocol fake payload + --dpi-desync-udplen-increment= ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length. + --dpi-desync-udplen-pattern=|0xHEX ; udp tail fill pattern + --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 dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) + --hostlist-exclude= ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) ``` The manipulation parameters can be combined in any way. diff --git a/docs/readme.txt b/docs/readme.txt index b2d9e2c..d9b5d18 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -191,43 +191,44 @@ nfqws Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. Для BSD систем существует адаптированный вариант - dvtws, собираемый из тех же исходников (см. bsd.txt). - --debug=0|1 ; 1=выводить отладочные сообщения - --daemon ; демонизировать прогу - --pidfile= ; сохранить PID в файл - --user= ; менять uid процесса - --uid=uid[:gid] ; менять uid процесса - --qnum=N ; номер очереди N - --bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов - --bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов - --wsize=[:] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) - --wssize=[:] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) - --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N - --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 - --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". - --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета - --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase - --domcase ; домен после Host: сделать таким : TeSt.cOm - --dpi-desync=[,][, ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 - --dpi-desync-ttl= ; установить ttl для десинхронизирующих пакетов - --dpi-desync-ttl6= ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl - --dpi-desync-fooling= ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum hopbyhop hopbyhop2 - --dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек - --dpi-desync-repeats= ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) - --dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI - --dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции - --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=по всем непустым пакетам данных - --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-fake-quic= ; файл, содержащий фейковый QUIC Initial - --dpi-desync-fake-unknown-udp= ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт - --dpi-desync-udplen-increment= ; насколько увеличивать длину udp пейлоада в режиме udplen - --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N - --hostlist= ; применять дурение только к хостам из листа. может быть множество листов, они обьединяются. пустой обший лист = его отсутствие - --hostlist-exclude= ; не применять дурение к хостам из листа. может быть множество листов, они обьединяются + --debug=0|1 ; 1=выводить отладочные сообщения + --daemon ; демонизировать прогу + --pidfile= ; сохранить PID в файл + --user= ; менять uid процесса + --uid=uid[:gid] ; менять uid процесса + --qnum=N ; номер очереди N + --bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов + --bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов + --wsize=[:] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) + --wssize=[:] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) + --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N + --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 + --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". + --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета + --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase + --domcase ; домен после Host: сделать таким : TeSt.cOm + --dpi-desync=[,][, ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 + --dpi-desync-ttl= ; установить ttl для десинхронизирующих пакетов + --dpi-desync-ttl6= ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl + --dpi-desync-fooling= ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum hopbyhop hopbyhop2 + --dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек + --dpi-desync-repeats= ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) + --dpi-desync-skip-nosni=0| 1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI + --dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции + --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=по всем непустым пакетам данных + --dpi-desync-fake-http=|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному w3.org + --dpi-desync-fake-tls=|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному w3.org + --dpi-desync-fake-unknown=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт + --dpi-desync-fake-quic=|0xHEX ; файл, содержащий фейковый QUIC Initial + --dpi-desync-fake-unknown-udp=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт + --dpi-desync-udplen-increment= ; насколько увеличивать длину udp пейлоада в режиме udplen + --dpi-desync-udplen-pattern=|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули + --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N + --hostlist= ; применять дурение только к хостам из листа. может быть множество листов, они обьединяются. пустой обший лист = его отсутствие + --hostlist-exclude= ; не применять дурение к хостам из листа. может быть множество листов, они обьединяются Параметры манипуляции могут сочетаться в любых комбинациях. diff --git a/nfq/darkmagic.c b/nfq/darkmagic.c index dcba3a2..29ac3d2 100644 --- a/nfq/darkmagic.c +++ b/nfq/darkmagic.c @@ -299,6 +299,7 @@ bool prepare_udp_segment4( const struct sockaddr_in *src, const struct sockaddr_in *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) @@ -324,7 +325,10 @@ bool prepare_udp_segment4( fill_udphdr(udp, src->sin_port, dst->sin_port, datalen); memcpy(payload,data,len); - memset(payload+len,0,padlen); + if (padding) + fill_pattern(payload+len,padlen,padding,padding_size); + else + memset(payload+len,0,padlen); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF); @@ -335,6 +339,7 @@ bool prepare_udp_segment6( const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) @@ -408,7 +413,10 @@ bool prepare_udp_segment6( fill_udphdr(udp, src->sin6_port, dst->sin6_port, datalen); memcpy(payload,data,len); - memset(payload+len,0,padlen); + if (padding) + fill_pattern(payload+len,padlen,padding,padding_size); + else + memset(payload+len,0,padlen); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF); @@ -419,14 +427,15 @@ bool prepare_udp_segment( const struct sockaddr *src, const struct sockaddr *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen) { return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? - prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,fooling,padlen,data,len,buf,buflen) : + prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,fooling,padding,padding_size,padlen,data,len,buf,buflen) : (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? - prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,fooling,padlen,data,len,buf,buflen) : + prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,fooling,padding,padding_size,padlen,data,len,buf,buflen) : false; } diff --git a/nfq/darkmagic.h b/nfq/darkmagic.h index 6a46cb7..dc953c0 100644 --- a/nfq/darkmagic.h +++ b/nfq/darkmagic.h @@ -73,6 +73,7 @@ bool prepare_udp_segment4( const struct sockaddr_in *src, const struct sockaddr_in *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); @@ -80,6 +81,7 @@ bool prepare_udp_segment6( const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); @@ -87,6 +89,7 @@ bool prepare_udp_segment( const struct sockaddr *src, const struct sockaddr *dst, uint8_t ttl, uint8_t fooling, + const uint8_t *padding, size_t padding_size, int padlen, const void *data, uint16_t len, uint8_t *buf, size_t *buflen); diff --git a/nfq/desync.c b/nfq/desync.c index ff9db68..6d9864f 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -783,7 +783,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, break; } case DESYNC_FAKE: - if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, params.desync_fooling_mode, 0, fake, fake_size, pkt1, &pkt1_len)) + if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, params.desync_fooling_mode, NULL, 0, 0, fake, fake_size, pkt1, &pkt1_len)) return res; DLOG("sending fake request : "); hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n") @@ -798,7 +798,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, if (ip6hdr && (params.desync_mode2==DESYNC_NONE || !desync_valid_second_stage_udp(params.desync_mode2))) { if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, - ttl_orig,fooling_orig,0, + ttl_orig,fooling_orig,NULL,0,0, data_payload, len_payload, pkt1, &pkt1_len)) { return res; @@ -837,7 +837,7 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, { case DESYNC_UDPLEN: pkt1_len = sizeof(pkt1); - if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, params.udplen_increment, data_payload, len_payload, pkt1, &pkt1_len)) + if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, params.udplen_pattern, sizeof(params.udplen_pattern), params.udplen_increment, data_payload, len_payload, pkt1, &pkt1_len)) { DLOG("could not construct packet with modified length. too large ?\n"); return res; diff --git a/nfq/helpers.c b/nfq/helpers.c index 27b76b4..80cbdb0 100644 --- a/nfq/helpers.c +++ b/nfq/helpers.c @@ -179,3 +179,50 @@ void phton64(uint8_t *p, uint64_t v) p[6] = (uint8_t)(v >> 8); p[7] = (uint8_t)(v >> 0); } + +#define INVALID_HEX_DIGIT ((uint8_t)-1) +static inline uint8_t parse_hex_digit(char c) +{ + return (c>='0' && c<='9') ? c-'0' : (c>='a' && c<='f') ? c-'a'+0xA : (c>='A' && c<='F') ? c-'A'+0xA : INVALID_HEX_DIGIT; +} +static inline bool parse_hex_byte(const char *s, uint8_t *pbyte) +{ + uint8_t u,l; + u = parse_hex_digit(s[0]); + l = parse_hex_digit(s[1]); + if (u==INVALID_HEX_DIGIT || l==INVALID_HEX_DIGIT) + { + *pbyte=0; + return false; + } + else + { + *pbyte=(u<<4) | l; + return true; + } +} +bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size) +{ + uint8_t *pe = pbuf+*size; + *size=0; + while(pbufpatsize ? patsize : bufsize; + memcpy(buf,pattern,size); + buf += size; + bufsize -= size; + } +} diff --git a/nfq/helpers.h b/nfq/helpers.h index 1e58d32..61043a1 100644 --- a/nfq/helpers.h +++ b/nfq/helpers.h @@ -34,3 +34,6 @@ static inline void phton16(uint8_t *p, uint16_t v) { static inline uint32_t pntoh32(const uint8_t *p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3]; } + +bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); +void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); diff --git a/nfq/nfqws.c b/nfq/nfqws.c index a65104b..664feb4 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -504,54 +504,55 @@ static void exithelp() #ifdef __linux__ " --qnum=\n" #elif defined(BSD) - " --port=\t\t\t\t; divert port\n" + " --port=\t\t\t\t\t; divert port\n" #endif - " --daemon\t\t\t\t; daemonize\n" - " --pidfile=\t\t\t; write pid to file\n" - " --user=\t\t\t; drop root privs\n" - " --uid=uid[:gid]\t\t\t; drop root privs\n" + " --daemon\t\t\t\t\t; daemonize\n" + " --pidfile=\t\t\t\t; write pid to file\n" + " --user=\t\t\t\t; drop root privs\n" + " --uid=uid[:gid]\t\t\t\t; drop root privs\n" #ifdef __linux__ - " --bind-fix4\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n" - " --bind-fix6\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n" + " --bind-fix4\t\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n" + " --bind-fix6\t\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n" #endif - " --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|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[:U]\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%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" - " --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" - " --domcase\t\t\t\t; mix domain case : Host: TeSt.cOm\n" - " --dpi-desync=[,][,] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen\n" + " --wsize=[:]\t\t; set window size. 0 = do not modify. OBSOLETE !\n" + " --wssize=[:]\t; set window size for server. 0 = do not modify. default scale_factor = 0.\n" + " --wssize-cutoff=[n|d|s]N\t\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[:U]\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n" + " --hostcase\t\t\t\t\t; change Host: => host:\n" + " --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" + " --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" + " --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n" + " --dpi-desync=[,][,]\t; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen\n" #ifdef __linux__ - " --dpi-desync-fwmark=\t; override fwmark for desync packet. default = 0x%08X (%u)\n" + " --dpi-desync-fwmark=\t\t; override fwmark for desync packet. default = 0x%08X (%u)\n" #elif defined(SO_USER_COOKIE) - " --dpi-desync-sockarg=\t; override sockarg (SO_USER_COOKIE) for desync packet. default = 0x%08X (%u)\n" + " --dpi-desync-sockarg=\t\t; override sockarg (SO_USER_COOKIE) for desync packet. default = 0x%08X (%u)\n" #endif - " --dpi-desync-ttl=\t\t\t; set ttl for desync packet\n" - " --dpi-desync-ttl6=\t\t; set ipv6 hop limit for desync packet. by default ttl value is used.\n" - " --dpi-desync-fooling=[,]\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum hopbyhop hopbyhop2\n" + " --dpi-desync-ttl=\t\t\t\t; set ttl for desync packet\n" + " --dpi-desync-ttl6=\t\t\t; set ipv6 hop limit for desync packet. by default ttl value is used.\n" + " --dpi-desync-fooling=[,]\t\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum hopbyhop hopbyhop2\n" #ifdef __linux__ - " --dpi-desync-retrans=0|1\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n" + " --dpi-desync-retrans=0|1\t\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n" #endif - " --dpi-desync-repeats=\t\t; send every desync packet N times\n" - " --dpi-desync-skip-nosni=0|1\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n" - " --dpi-desync-split-pos=<1..%u>\t; data payload split position\n" - " --dpi-desync-ipfrag-pos-tcp=<8..%u>\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" - " --dpi-desync-ipfrag-pos-udp=<8..%u>\t; ip frag position starting from the transport header. multiple of 8, default %u.\n" - " --dpi-desync-badseq-increment= ; badseq fooling seq signed increment. default %d\n" - " --dpi-desync-badack-increment= ; badseq fooling ackseq signed increment. default %d\n" - " --dpi-desync-any-protocol=0|1\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n" - " --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-fake-quic=\t; file containing fake QUIC Initial\n" - " --dpi-desync-fake-wireguard=\t; file containing fake wireguard handshake initiation\n" - " --dpi-desync-fake-unknown-udp= ; file containing unknown udp protocol fake payload\n" - " --dpi-desync-udplen-increment=\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\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, gzip supported, multiple hostlists allowed)\n" - " --hostlist-exclude=\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n", + " --dpi-desync-repeats=\t\t\t; send every desync packet N times\n" + " --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n" + " --dpi-desync-split-pos=<1..%u>\t\t; data payload split position\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 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" + " --dpi-desync-fake-quic=|0xHEX\t; file containing fake QUIC Initial\n" + " --dpi-desync-fake-wireguard=|0xHEX\t; file containing fake wireguard handshake initiation\n" + " --dpi-desync-fake-unknown-udp=|0xHEX\t; file containing unknown udp protocol fake payload\n" + " --dpi-desync-udplen-increment=\t\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\n" + " --dpi-desync-udplen-pattern=|0xHEX\t; udp tail fill pattern\n" + " --dpi-desync-cutoff=[n|d|s]N\t\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\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" + " --hostlist-exclude=\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n", CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP, #if defined(__linux__) || defined(SO_USER_COOKIE) DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT, @@ -612,12 +613,24 @@ static bool parse_badseq_increment(const char *opt, uint32_t *value) } static void load_file_or_exit(const char *filename, void *buf, size_t *size) { - if (!load_file_nonempty(filename,buf,size)) + if (filename[0]=='0' && filename[1]=='x') { - fprintf(stderr, "could not read %s\n",filename); - exit_clean(1); + if (!parse_hex_str(filename+2,buf,size) || !*size) + { + fprintf(stderr, "invalid hex string: %s\n",filename+2); + exit_clean(1); + } + DLOG("read %zu bytes from hex string\n",*size) + } + else + { + if (!load_file_nonempty(filename,buf,size)) + { + fprintf(stderr, "could not read %s\n",filename); + exit_clean(1); + } + DLOG("read %zu bytes from %s\n",*size,filename) } - DLOG("read %zu bytes from %s\n",*size,filename) } @@ -717,12 +730,13 @@ int main(int argc, char **argv) {"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=32 {"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=33 {"dpi-desync-udplen-increment",required_argument,0,0},// optidx=34 - {"dpi-desync-cutoff",required_argument,0,0},// optidx=35 - {"hostlist",required_argument,0,0}, // optidx=36 - {"hostlist-exclude",required_argument,0,0}, // optidx=37 + {"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=35 + {"dpi-desync-cutoff",required_argument,0,0},// optidx=36 + {"hostlist",required_argument,0,0}, // optidx=37 + {"hostlist-exclude",required_argument,0,0}, // optidx=38 #ifdef __linux__ - {"bind-fix4",no_argument,0,0}, // optidx=38 - {"bind-fix6",no_argument,0,0}, // optidx=39 + {"bind-fix4",no_argument,0,0}, // optidx=39 + {"bind-fix6",no_argument,0,0}, // optidx=40 #endif {NULL,0,NULL,0} }; @@ -1019,21 +1033,29 @@ int main(int argc, char **argv) exit_clean(1); } break; - case 35: /* desync-cutoff */ + case 35: /* dpi-desync-udplen-pattern */ + { + char buf[sizeof(params.udplen_pattern)]; + size_t sz=sizeof(buf); + load_file_or_exit(optarg,buf,&sz); + fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz); + } + break; + case 36: /* 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 36: /* hostlist */ + case 37: /* hostlist */ if (!strlist_add(¶ms.hostlist_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); exit_clean(1); } break; - case 37: /* hostlist-exclude */ + case 38: /* hostlist-exclude */ if (!strlist_add(¶ms.hostlist_exclude_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); @@ -1041,10 +1063,10 @@ int main(int argc, char **argv) } break; #ifdef __linux__ - case 38: /* bind-fix4 */ + case 39: /* bind-fix4 */ params.bind_fix4 = true; break; - case 39: /* bind-fix6 */ + case 40: /* bind-fix6 */ params.bind_fix6 = true; break; #endif diff --git a/nfq/params.h b/nfq/params.h index 321d4cb..9e307ae 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -50,7 +50,7 @@ struct params_s uint8_t desync_fooling_mode; uint32_t desync_fwmark; // unused in BSD uint32_t desync_badseq_increment, desync_badseq_ack_increment; - uint8_t fake_http[1432],fake_tls[1432],fake_quic[1472],fake_wg[1472],fake_unknown[1432],fake_unknown_udp[1472]; + uint8_t fake_http[1432],fake_tls[1432],fake_quic[1472],fake_wg[1472],fake_unknown[1432],fake_unknown_udp[1472], udplen_pattern[1472]; size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_unknown_size,fake_unknown_udp_size; int udplen_increment; bool droproot;