diff --git a/docs/changes.txt b/docs/changes.txt index 5fe7bcd..748dc61 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -452,3 +452,7 @@ install_easy: dnf packager support nfqws,tpws: hostlist/ipset track not only file mod time but also file size nfqws,tpws,ipset: return lists reload on HUP nfqws,blockcheck: --dpi-desync-fake-tls-mod + +v70.1 + +nfqws: --dpi-desync-fake-tls-mod=dupsid diff --git a/docs/readme.en.md b/docs/readme.en.md index 55c7b68..e458191 100644 --- a/docs/readme.en.md +++ b/docs/readme.en.md @@ -1,4 +1,4 @@ -# zapret v70 +# zapret v70.1 # SCAMMER WARNING @@ -173,7 +173,7 @@ nfqws takes the following parameters: --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-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap + --dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap --dpi-desync-fake-unknown=|0xHEX ; file containing unknown protocol fake payload --dpi-desync-fake-syndata=|0xHEX ; file containing SYN data payload --dpi-desync-fake-quic=|0xHEX ; file containing fake QUIC Initial @@ -273,6 +273,7 @@ It's possible to use TLS Client Hello with any fingerprint and any SNI. * `none`. Do not do any mods. * `rnd`. Randomize `random` and `session id` fields. Applied on every request. * `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup. + * `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request. * `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request. By default if custom fake is not defined `rnd,rndsni` mods are applied. If defined - `none`. diff --git a/docs/readme.md b/docs/readme.md index e8fd378..f085e66 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,4 +1,4 @@ -# zapret v70 +# zapret v70.1 # ВНИМАНИЕ, остерегайтесь мошенников @@ -194,7 +194,7 @@ dvtws, собираемый из тех же исходников (см. [док --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных --dpi-desync-fake-http=|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org --dpi-desync-fake-tls=|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному ---dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,padencap +--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,dupsid,padencap --dpi-desync-fake-unknown=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт --dpi-desync-fake-syndata=|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata --dpi-desync-fake-quic=|0xHEX ; файл, содержащий фейковый QUIC Initial @@ -326,6 +326,7 @@ dvtws, собираемый из тех же исходников (см. [док * `none`. Не применять никакие модификации. * `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос. + * `dupsid`. Копировать `session ID` из передаваемого TLS Client Hello. Имеет приоритет над `rnd`. Выполняется на каждый запрос. * `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте. * `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос. diff --git a/nfq/desync.c b/nfq/desync.c index 8090f5b..9aef4ff 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -606,17 +606,17 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip) // fake_mod buffer must at least sizeof(desync_profile->fake_tls) // size does not change // return : true - altered, false - not altered -static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, uint8_t *fake_mod) +static bool runtime_tls_mod(const struct desync_profile *dp, uint8_t *fake_mod, const uint8_t *payload, size_t payload_len) { bool b=false; if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP) { - size_t sz_rec = pntoh16(dp->fake_tls+3) + encap_len; - size_t sz_handshake = pntoh24(dp->fake_tls+6) + encap_len; - size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + encap_len; - size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + encap_len; + size_t sz_rec = pntoh16(dp->fake_tls+3) + payload_len; + size_t sz_handshake = pntoh24(dp->fake_tls+6) + payload_len; + size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + payload_len; + size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + payload_len; if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF)) - DLOG("cannot apply tls mod. length overflow.\n"); + DLOG("cannot apply padencap tls mod. length overflow.\n"); else { memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size); @@ -634,6 +634,19 @@ static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, u fill_random_bytes(fake_mod+44,fake_mod[43]); // session id b=true; } + if (dp->fake_tls_mod & FAKE_TLS_MOD_DUP_SID) + { + if (dp->fake_tls[43]!=payload[43]) + DLOG("cannot apply dupsid tls mod. fake and orig session id length mismatch.\n"); + else if (payload_len<(44+payload[43])) + DLOG("cannot apply dupsid tls mod. data payload is not valid.\n"); + else + { + if (!b) memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size); + memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id + b=true; + } + } return b; } @@ -1174,7 +1187,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint fake_size = dp->fake_http_size; break; case TLS: - fake = runtime_tls_mod(dp,rlen_payload,fake_mod) ? fake_mod : dp->fake_tls; + fake = runtime_tls_mod(dp,fake_mod,rdata_payload,rlen_payload) ? fake_mod : dp->fake_tls; fake_size = dp->fake_tls_size; break; default: diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 6208b23..93cfffc 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -934,6 +934,8 @@ static bool parse_tlsmod_list(char *opt, uint8_t *mod) *mod |= FAKE_TLS_MOD_RND_SNI; else if (!strcmp(p,"padencap")) *mod |= FAKE_TLS_MOD_PADENCAP; + else if (!strcmp(p,"dupsid")) + *mod |= FAKE_TLS_MOD_DUP_SID; else if (strcmp(p,"none")) return false; @@ -979,10 +981,10 @@ static void onetime_tls_mod(struct desync_profile *dp) size_t extlen, slen; if (dp->n && !(dp->fake_tls_mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE))) - dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI; // old behavior compat + dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid if (!(dp->fake_tls_mod & ~FAKE_TLS_MOD_SAVE_MASK)) return; // nothing to do - if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false)) + if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false) || (dp->fake_tls_size<(44+dp->fake_tls[43]))) // has session id ? { DLOG_ERR("profile %d tls mod set but tls fake structure invalid\n", dp->n); exit_clean(1); @@ -1291,7 +1293,7 @@ static void exithelp(void) " --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-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap\n" + " --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap\n" " --dpi-desync-fake-unknown=|0xHEX\t; file containing unknown protocol fake payload\n" " --dpi-desync-fake-syndata=|0xHEX\t; file containing SYN data payload\n" " --dpi-desync-fake-quic=|0xHEX\t; file containing fake QUIC Initial\n" diff --git a/nfq/params.h b/nfq/params.h index 1008343..1d74a23 100644 --- a/nfq/params.h +++ b/nfq/params.h @@ -42,8 +42,9 @@ #define FAKE_TLS_MOD_SET 0x01 #define FAKE_TLS_MOD_CUSTOM_FAKE 0x02 #define FAKE_TLS_MOD_RND 0x10 -#define FAKE_TLS_MOD_RND_SNI 0x20 -#define FAKE_TLS_MOD_PADENCAP 0x40 +#define FAKE_TLS_MOD_DUP_SID 0x20 +#define FAKE_TLS_MOD_RND_SNI 0x40 +#define FAKE_TLS_MOD_PADENCAP 0x80 enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };