mirror of
https://github.com/bol-van/zapret.git
synced 2025-08-10 01:02:03 +03:00
Compare commits
18 Commits
v70.5
...
e5e53db6b8
Author | SHA1 | Date | |
---|---|---|---|
|
e5e53db6b8 | ||
|
e14ee9d1fe | ||
|
360506ba4e | ||
|
aa769e05c6 | ||
|
6b0bc7a96b | ||
|
93bdfdb6be | ||
|
6d95eada2b | ||
|
e452ee8688 | ||
|
6e746f94cd | ||
|
9fd61e5d38 | ||
|
0c0fba4461 | ||
|
056e4c588a | ||
|
4b288643ac | ||
|
cbdee74e5f | ||
|
743eb5a4a2 | ||
|
4e8e3a9ed9 | ||
|
b9b91a0e68 | ||
|
9de7b66eef |
@@ -471,3 +471,9 @@ v70.5
|
||||
|
||||
nfqws: multiple --dpi-desync-fake-xxx
|
||||
nfqws: support of inter-packet fragmented QUIC CRYPTO
|
||||
|
||||
v70.6
|
||||
|
||||
nfqws: detect Discord Voice IP discovery packets
|
||||
nfqws: detect STUN message packets
|
||||
nfqws: change SNI to specified value tls mod : --dpi-desync-fake-tls-mod sni=<sni>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
debian,ubuntu :
|
||||
|
||||
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev
|
||||
make -C /opt/zapret
|
||||
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libsystemd-dev
|
||||
make -C /opt/zapret systemd
|
||||
|
||||
FreeBSD :
|
||||
|
||||
|
@@ -174,12 +174,14 @@ 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=<filename>|0xHEX ; file containing fake http request
|
||||
--dpi-desync-fake-tls=<filename>|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,dupsid,padencap
|
||||
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
||||
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
|
||||
--dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation
|
||||
--dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e)
|
||||
--dpi-desync-fake-discord=<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
|
||||
--dpi-desync-fake-stun=<filename>|0xHEX ; file containing fake STUN message
|
||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload
|
||||
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
|
||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
|
||||
@@ -193,13 +195,13 @@ nfqws takes the following parameters:
|
||||
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
||||
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
|
||||
--hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3)
|
||||
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
|
||||
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
|
||||
--new ; begin new strategy (new profile)
|
||||
--skip ; do not use this profile
|
||||
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
||||
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
|
||||
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
|
||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
||||
--filter-l7=<proto> ; L6-L7 protocol filter. multiple comma separated values allowed. proto: http tls quic wireguard dht discord stun unknown
|
||||
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||
--ipset-ip=<ip_list> ; comma separated fixed subnet list
|
||||
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
|
||||
@@ -283,6 +285,7 @@ It's possible to use TLS Client Hello with any fingerprint and any SNI.
|
||||
* `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.
|
||||
* `sni=<sni>`. Set specified SNI value. Changes TLS fake length, fixes lengths in TLS structure. Applied once at startup before `rndsni`.
|
||||
* `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,dupsid` mods are applied. If defined - `none`.
|
||||
@@ -474,7 +477,7 @@ This option can resist DPIs that track outgoing UDP packet sizes.
|
||||
Requires that application protocol does not depend on udp payload size.
|
||||
|
||||
QUIC initial packets are recognized. Decryption and hostname extraction is supported so `--hostlist` parameter will work.
|
||||
Wireguard handshake initiation and DHT packets are also recognized.
|
||||
Wireguard handshake initiation, DHT, STUN and [Discord Voice IP Discovery](https://discord.com/developers/docs/topics/voice-connections#ip-discovery) packets are also recognized.
|
||||
For other protocols desync use `--dpi-desync-any-protocol`.
|
||||
|
||||
Conntrack supports udp. `--dpi-desync-cutoff` will work. UDP conntrack timeout can be set in the 4th parameter of `--ctrack-timeouts`.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# zapret v70.5
|
||||
# zapret v70.6
|
||||
|
||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||
|
||||
@@ -196,11 +196,13 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||||
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,dupsid,padencap
|
||||
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-fake-discord=<filename>|0xHEX ; файл, содержащий фейковый пейлоад Discord протокола нахождения IP адреса для голосовых чатов для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-fake-stun=<filename>|0xHEX ; файл, содержащий фейковый пейлоад STUN протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
|
||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||||
@@ -226,7 +228,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
|
||||
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
|
||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||
--filter-l7=<proto> ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. proto : http tls quic wireguard dht discord stun unknown
|
||||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
|
||||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
@@ -338,6 +340,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
* `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос.
|
||||
* `dupsid`. Копировать `session ID` из передаваемого TLS Client Hello. Имеет приоритет над `rnd`. Выполняется на каждый запрос.
|
||||
* `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте.
|
||||
* `sni=<sni>`. Заменить sni на указанное значение. Макс длина SNI - 63 байта. Общая длина TLS фейка и длины в структуре TLS Client Hello меняются. Выполняется один раз при старте. Если сочетается с `rndsni`, выполняется до него.
|
||||
* `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос.
|
||||
|
||||
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
|
||||
@@ -575,7 +578,8 @@ chrome рандомизирует фингерпринт TLS. SNI может о
|
||||
На текущий момент работает только с DHT.
|
||||
Поддерживается определение пакетов QUIC Initial с расшифровкой содержимого и имени хоста, то есть параметр
|
||||
`--hostlist` будет работать.
|
||||
Определяются пакеты wireguard handshake initiation и DHT (начинается с 'd1', кончается 'e').
|
||||
Определяются пакеты wireguard handshake initiation, DHT (начинается с 'd1', кончается 'e'), STUN и
|
||||
[Discord Voice IP Discovery](https://discord.com/developers/docs/topics/voice-connections#ip-discovery).
|
||||
Для десинхронизации других протоколов обязательно указывать `--dpi-desync-any-protocol`.
|
||||
Реализован conntrack для udp. Можно пользоваться --dpi-desync-cutoff. Таймаут conntrack для udp
|
||||
можно изменить 4-м параметром в `--ctrack-timeouts`.
|
||||
|
BIN
files/fake/discord-ip-discovery-with-port.bin
Normal file
BIN
files/fake/discord-ip-discovery-with-port.bin
Normal file
Binary file not shown.
BIN
files/fake/discord-ip-discovery-without-port.bin
Normal file
BIN
files/fake/discord-ip-discovery-without-port.bin
Normal file
Binary file not shown.
BIN
files/fake/stun.bin
Normal file
BIN
files/fake/stun.bin
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
23
nfq/desync.c
23
nfq/desync.c
@@ -609,7 +609,7 @@ 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(int fake_n,const struct fake_tls_mod_cache *modcache, uint8_t fake_tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod)
|
||||
static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache, uint32_t fake_tls_mod, const uint8_t *fake_data, size_t fake_data_size, const uint8_t *payload, size_t payload_len, uint8_t *fake_mod)
|
||||
{
|
||||
bool b=false;
|
||||
if (modcache) // it's filled only if it's TLS
|
||||
@@ -630,6 +630,7 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
|
||||
phton16(fake_mod+modcache->extlen_offset,(uint16_t)sz_ext);
|
||||
phton16(fake_mod+modcache->padlen_offset,(uint16_t)sz_pad);
|
||||
b=true;
|
||||
DLOG("fake[%d] applied padencap tls mod. sizes increased by %zu bytes.\n", fake_n, payload_len);
|
||||
}
|
||||
}
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_RND)
|
||||
@@ -638,6 +639,7 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
|
||||
fill_random_bytes(fake_mod+11,32); // random
|
||||
fill_random_bytes(fake_mod+44,fake_mod[43]); // session id
|
||||
b=true;
|
||||
DLOG("fake[%d] applied rnd tls mod\n", fake_n);
|
||||
}
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
|
||||
{
|
||||
@@ -650,6 +652,7 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
|
||||
if (!b) memcpy(fake_mod,fake_data,fake_data_size);
|
||||
memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id
|
||||
b=true;
|
||||
DLOG("fake[%d] applied dupsid tls mod\n", fake_n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2079,6 +2082,18 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
l7proto = DHT;
|
||||
if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto;
|
||||
}
|
||||
else if (IsDiscordIpDiscoveryRequest(dis->data_payload,dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains discord voice IP discovery\n");
|
||||
l7proto = DISCORD;
|
||||
if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto;
|
||||
}
|
||||
else if (IsStunMessage(dis->data_payload,dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains STUN message\n");
|
||||
l7proto = STUN;
|
||||
if (ctrack && ctrack->l7proto==UNKNOWN) ctrack->l7proto = l7proto;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!dp->desync_any_proto)
|
||||
@@ -2191,6 +2206,12 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
case DHT:
|
||||
fake = &dp->fake_dht;
|
||||
break;
|
||||
case DISCORD:
|
||||
fake = &dp->fake_discord;
|
||||
break;
|
||||
case STUN:
|
||||
fake = &dp->fake_stun;
|
||||
break;
|
||||
default:
|
||||
fake = &dp->fake_unknown_udp;
|
||||
break;
|
||||
|
328
nfq/nfqws.c
328
nfq/nfqws.c
@@ -738,6 +738,10 @@ static bool parse_l7_list(char *opt, uint32_t *l7)
|
||||
*l7 |= L7_PROTO_WIREGUARD;
|
||||
else if (!strcmp(p,"dht"))
|
||||
*l7 |= L7_PROTO_DHT;
|
||||
else if (!strcmp(p,"discord"))
|
||||
*l7 |= L7_PROTO_DISCORD;
|
||||
else if (!strcmp(p,"stun"))
|
||||
*l7 |= L7_PROTO_STUN;
|
||||
else if (!strcmp(p,"unknown"))
|
||||
*l7 |= L7_PROTO_UNKNOWN;
|
||||
else return false;
|
||||
@@ -946,35 +950,57 @@ static bool parse_ip_list(char *opt, ipset *pp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_tlsmod_list(char *opt, uint8_t *mod)
|
||||
static bool parse_tlsmod_list(char *opt, uint32_t *mod, char *sni, size_t sni_buf_len)
|
||||
{
|
||||
char *e,*p,c;
|
||||
char *e,*e2,*p,c,c2;
|
||||
|
||||
*mod &= FAKE_TLS_MOD_SAVE_MASK;
|
||||
*mod |= FAKE_TLS_MOD_SET;
|
||||
for (p=opt ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
for (e2=p ; *e2 && *e2!=',' && *e2!='=' ; e2++);
|
||||
|
||||
if ((e = strchr(e2,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (*e2=='=')
|
||||
{
|
||||
c2=*e2;
|
||||
*e2=0;
|
||||
}
|
||||
else
|
||||
e2=NULL;
|
||||
|
||||
if (!strcmp(p,"rnd"))
|
||||
*mod |= FAKE_TLS_MOD_RND;
|
||||
else if (!strcmp(p,"rndsni"))
|
||||
*mod |= FAKE_TLS_MOD_RND_SNI;
|
||||
else if (!strcmp(p,"sni"))
|
||||
{
|
||||
*mod |= FAKE_TLS_MOD_SNI;
|
||||
if (!e2 || !e2[1] || e2[1]==',') goto err;
|
||||
strncpy(sni,e2+1,sni_buf_len-1);
|
||||
sni[sni_buf_len-1]=0;
|
||||
}
|
||||
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;
|
||||
goto err;
|
||||
|
||||
if (e2) *e2=c2;
|
||||
if (e) *e++=c;
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
err:
|
||||
if (e2) *e2=c2;
|
||||
if (e) *e++=c;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1008,13 +1034,13 @@ static void SplitDebug(void)
|
||||
|
||||
static const char * tld[]={"com","org","net","edu","gov","biz"};
|
||||
|
||||
static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint8_t fake_tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
|
||||
static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint32_t fake_tls_mod, const char *fake_tls_sni, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
|
||||
{
|
||||
const uint8_t *ext;
|
||||
size_t extlen, slen;
|
||||
size_t extlen;
|
||||
|
||||
modcache->extlen_offset = modcache->padlen_offset = 0;
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
|
||||
if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI|FAKE_TLS_MOD_PADENCAP))
|
||||
{
|
||||
if (!TLSFindExtLen(fake_tls,*fake_tls_size,&modcache->extlen_offset))
|
||||
{
|
||||
@@ -1022,6 +1048,86 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint8_t fake_tls_mod
|
||||
return false;
|
||||
}
|
||||
DLOG("profile %d fake[%d] tls extensions length offset : %zu\n", profile_n, fake_n, modcache->extlen_offset);
|
||||
if (fake_tls_mod & (FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_SNI))
|
||||
{
|
||||
size_t slen;
|
||||
if (!TLSFindExt(fake_tls,*fake_tls_size,0,&ext,&extlen,false))
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] sni mod is set but tls fake does not have SNI\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
uint8_t *sniext = fake_tls + (ext - fake_tls);
|
||||
if (!TLSAdvanceToHostInSNI(&ext,&extlen,&slen))
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] sni set but tls fake has invalid SNI structure\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
uint8_t *sni = fake_tls + (ext - fake_tls);
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_SNI)
|
||||
{
|
||||
size_t slen_new = strlen(fake_tls_sni);
|
||||
ssize_t slen_delta = slen_new-slen;
|
||||
if (slen_delta)
|
||||
{
|
||||
if ((*fake_tls_size+slen_delta)>fake_tls_buf_size)
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] not enough space for new SNI\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
memmove(sni+slen_new,sni+slen,fake_tls+*fake_tls_size-(sni+slen));
|
||||
phton16(fake_tls+3,(uint16_t)(pntoh16(fake_tls+3)+slen_delta));
|
||||
phton24(fake_tls+6,(uint32_t)(pntoh24(fake_tls+6)+slen_delta));
|
||||
phton16(fake_tls+modcache->extlen_offset,(uint16_t)(pntoh16(fake_tls+modcache->extlen_offset)+slen_delta));
|
||||
phton16(sniext-2,(uint16_t)(pntoh16(sniext-2)+slen_delta));
|
||||
phton16(sniext,(uint16_t)(pntoh16(sniext)+slen_delta));
|
||||
phton16(sni-2,(uint16_t)(pntoh16(sni-2)+slen_delta));
|
||||
*fake_tls_size+=slen_delta;
|
||||
slen = slen_new;
|
||||
}
|
||||
DLOG("profile %d fake[%d] change sni to %s size_delta=%zd\n", profile_n, fake_n, fake_tls_sni,slen_delta);
|
||||
memcpy(sni,fake_tls_sni,slen_new);
|
||||
}
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_RND_SNI)
|
||||
{
|
||||
if (!slen)
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] rndsni set but tls fake has zero sized SNI\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *s1=NULL, *s2=NULL;
|
||||
if (params.debug)
|
||||
{
|
||||
if ((s1 = malloc(slen+1)))
|
||||
{
|
||||
memcpy(s1,sni,slen); s1[slen]=0;
|
||||
}
|
||||
}
|
||||
|
||||
fill_random_az(sni,1);
|
||||
if (slen>=7) // domain name in SNI must be at least 3 chars long to enable xxx.tls randomization
|
||||
{
|
||||
fill_random_az09(sni+1,slen-5);
|
||||
sni[slen-4] = '.';
|
||||
memcpy(sni+slen-3,tld[random()%(sizeof(tld)/sizeof(*tld))],3);
|
||||
}
|
||||
else
|
||||
fill_random_az09(sni+1,slen-1);
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
if (s1 && (s2 = malloc(slen+1)))
|
||||
{
|
||||
memcpy(s2,sni,slen); s2[slen]=0;
|
||||
DLOG("profile %d fake[%d] generated random SNI : %s -> %s\n",profile_n,fake_n,s1,s2);
|
||||
}
|
||||
free(s1); free(s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
|
||||
{
|
||||
if (TLSFindExt(fake_tls,*fake_tls_size,21,&ext,&extlen,false))
|
||||
{
|
||||
if ((ext-fake_tls+extlen)!=*fake_tls_size)
|
||||
@@ -1050,54 +1156,6 @@ static bool onetime_tls_mod_blob(int profile_n, int fake_n, uint8_t fake_tls_mod
|
||||
DLOG("profile %d fake[%d] tls padding is absent. added. padding length offset %zu\n", profile_n, fake_n, modcache->padlen_offset);
|
||||
}
|
||||
}
|
||||
if (fake_tls_mod & FAKE_TLS_MOD_RND_SNI)
|
||||
{
|
||||
if (!TLSFindExt(fake_tls,*fake_tls_size,0,&ext,&extlen,false))
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] rndsni set but tls fake does not have SNI\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
if (!TLSAdvanceToHostInSNI(&ext,&extlen,&slen))
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] rndsni set but tls fake has invalid SNI structure\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
if (!slen)
|
||||
{
|
||||
DLOG_ERR("profile %d fake[%d] rndsni set but tls fake has zero sized SNI\n", profile_n, fake_n);
|
||||
return false;
|
||||
}
|
||||
uint8_t *sni = fake_tls + (ext - fake_tls);
|
||||
|
||||
char *s1=NULL, *s2=NULL;
|
||||
if (params.debug)
|
||||
{
|
||||
if ((s1 = malloc(slen+1)))
|
||||
{
|
||||
memcpy(s1,sni,slen); s1[slen]=0;
|
||||
}
|
||||
}
|
||||
|
||||
fill_random_az(sni,1);
|
||||
if (slen>=7) // domain name in SNI must be at least 3 chars long to enable xxx.tls randomization
|
||||
{
|
||||
fill_random_az09(sni+1,slen-5);
|
||||
sni[slen-4] = '.';
|
||||
memcpy(sni+slen-3,tld[random()%(sizeof(tld)/sizeof(*tld))],3);
|
||||
}
|
||||
else
|
||||
fill_random_az09(sni+1,slen-1);
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
if (s1 && (s2 = malloc(slen+1)))
|
||||
{
|
||||
memcpy(s2,sni,slen); s2[slen]=0;
|
||||
DLOG("profile %d fake[%d] generated random SNI : %s -> %s\n",profile_n,fake_n,s1,s2);
|
||||
}
|
||||
free(s1); free(s2);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool onetime_tls_mod(struct desync_profile *dp)
|
||||
@@ -1126,7 +1184,7 @@ static bool onetime_tls_mod(struct desync_profile *dp)
|
||||
fake_tls->extra = malloc(sizeof(struct fake_tls_mod_cache));
|
||||
if (!fake_tls->extra) return false;
|
||||
}
|
||||
if (!onetime_tls_mod_blob(dp->n,n,dp->fake_tls_mod,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra))
|
||||
if (!onetime_tls_mod_blob(dp->n,n,dp->fake_tls_mod,dp->fake_tls_sni,fake_tls->data,&fake_tls->size,fake_tls->size_buf,(struct fake_tls_mod_cache*)fake_tls->extra))
|
||||
return false;
|
||||
}
|
||||
if (!bMod)
|
||||
@@ -1321,7 +1379,7 @@ static void exithelp(void)
|
||||
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
||||
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
||||
" --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-l7=[http|tls|quic|wireguard|dht|discord|stun|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
" --ipset-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
|
||||
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
@@ -1374,12 +1432,14 @@ 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=<filename>|0xHEX\t; file containing fake http request\n"
|
||||
" --dpi-desync-fake-tls=<filename>|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,dupsid,padencap\n"
|
||||
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap\n"
|
||||
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake payload\n"
|
||||
" --dpi-desync-fake-syndata=<filename>|0xHEX\t; file containing SYN data payload\n"
|
||||
" --dpi-desync-fake-quic=<filename>|0xHEX\t; file containing fake QUIC Initial\n"
|
||||
" --dpi-desync-fake-wireguard=<filename>|0xHEX\t; file containing fake wireguard handshake initiation\n"
|
||||
" --dpi-desync-fake-dht=<filename>|0xHEX\t\t; file containing DHT protocol fake payload (d1...e)\n"
|
||||
" --dpi-desync-fake-discord=<filename>|0xHEX\t; file containing discord protocol fake payload (Voice IP Discovery)\n"
|
||||
" --dpi-desync-fake-stun=<filename>|0xHEX\t; file containing STUN protocol fake payload\n"
|
||||
" --dpi-desync-fake-unknown-udp=<filename>|0xHEX\t; file containing unknown udp protocol fake payload\n"
|
||||
" --dpi-desync-udplen-increment=<int>\t\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\n"
|
||||
" --dpi-desync-udplen-pattern=<filename>|0xHEX\t; udp tail fill pattern\n"
|
||||
@@ -1604,43 +1664,45 @@ int main(int argc, char **argv)
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=43
|
||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=44
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=45
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=46
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=47
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=48
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=49
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=50
|
||||
{"hostlist",required_argument,0,0}, // optidx=51
|
||||
{"hostlist-domains",required_argument,0,0},// optidx=52
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=53
|
||||
{"hostlist-exclude-domains",required_argument,0,0},// optidx=54
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=55
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=56
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=57
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=58
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=59
|
||||
{"new",no_argument,0,0}, // optidx=60
|
||||
{"skip",no_argument,0,0}, // optidx=61
|
||||
{"filter-l3",required_argument,0,0}, // optidx=62
|
||||
{"filter-tcp",required_argument,0,0}, // optidx=63
|
||||
{"filter-udp",required_argument,0,0}, // optidx=64
|
||||
{"filter-l7",required_argument,0,0}, // optidx=65
|
||||
{"ipset",required_argument,0,0}, // optidx=66
|
||||
{"ipset-ip",required_argument,0,0}, // optidx=67
|
||||
{"ipset-exclude",required_argument,0,0},// optidx=68
|
||||
{"ipset-exclude-ip",required_argument,0,0}, // optidx=69
|
||||
{"dpi-desync-fake-discord",required_argument,0,0},// optidx=46
|
||||
{"dpi-desync-fake-stun",required_argument,0,0},// optidx=47
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=48
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=49
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=50
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=51
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=52
|
||||
{"hostlist",required_argument,0,0}, // optidx=53
|
||||
{"hostlist-domains",required_argument,0,0},// optidx=54
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=55
|
||||
{"hostlist-exclude-domains",required_argument,0,0},// optidx=56
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=57
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=58
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=59
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=60
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=61
|
||||
{"new",no_argument,0,0}, // optidx=62
|
||||
{"skip",no_argument,0,0}, // optidx=63
|
||||
{"filter-l3",required_argument,0,0}, // optidx=64
|
||||
{"filter-tcp",required_argument,0,0}, // optidx=65
|
||||
{"filter-udp",required_argument,0,0}, // optidx=66
|
||||
{"filter-l7",required_argument,0,0}, // optidx=67
|
||||
{"ipset",required_argument,0,0}, // optidx=68
|
||||
{"ipset-ip",required_argument,0,0}, // optidx=69
|
||||
{"ipset-exclude",required_argument,0,0},// optidx=70
|
||||
{"ipset-exclude-ip",required_argument,0,0}, // optidx=71
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=70
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=71
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=72
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=73
|
||||
#elif defined(__CYGWIN__)
|
||||
{"wf-iface",required_argument,0,0}, // optidx=70
|
||||
{"wf-l3",required_argument,0,0}, // optidx=71
|
||||
{"wf-tcp",required_argument,0,0}, // optidx=72
|
||||
{"wf-udp",required_argument,0,0}, // optidx=73
|
||||
{"wf-raw",required_argument,0,0}, // optidx=74
|
||||
{"wf-save",required_argument,0,0}, // optidx=75
|
||||
{"ssid-filter",required_argument,0,0}, // optidx=76
|
||||
{"nlm-filter",required_argument,0,0}, // optidx=77
|
||||
{"nlm-list",optional_argument,0,0}, // optidx=78
|
||||
{"wf-iface",required_argument,0,0}, // optidx=72
|
||||
{"wf-l3",required_argument,0,0}, // optidx=73
|
||||
{"wf-tcp",required_argument,0,0}, // optidx=74
|
||||
{"wf-udp",required_argument,0,0}, // optidx=75
|
||||
{"wf-raw",required_argument,0,0}, // optidx=76
|
||||
{"wf-save",required_argument,0,0}, // optidx=77
|
||||
{"ssid-filter",required_argument,0,0}, // optidx=78
|
||||
{"nlm-filter",required_argument,0,0}, // optidx=79
|
||||
{"nlm-list",optional_argument,0,0}, // optidx=80
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
@@ -2043,11 +2105,11 @@ int main(int argc, char **argv)
|
||||
load_blob_to_collection(optarg, &dp->fake_http, FAKE_MAX_TCP,0);
|
||||
break;
|
||||
case 39: /* dpi-desync-fake-tls */
|
||||
load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4);
|
||||
load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->fake_tls_sni));
|
||||
dp->fake_tls_mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
|
||||
break;
|
||||
case 40: /* dpi-desync-fake-tls-mod */
|
||||
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod))
|
||||
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod,dp->fake_tls_sni,sizeof(dp->fake_tls_sni)))
|
||||
{
|
||||
DLOG_ERR("Invalid tls mod : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
@@ -2069,17 +2131,23 @@ int main(int argc, char **argv)
|
||||
case 45: /* dpi-desync-fake-dht */
|
||||
load_blob_to_collection(optarg, &dp->fake_dht, FAKE_MAX_UDP, 0);
|
||||
break;
|
||||
case 46: /* dpi-desync-fake-unknown-udp */
|
||||
case 46: /* dpi-desync-fake-discord */
|
||||
load_blob_to_collection(optarg, &dp->fake_discord, FAKE_MAX_UDP, 0);
|
||||
break;
|
||||
case 47: /* dpi-desync-fake-stun */
|
||||
load_blob_to_collection(optarg, &dp->fake_stun, FAKE_MAX_UDP, 0);
|
||||
break;
|
||||
case 48: /* dpi-desync-fake-unknown-udp */
|
||||
load_blob_to_collection(optarg, &dp->fake_unknown_udp, FAKE_MAX_UDP, 0);
|
||||
break;
|
||||
case 47: /* dpi-desync-udplen-increment */
|
||||
case 49: /* dpi-desync-udplen-increment */
|
||||
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000)
|
||||
{
|
||||
DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 48: /* dpi-desync-udplen-pattern */
|
||||
case 50: /* dpi-desync-udplen-pattern */
|
||||
{
|
||||
char buf[sizeof(dp->udplen_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
@@ -2087,21 +2155,21 @@ int main(int argc, char **argv)
|
||||
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 49: /* desync-cutoff */
|
||||
case 51: /* desync-cutoff */
|
||||
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
|
||||
{
|
||||
DLOG_ERR("invalid desync-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 50: /* desync-start */
|
||||
case 52: /* desync-start */
|
||||
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
|
||||
{
|
||||
DLOG_ERR("invalid desync-start value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 51: /* hostlist */
|
||||
case 53: /* hostlist */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, false, optarg))
|
||||
{
|
||||
@@ -2109,7 +2177,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 52: /* hostlist-domains */
|
||||
case 54: /* hostlist-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
||||
{
|
||||
@@ -2122,7 +2190,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 53: /* hostlist-exclude */
|
||||
case 55: /* hostlist-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, true, optarg))
|
||||
{
|
||||
@@ -2130,7 +2198,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 54: /* hostlist-exclude-domains */
|
||||
case 56: /* hostlist-exclude-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
||||
{
|
||||
@@ -2143,7 +2211,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 55: /* hostlist-auto */
|
||||
case 57: /* hostlist-auto */
|
||||
if (bSkip) break;
|
||||
if (dp->hostlist_auto)
|
||||
{
|
||||
@@ -2171,7 +2239,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 56: /* hostlist-auto-fail-threshold */
|
||||
case 58: /* hostlist-auto-fail-threshold */
|
||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
@@ -2179,7 +2247,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 57: /* hostlist-auto-fail-time */
|
||||
case 59: /* hostlist-auto-fail-time */
|
||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_time<1)
|
||||
{
|
||||
@@ -2187,7 +2255,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 58: /* hostlist-auto-retrans-threshold */
|
||||
case 60: /* hostlist-auto-retrans-threshold */
|
||||
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
|
||||
{
|
||||
@@ -2195,7 +2263,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 59: /* hostlist-auto-debug */
|
||||
case 61: /* hostlist-auto-debug */
|
||||
{
|
||||
FILE *F = fopen(optarg,"a+t");
|
||||
if (!F)
|
||||
@@ -2209,7 +2277,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 60: /* new */
|
||||
case 62: /* new */
|
||||
if (bSkip)
|
||||
{
|
||||
dp_clear(dp);
|
||||
@@ -2231,18 +2299,18 @@ int main(int argc, char **argv)
|
||||
anon_hl = anon_hl_exclude = NULL;
|
||||
anon_ips = anon_ips_exclude = NULL;
|
||||
break;
|
||||
case 61: /* skip */
|
||||
case 63: /* skip */
|
||||
bSkip = true;
|
||||
break;
|
||||
|
||||
case 62: /* filter-l3 */
|
||||
case 64: /* filter-l3 */
|
||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --filter-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 63: /* filter-tcp */
|
||||
case 65: /* filter-tcp */
|
||||
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
@@ -2252,7 +2320,7 @@ int main(int argc, char **argv)
|
||||
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 64: /* filter-udp */
|
||||
case 66: /* filter-udp */
|
||||
if (!parse_pf_list(optarg,&dp->pf_udp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
@@ -2262,14 +2330,14 @@ int main(int argc, char **argv)
|
||||
if (!port_filters_deny_if_empty(&dp->pf_tcp))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 65: /* filter-l7 */
|
||||
case 67: /* filter-l7 */
|
||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||
{
|
||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 66: /* ipset */
|
||||
case 68: /* ipset */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, false, optarg))
|
||||
{
|
||||
@@ -2277,7 +2345,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 67: /* ipset-ip */
|
||||
case 69: /* ipset-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||
{
|
||||
@@ -2290,7 +2358,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 68: /* ipset-exclude */
|
||||
case 70: /* ipset-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, true, optarg))
|
||||
{
|
||||
@@ -2298,7 +2366,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 69: /* ipset-exclude-ip */
|
||||
case 71: /* ipset-exclude-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||
{
|
||||
@@ -2314,28 +2382,28 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
case 70: /* bind-fix4 */
|
||||
case 72: /* bind-fix4 */
|
||||
params.bind_fix4 = true;
|
||||
break;
|
||||
case 71: /* bind-fix6 */
|
||||
case 73: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#elif defined(__CYGWIN__)
|
||||
case 70: /* wf-iface */
|
||||
case 72: /* wf-iface */
|
||||
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
|
||||
{
|
||||
DLOG_ERR("bad value for --wf-iface\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 71: /* wf-l3 */
|
||||
case 73: /* wf-l3 */
|
||||
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --wf-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 72: /* wf-tcp */
|
||||
case 74: /* 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)))
|
||||
@@ -2344,7 +2412,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 73: /* wf-udp */
|
||||
case 75: /* 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)))
|
||||
@@ -2353,7 +2421,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 74: /* wf-raw */
|
||||
case 76: /* wf-raw */
|
||||
hash_wf_raw=hash_jen(optarg,strlen(optarg));
|
||||
if (optarg[0]=='@')
|
||||
{
|
||||
@@ -2367,11 +2435,11 @@ int main(int argc, char **argv)
|
||||
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case 75: /* wf-save */
|
||||
case 77: /* wf-save */
|
||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||
break;
|
||||
case 76: /* ssid-filter */
|
||||
case 78: /* ssid-filter */
|
||||
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
@@ -2389,7 +2457,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 77: /* nlm-filter */
|
||||
case 79: /* nlm-filter */
|
||||
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
@@ -2407,7 +2475,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 78: /* nlm-list */
|
||||
case 80: /* nlm-list */
|
||||
if (!nlm_list(optarg && !strcmp(optarg,"all")))
|
||||
{
|
||||
DLOG_ERR("could not get list of NLM networks\n");
|
||||
|
35
nfq/params.c
35
nfq/params.c
@@ -206,7 +206,7 @@ bool dp_fake_defaults(struct desync_profile *dp)
|
||||
return false;
|
||||
if (blob_collection_empty(&dp->fake_tls))
|
||||
{
|
||||
if (!blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4))
|
||||
if (!blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(dp->fake_tls_sni)))
|
||||
return false;
|
||||
}
|
||||
if (blob_collection_empty(&dp->fake_unknown))
|
||||
@@ -222,23 +222,15 @@ bool dp_fake_defaults(struct desync_profile *dp)
|
||||
memset(item->data,0,item->size);
|
||||
item->data[0] = 0x40;
|
||||
}
|
||||
if (blob_collection_empty(&dp->fake_wg))
|
||||
struct blob_collection_head **fake,*fakes_z64[] = {&dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, &dp->fake_unknown_udp,NULL};
|
||||
for(fake=fakes_z64;*fake;fake++)
|
||||
{
|
||||
if (!(item=blob_collection_add_blob(&dp->fake_wg,NULL,64,0)))
|
||||
return false;
|
||||
memset(item->data,0,item->size);
|
||||
}
|
||||
if (blob_collection_empty(&dp->fake_dht))
|
||||
{
|
||||
if (!(item=blob_collection_add_blob(&dp->fake_dht,NULL,64,0)))
|
||||
return false;
|
||||
memset(item->data,0,item->size);
|
||||
}
|
||||
if (blob_collection_empty(&dp->fake_unknown_udp))
|
||||
{
|
||||
if (!(item=blob_collection_add_blob(&dp->fake_unknown_udp,NULL,64,0)))
|
||||
return false;
|
||||
memset(item->data,0,item->size);
|
||||
if (blob_collection_empty(*fake))
|
||||
{
|
||||
if (!(item=blob_collection_add_blob(*fake,NULL,64,0)))
|
||||
return false;
|
||||
memset(item->data,0,item->size);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -269,14 +261,9 @@ static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
ipset_collection_destroy(&dp->ips_collection_exclude);
|
||||
port_filters_destroy(&dp->pf_tcp);
|
||||
port_filters_destroy(&dp->pf_udp);
|
||||
blob_collection_destroy(&dp->fake_http);
|
||||
blob_collection_destroy(&dp->fake_tls);
|
||||
blob_collection_destroy(&dp->fake_unknown);
|
||||
blob_collection_destroy(&dp->fake_unknown_udp);
|
||||
blob_collection_destroy(&dp->fake_quic);
|
||||
blob_collection_destroy(&dp->fake_wg);
|
||||
blob_collection_destroy(&dp->fake_dht);
|
||||
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
|
||||
struct blob_collection_head **fake,*fakes[] = {&dp->fake_http, &dp->fake_tls, &dp->fake_unknown, &dp->fake_unknown_udp, &dp->fake_quic, &dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, NULL};
|
||||
for(fake=fakes;*fake;fake++) blob_collection_destroy(*fake);
|
||||
}
|
||||
void dp_clear(struct desync_profile *dp)
|
||||
{
|
||||
|
@@ -44,7 +44,8 @@
|
||||
#define FAKE_TLS_MOD_RND 0x10
|
||||
#define FAKE_TLS_MOD_DUP_SID 0x20
|
||||
#define FAKE_TLS_MOD_RND_SNI 0x40
|
||||
#define FAKE_TLS_MOD_PADENCAP 0x80
|
||||
#define FAKE_TLS_MOD_SNI 0x80
|
||||
#define FAKE_TLS_MOD_PADENCAP 0x100
|
||||
|
||||
#define FAKE_MAX_TCP 1460
|
||||
#define FAKE_MAX_UDP 1472
|
||||
@@ -83,11 +84,12 @@ struct desync_profile
|
||||
uint32_t desync_fooling_mode;
|
||||
uint32_t desync_badseq_increment, desync_badseq_ack_increment;
|
||||
|
||||
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht;
|
||||
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
|
||||
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
|
||||
size_t fake_syndata_size;
|
||||
|
||||
uint8_t fake_tls_mod;
|
||||
uint32_t fake_tls_mod;
|
||||
char fake_tls_sni[64];
|
||||
|
||||
int udplen_increment;
|
||||
|
||||
|
@@ -35,6 +35,8 @@ const char *l7proto_str(t_l7proto l7)
|
||||
case QUIC: return "quic";
|
||||
case WIREGUARD: return "wireguard";
|
||||
case DHT: return "dht";
|
||||
case DISCORD: return "discord";
|
||||
case STUN: return "stun";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
@@ -45,7 +47,9 @@ bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7)
|
||||
(l7proto==TLS && (filter_l7 & L7_PROTO_TLS)) ||
|
||||
(l7proto==QUIC && (filter_l7 & L7_PROTO_QUIC)) ||
|
||||
(l7proto==WIREGUARD && (filter_l7 & L7_PROTO_WIREGUARD)) ||
|
||||
(l7proto==DHT && (filter_l7 & L7_PROTO_DHT));
|
||||
(l7proto==DHT && (filter_l7 & L7_PROTO_DHT)) ||
|
||||
(l7proto==DISCORD && (filter_l7 & L7_PROTO_DISCORD)) ||
|
||||
(l7proto==STUN && (filter_l7 & L7_PROTO_STUN));
|
||||
}
|
||||
|
||||
#define PM_ABS 0
|
||||
@@ -1006,3 +1010,18 @@ bool IsDhtD1(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=7 && data[0]=='d' && data[1]=='1' && data[len-1]=='e';
|
||||
}
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==74 &&
|
||||
data[0]==0 && data[1]==1 &&
|
||||
data[2]==0 && data[3]==70 &&
|
||||
data[8]==0 && memcmp(&data[8],&data[9],63)==0; // address is not set in requests
|
||||
}
|
||||
bool IsStunMessage(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=20 && // header size
|
||||
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
|
||||
(data[3]&0b11)==0 && // length must be a multiple of 4
|
||||
ntohl(*(uint32_t*)(&data[4]))==0x2112A442 && // magic cookie
|
||||
ntohs(*(uint16_t*)(&data[2]))==len-20;
|
||||
}
|
||||
|
@@ -7,12 +7,14 @@
|
||||
#include "crypto/aes-gcm.h"
|
||||
#include "helpers.h"
|
||||
|
||||
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto;
|
||||
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT, DISCORD, STUN} t_l7proto;
|
||||
#define L7_PROTO_HTTP 0x00000001
|
||||
#define L7_PROTO_TLS 0x00000002
|
||||
#define L7_PROTO_QUIC 0x00000004
|
||||
#define L7_PROTO_WIREGUARD 0x00000008
|
||||
#define L7_PROTO_DHT 0x00000010
|
||||
#define L7_PROTO_DISCORD 0x00000020
|
||||
#define L7_PROTO_STUN 0x00000040
|
||||
#define L7_PROTO_UNKNOWN 0x80000000
|
||||
const char *l7proto_str(t_l7proto l7);
|
||||
bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7);
|
||||
@@ -72,6 +74,8 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
|
||||
|
||||
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len);
|
||||
bool IsDhtD1(const uint8_t *data, size_t len);
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
|
||||
bool IsStunMessage(const uint8_t *data, size_t len);
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
@@ -3,7 +3,7 @@ CFLAGS += -std=gnu99 -Os -flto=auto
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
LIBS = -lz -lpthread
|
||||
LIBS_SYSTEMD = -lz -lsystemd
|
||||
LIBS_SYSTEMD = -lsystemd
|
||||
LIBS_ANDROID = -lz
|
||||
SRC_FILES = *.c
|
||||
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
|
||||
@@ -14,7 +14,7 @@ tpws: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS)
|
||||
|
||||
systemd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o tpws $(SRC_FILES) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o tpws $(SRC_FILES) $(LIBS) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
|
||||
android: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS)
|
||||
|
Reference in New Issue
Block a user