mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-26 20:20:53 +03:00
nfqws: DHT and tamper
This commit is contained in:
parent
91ac09a8bd
commit
c91542d516
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -237,3 +237,9 @@ nfqws : udplen fooling supports packet shrinking (negative increment value)
|
||||
v49
|
||||
|
||||
QUIC support integrated to the main system and setup
|
||||
|
||||
v50
|
||||
|
||||
DHT protocol support.
|
||||
DPI desync mode 'tamper' for DHT.
|
||||
HEX string support in addition to binary files.
|
||||
|
@ -154,7 +154,7 @@ nfqws takes the following parameters:
|
||||
--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=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen tamper
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
|
||||
@ -173,6 +173,7 @@ nfqws takes the following parameters:
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake 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-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
|
||||
@ -427,14 +428,15 @@ Set conntrack timeouts appropriately.
|
||||
|
||||
UDP attacks are limited. Its not possible to fragment UDP on transport level, only on network (ip) level.
|
||||
Only desync modes `fake`,`hopbyhop`,`destopt`,`ipfrag1` and `ipfrag2` are applicable.
|
||||
`fake`,`hopbyhop`,`destopt` can be used in combo with `ipfrag2` and `udplen`.
|
||||
`fake`,`hopbyhop`,`destopt` can be used in combo with `ipfrag2`.
|
||||
`fake` can be used in combo with `udplen` and `tamper`.
|
||||
|
||||
`udplen` increases udp payload size by `--dpi-desync-udplen-increment` bytes. Padding is filled with zeroes.
|
||||
`udplen` increases udp payload size by `--dpi-desync-udplen-increment` bytes. Padding is filled with zeroes by default but can be overriden with a pattern.
|
||||
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 is also recognized.
|
||||
Wireguard handshake initiation and DHT 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 v.49
|
||||
zapret v.50
|
||||
|
||||
English
|
||||
-------
|
||||
@ -207,7 +207,7 @@ nfqws
|
||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen tamper
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||||
@ -223,6 +223,7 @@ nfqws
|
||||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному w3.org
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для 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. по умолчанию - нули
|
||||
@ -464,14 +465,17 @@ window size итоговый размер окна стал максимальн
|
||||
|
||||
ПОДДЕРЖКА UDP
|
||||
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
||||
Для UDP действуют только режимы десинхронизации fake,hopbyhop,destopt,ipfrag1,ipfrag2,udplen.
|
||||
Возможно сочетание fake,hopbyhop,destopt с ipfrag2 и udplen.
|
||||
Для UDP действуют только режимы десинхронизации fake,hopbyhop,destopt,ipfrag1,ipfrag2,udplen,tamper.
|
||||
Возможно сочетание fake,hopbyhop,destopt с ipfrag2, fake,fakeknown с udplen и tamper.
|
||||
udplen увеличивает размер udp пакета на указанное в --dpi-desync-udplen-increment количество байтов.
|
||||
Паддинг заполняется нулями. Предназначено для обмана DPI, ориентирующегося на размеры пакетов.
|
||||
Паддинг заполняется нулями по умолчанию, но можно задать свой паттерн.
|
||||
Предназначено для обмана DPI, ориентирующегося на размеры пакетов.
|
||||
Может сработать, если пользовательсткий протокол не привязан жестко к размеру udp пейлоада.
|
||||
Режим tamper означает модификацию пакетов известных протоколов особенным для протокола образом.
|
||||
На текущий момент работает только с DHT.
|
||||
Поддерживается определение пакетов QUIC Initial с расшифровкой содержимого и имени хоста, то есть параметр
|
||||
--hostlist будет работать.
|
||||
Определяется пакет wireguard handshake initiation.
|
||||
Определяются пакеты wireguard handshake initiation и DHT (начинается с 'd1', кончается 'e').
|
||||
Для десинхронизации других протоколов обязательно указывать --dpi-desync-any-protocol.
|
||||
Реализован conntrack для udp. Можно пользоваться --dpi-desync-cutoff. Таймаут conntrack для udp
|
||||
можно изменить 4-м параметром в --ctrack-timeouts.
|
||||
|
44
nfq/desync.c
44
nfq/desync.c
@ -75,7 +75,7 @@ bool desync_only_first_stage(enum dpi_desync_mode mode)
|
||||
}
|
||||
bool desync_valid_second_stage(enum dpi_desync_mode mode)
|
||||
{
|
||||
return mode==DESYNC_NONE || mode==DESYNC_DISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_SPLIT || mode==DESYNC_SPLIT2 || mode==DESYNC_IPFRAG2 || mode==DESYNC_UDPLEN;
|
||||
return mode==DESYNC_NONE || mode==DESYNC_DISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_SPLIT || mode==DESYNC_SPLIT2 || mode==DESYNC_IPFRAG2 || mode==DESYNC_UDPLEN || mode==DESYNC_TAMPER;
|
||||
}
|
||||
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode)
|
||||
{
|
||||
@ -83,7 +83,7 @@ bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode)
|
||||
}
|
||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode)
|
||||
{
|
||||
return mode==DESYNC_NONE || mode==DESYNC_UDPLEN || mode==DESYNC_IPFRAG2;
|
||||
return mode==DESYNC_NONE || mode==DESYNC_UDPLEN || mode==DESYNC_TAMPER || mode==DESYNC_IPFRAG2;
|
||||
}
|
||||
enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
{
|
||||
@ -117,6 +117,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
return DESYNC_IPFRAG1;
|
||||
else if (!strcmp(s,"udplen"))
|
||||
return DESYNC_UDPLEN;
|
||||
else if (!strcmp(s,"tamper"))
|
||||
return DESYNC_TAMPER;
|
||||
return DESYNC_INVALID;
|
||||
}
|
||||
|
||||
@ -734,6 +736,13 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
|
||||
fake_size = params.fake_wg_size;
|
||||
bKnownProtocol = true;
|
||||
}
|
||||
else if (IsDhtD1(data_payload,len_payload))
|
||||
{
|
||||
DLOG("packet contains DHT d1...e\n")
|
||||
fake = params.fake_dht;
|
||||
fake_size = params.fake_dht_size;
|
||||
bKnownProtocol = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!params.desync_any_proto) return res;
|
||||
@ -846,6 +855,37 @@ packet_process_result dpi_desync_udp_packet(uint32_t fwmark, const char *ifout,
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
return drop;
|
||||
case DESYNC_TAMPER:
|
||||
if (IsDhtD1(data_payload,len_payload))
|
||||
{
|
||||
size_t szbuf,szcopy;
|
||||
memcpy(pkt2,"d2:zz1:x",8);
|
||||
pkt2_len=8;
|
||||
szbuf=sizeof(pkt2)-pkt2_len;
|
||||
szcopy=len_payload-1;
|
||||
if (szcopy>szbuf)
|
||||
{
|
||||
DLOG("packet is too long to tamper");
|
||||
return res;
|
||||
}
|
||||
memcpy(pkt2+pkt2_len,data_payload+1,szcopy);
|
||||
pkt2_len+=szcopy;
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
|
||||
{
|
||||
DLOG("could not construct packet with modified length. too large ?\n");
|
||||
return res;
|
||||
}
|
||||
DLOG("resending tampered DHT\n");
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return res;
|
||||
return drop;
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG("payload is not tamperable\n");
|
||||
return res;
|
||||
}
|
||||
case DESYNC_IPFRAG2:
|
||||
{
|
||||
|
||||
|
@ -34,7 +34,8 @@ enum dpi_desync_mode {
|
||||
DESYNC_HOPBYHOP,
|
||||
DESYNC_DESTOPT,
|
||||
DESYNC_IPFRAG1,
|
||||
DESYNC_UDPLEN
|
||||
DESYNC_UDPLEN,
|
||||
DESYNC_TAMPER
|
||||
};
|
||||
|
||||
extern const char *fake_http_request_default;
|
||||
|
41
nfq/nfqws.c
41
nfq/nfqws.c
@ -522,7 +522,7 @@ static void exithelp()
|
||||
" --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=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen\n"
|
||||
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 ipfrag2 udplen tamper\n"
|
||||
#ifdef __linux__
|
||||
" --dpi-desync-fwmark=<int|0xHEX>\t\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
@ -547,6 +547,7 @@ static void exithelp()
|
||||
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake 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-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"
|
||||
@ -660,6 +661,7 @@ int main(int argc, char **argv)
|
||||
params.fake_quic_size = 620; // must be 601+ for TSPU hack
|
||||
params.fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
|
||||
params.fake_wg_size = 64;
|
||||
params.fake_dht_size = 64;
|
||||
params.fake_unknown_size = 256;
|
||||
params.fake_unknown_udp_size = 64;
|
||||
params.wscale=-1; // default - dont change scale factor (client)
|
||||
@ -728,15 +730,16 @@ int main(int argc, char **argv)
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=30
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=31
|
||||
{"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-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
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=34
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=35
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=36
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=37
|
||||
{"hostlist",required_argument,0,0}, // optidx=38
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=39
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=39
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=40
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=40
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=41
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
@ -1022,18 +1025,22 @@ int main(int argc, char **argv)
|
||||
params.fake_wg_size = sizeof(params.fake_wg);
|
||||
load_file_or_exit(optarg,params.fake_wg,¶ms.fake_wg_size);
|
||||
break;
|
||||
case 33: /* dpi-desync-fake-unknown-udp */
|
||||
case 33: /* dpi-desync-fake-dht */
|
||||
params.fake_dht_size = sizeof(params.fake_dht);
|
||||
load_file_or_exit(optarg,params.fake_dht,¶ms.fake_dht_size);
|
||||
break;
|
||||
case 34: /* dpi-desync-fake-unknown-udp */
|
||||
params.fake_unknown_udp_size = sizeof(params.fake_unknown_udp);
|
||||
load_file_or_exit(optarg,params.fake_unknown_udp,¶ms.fake_unknown_udp_size);
|
||||
break;
|
||||
case 34: /* dpi-desync-udplen-increment */
|
||||
case 35: /* dpi-desync-udplen-increment */
|
||||
if (sscanf(optarg,"%d",¶ms.udplen_increment)<1 || params.udplen_increment>0x7FFF || params.udplen_increment<-0x8000)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 35: /* dpi-desync-udplen-pattern */
|
||||
case 36: /* dpi-desync-udplen-pattern */
|
||||
{
|
||||
char buf[sizeof(params.udplen_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
@ -1041,21 +1048,21 @@ int main(int argc, char **argv)
|
||||
fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 36: /* desync-cutoff */
|
||||
case 37: /* 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 37: /* hostlist */
|
||||
case 38: /* hostlist */
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 38: /* hostlist-exclude */
|
||||
case 39: /* hostlist-exclude */
|
||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
@ -1063,10 +1070,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#ifdef __linux__
|
||||
case 39: /* bind-fix4 */
|
||||
case 40: /* bind-fix4 */
|
||||
params.bind_fix4 = true;
|
||||
break;
|
||||
case 40: /* bind-fix6 */
|
||||
case 41: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#endif
|
||||
|
@ -50,8 +50,8 @@ 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], udplen_pattern[1472];
|
||||
size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_unknown_size,fake_unknown_udp_size;
|
||||
uint8_t fake_http[1432],fake_tls[1432],fake_quic[1472],fake_wg[1472],fake_dht[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_dht_size,fake_unknown_size,fake_unknown_udp_size;
|
||||
int udplen_increment;
|
||||
bool droproot;
|
||||
uid_t uid;
|
||||
|
@ -192,7 +192,10 @@ bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==148 && data[0]==1 && data[1]==0 && data[2]==0 && data[3]==0;
|
||||
}
|
||||
|
||||
bool IsDhtD1(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=3 && data[0]=='d' && data[1]=='1' && data[len-1]=='e';
|
||||
}
|
||||
|
||||
/* Returns the QUIC draft version or 0 if not applicable. */
|
||||
uint8_t QUICDraftVersion(uint32_t version)
|
||||
|
@ -16,6 +16,7 @@ bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len
|
||||
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host);
|
||||
|
||||
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len);
|
||||
bool IsDhtD1(const uint8_t *data, size_t len);
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
Loading…
Reference in New Issue
Block a user