Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-14 06:13:09 +00:00

nfqws2: --payload-disable

This commit is contained in:
bol-van
2026-01-11 17:25:08 +03:00
parent 5a7e2b1ca2
commit f93c6de772
9 changed files with 89 additions and 80 deletions

View File

@@ -176,3 +176,4 @@ v0.8.1
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
* nfqws2: move ctx from lightuserdata to userdata. prevents crashes on specific ARM cpus
* nfqws2: alternative representation of payload filter in execution_plan item
* nfqws2: --payload-disable

View File

@@ -612,10 +612,11 @@ General parameters for all versions - nfqws2, dvtws2, winws2.
--pidfile=<filename> ; write PID to a file
--ctrack-timeouts=S:E:F[:U] ; conntrack timeouts for tcp stages (SYN, ESTABLISHED, FIN) and for udp
--ctrack-disable=[0|1] ; 1 disables conntrack
--payload-disable=[type[,type]] ; do not discover these payload types. for available payload types see '--payload'. disable all if no argument.
--server=[0|1] ; server mode. modifies various aspects of direction selection and source/destination ip/port for handling listeners
--ipcache-lifetime=<int> ; IP cache entry lifetime in seconds. 0 - unlimited.
--ipcache-hostname=[0|1] ; 1 or no argument enables hostname caching for use in zero-phase strategies
--reasm-disable=[proto[,proto]] ; disable fragment reassembly for a list of payloads: tls_client_hello quic_initial. without arguments - disable reasm for everything.
--reasm-disable=[type[,type]] ; disable fragment reassembly for a list of payloads: tls_client_hello quic_initial. without arguments - disable reasm for everything.
DESYNC ENGINE INIT:
--writeable[=<dir_name>] ; create a directory for Lua with write permissions and store its path in the "WRITEABLE" env variable (only one directory)

View File

@@ -668,10 +668,11 @@ nfqws2 использует стандартный парсер getopt_long_only
--pidfile=<filename> ; запись PID в файл
--ctrack-timeouts=S:E:F[:U] ; таймауты conntrack для стадий tcp SYN, ESTABLISHED, FIN и для udp
--ctrack-disable=[0|1] ; 1 отключает conntrack
--payload-disable=[type[,type]] ; отключить распознавание указанных типов пейлоадов. без аргумента - отключить все.
--server=[0|1] ; серверный режим. для обслуживания listener-ов меняются многие аспекты выбора направления и ip/port источника/приемника
--ipcache-lifetime=<int> ; время жизни записей кэша IP в секундах. 0 - без ограничений.
--ipcache-hostname=[0|1] ; 1 или отсутствие аргумента включают кэширование имен хостов для применения в стратегиях нулевой фазы
--reasm-disable=[proto[,proto]] ; отключить сборку фрагментов для списка пейлоадов : tls_client_hello quic_initial . без аргумента - отключить reasm для всего.
--reasm-disable=[type[,type]] ; отключить сборку фрагментов для списка пейлоадов : tls_client_hello quic_initial . без аргумента - отключить reasm для всего.
DESYNC ENGINE INIT:
--writeable[=<dir_name>] ; создать директорию для Lua с разрешением записи и поместить путь к ней в переменную env "WRITEABLE" (только одна директория)

View File

@@ -30,7 +30,7 @@ static void protocol_probe(t_protocol_probe *probe, int probe_count, const uint8
{
for (int i = 0; i < probe_count; i++)
{
if ((!probe[i].l7match || *l7proto==probe[i].l7) && probe[i].check(data_payload, len_payload))
if (!l7_payload_match(probe[i].l7p, params.payload_disable) && (!probe[i].l7match || *l7proto==probe[i].l7) && probe[i].check(data_payload, len_payload))
{
*l7payload = probe[i].l7p;
if (*l7proto == L7_UNKNOWN)
@@ -1280,88 +1280,78 @@ static uint8_t dpi_desync_tcp_packet_play(
process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin);
if (IsHttp(rdata_payload, rlen_payload))
t_protocol_probe testers[] = {
{L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial},
{L7P_HTTP_REQ,L7_HTTP,IsHttp,false},
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
if (l7payload==L7P_UNKNOWN)
{
DLOG("packet contains HTTP request\n");
l7payload = L7P_HTTP_REQ;
if (l7proto == L7_UNKNOWN)
// this is special type. detection requires AES and can be successful only for the first data packet. no reason to AES every packet
if (ctrack && (ctrack->pos.client.seq_last - ctrack->pos.client.seq0)==1)
{
l7proto = L7_HTTP;
if (ctrack && ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
}
// we do not reassemble http
reasm_client_cancel(ctrack);
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
if (!bHaveHost)
{
DLOG("not applying tampering to HTTP without Host:\n");
goto pass;
t_protocol_probe testers[] = {
{L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
}
}
else if (IsTLSClientHello(rdata_payload, rlen_payload, TLS_PARTIALS_ENABLE))
switch(l7payload)
{
bool bReqFull = IsTLSRecordFull(rdata_payload, rlen_payload);
DLOG(bReqFull ? "packet contains full TLS ClientHello\n" : "packet contains partial TLS ClientHello\n");
l7payload = L7P_TLS_CLIENT_HELLO;
if (l7proto == L7_UNKNOWN)
{
l7proto = L7_TLS;
if (ctrack && ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
}
case L7P_HTTP_REQ:
// we do not reassemble http
reasm_client_cancel(ctrack);
if (bReqFull) TLSDebug(rdata_payload, rlen_payload);
bHaveHost = TLSHelloExtractHost(rdata_payload, rlen_payload, host, sizeof(host), TLS_PARTIALS_ENABLE);
if (ctrack && !(params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable)))
{
// do not reasm retransmissions
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_client) && !is_retransmission(&ctrack->pos.client))
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
if (!bHaveHost)
{
// do not reconstruct unexpected large payload (they are feeding garbage ?)
if (!reasm_client_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
goto pass_reasm_cancel;
DLOG("not applying tampering to HTTP without Host:\n");
goto pass;
}
if (!ReasmIsEmpty(&ctrack->reasm_client))
break;
case L7P_TLS_CLIENT_HELLO:
{
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
bool bReqFull = IsTLSRecordFull(rdata_payload, rlen_payload);
DLOG(bReqFull ? "TLS ClientHello is FULL\n" : "TLS ClientHello is PARTIAL\n");
if (bReqFull) TLSDebug(rdata_payload, rlen_payload);
bHaveHost = TLSHelloExtractHost(rdata_payload, rlen_payload, host, sizeof(host), true);
if (ctrack && !l7_payload_match(l7payload, params.reasm_payload_disable))
{
// do not reasm retransmissions
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_client) && !is_retransmission(&ctrack->pos.client))
{
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
// do not reconstruct unexpected large payload (they are feeding garbage ?)
if (!reasm_client_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
goto pass_reasm_cancel;
}
else
if (!ReasmIsEmpty(&ctrack->reasm_client))
{
DLOG_ERR("rawpacket_queue failed !\n");
goto pass_reasm_cancel;
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
{
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
}
else
{
DLOG_ERR("rawpacket_queue failed !\n");
goto pass_reasm_cancel;
}
if (ReasmIsFull(&ctrack->reasm_client))
{
replay_queue(&ctrack->delayed);
reasm_client_fin(ctrack);
}
return VERDICT_DROP;
}
if (ReasmIsFull(&ctrack->reasm_client))
{
replay_queue(&ctrack->delayed);
reasm_client_fin(ctrack);
}
return VERDICT_DROP;
}
}
}
else if (ctrack && (ctrack->pos.client.seq_last - ctrack->pos.client.seq0)==1 && IsMTProto(dis->data_payload, dis->len_payload))
{
DLOG("packet contains telegram mtproto2 initial\n");
// mtproto detection requires aes. react only on the first tcp data packet. do not detect if ctrack unavailable.
l7payload = L7P_MTPROTO_INITIAL;
if (l7proto == L7_UNKNOWN)
{
l7proto = L7_MTPROTO;
if (ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
}
}
else
{
t_protocol_probe testers[] = {
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
break;
}
}
}
@@ -1764,7 +1754,7 @@ static uint8_t dpi_desync_udp_packet_play(
}
if (pclean)
{
bool reasm_disable = params.reasm_payload_disable && l7_payload_match(l7payload, params.reasm_payload_disable);
bool reasm_disable = l7_payload_match(l7payload, params.reasm_payload_disable);
if (ctrack && !reasm_disable && !ReasmIsEmpty(&ctrack->reasm_client))
{
if (ReasmHasSpace(&ctrack->reasm_client, clean_len))
@@ -1826,7 +1816,7 @@ static uint8_t dpi_desync_udp_packet_play(
{
data_decrypt = defrag + hello_offset;
len_decrypt = hello_len;
bHaveHost = TLSHelloExtractHostFromHandshake(data_decrypt, len_decrypt, host, sizeof(host), TLS_PARTIALS_ENABLE);
bHaveHost = TLSHelloExtractHostFromHandshake(data_decrypt, len_decrypt, host, sizeof(host), true);
}
else
{

View File

@@ -1378,10 +1378,11 @@ static void exithelp(void)
#endif
" --ctrack-timeouts=S:E:F[:U]\t\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
" --ctrack-disable=[0|1]\t\t\t\t\t; 1 or no argument disables conntrack\n"
" --payload-disable=[type[,type]]\t\t\t; do not discover these payload types. for available payload types see '--payload'. disable all if no argument.\n"
" --server=[0|1]\t\t\t\t\t\t; change multiple aspects of src/dst ip/port handling for incoming connections\n"
" --ipcache-lifetime=<int>\t\t\t\t; time in seconds to keep cached hop count and domain name (default %u). 0 = no expiration\n"
" --ipcache-hostname=[0|1]\t\t\t\t; 1 or no argument enables ip->hostname caching\n"
" --reasm-disable=[proto[,proto]]\t\t\t; disable reasm for these L7 payloads : tls_client_hello quic_initial . if no argument - disable all reasm.\n"
" --reasm-disable=[type[,type]]\t\t\t\t; disable reasm for these L7 payloads : tls_client_hello quic_initial . if no argument - disable all reasm.\n"
#ifdef __CYGWIN__
"\nWINDIVERT FILTER:\n"
" --wf-iface=<int>[.<int>]\t\t\t\t; numeric network interface and subinterface indexes\n"
@@ -1523,6 +1524,7 @@ enum opt_indices {
#endif
IDX_CTRACK_TIMEOUTS,
IDX_CTRACK_DISABLE,
IDX_PAYLOAD_DISABLE,
IDX_SERVER,
IDX_IPCACHE_LIFETIME,
IDX_IPCACHE_HOSTNAME,
@@ -1616,6 +1618,7 @@ static const struct option long_options[] = {
#endif
[IDX_CTRACK_TIMEOUTS] = {"ctrack-timeouts", required_argument, 0, 0},
[IDX_CTRACK_DISABLE] = {"ctrack-disable", optional_argument, 0, 0},
[IDX_PAYLOAD_DISABLE] = {"payload-disable", optional_argument, 0, 0},
[IDX_SERVER] = {"server", optional_argument, 0, 0},
[IDX_IPCACHE_LIFETIME] = {"ipcache-lifetime", required_argument, 0, 0},
[IDX_IPCACHE_HOSTNAME] = {"ipcache-hostname", optional_argument, 0, 0},
@@ -1945,6 +1948,18 @@ int main(int argc, char **argv)
case IDX_IPCACHE_HOSTNAME:
params.cache_hostname = !optarg || atoi(optarg);
break;
case IDX_PAYLOAD_DISABLE:
if (optarg)
{
if (!parse_l7p_list(optarg, &params.payload_disable))
{
DLOG_ERR("Invalid payload filter : %s\n", optarg);
exit_clean(1);
}
}
else
params.payload_disable = L7P_ALL;
break;
case IDX_REASM_DISABLE:
if (optarg)
{
@@ -1955,7 +1970,7 @@ int main(int argc, char **argv)
}
}
else
params.reasm_payload_disable = 0xFFFFFFFFFFFFFFFF;
params.reasm_payload_disable = L7P_ALL;
break;
#if defined(__linux__)
case IDX_FWMARK:

View File

@@ -532,6 +532,8 @@ void init_params(struct params_s *params)
LIST_INIT(&params->blobs);
LIST_INIT(&params->lua_init_scripts);
params->reasm_payload_disable = params->payload_disable = 1<<L7P_NONE;
#ifdef __CYGWIN__
LIST_INIT(&params->ssid_filter);
LIST_INIT(&params->nlm_filter);

View File

@@ -21,8 +21,6 @@
#include <wordexp.h>
#endif
#define TLS_PARTIALS_ENABLE true
#define RAW_SNDBUF (64*1024) // in bytes
#define Q_MAXLEN 1024 // in packets
@@ -176,6 +174,7 @@ struct params_s
unsigned int ipcache_lifetime;
ip_cache ipcache;
uint64_t reasm_payload_disable;
uint64_t payload_disable;
struct str_list_head lua_init_scripts;
bool writeable_dir_enable;

View File

@@ -675,7 +675,7 @@ ssize_t TLSPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
case PM_HOST_MIDSLD:
case PM_HOST_ENDSLD:
case PM_SNI_EXT:
if (TLSFindExt(data,sz,0,&ext,&elen,TLS_PARTIALS_ENABLE))
if (TLSFindExt(data,sz,0,&ext,&elen,true))
{
if (posmarker==PM_SNI_EXT)
{

View File

@@ -20,7 +20,7 @@ typedef enum {
L7_XMPP,
L7_DNS,
L7_MTPROTO,
L7_LAST, L7_INVALID=L7_LAST
L7_LAST, L7_INVALID=L7_LAST, L7_NONE=L7_LAST
} t_l7proto;
const char *l7proto_str(t_l7proto l7);
t_l7proto l7proto_from_name(const char *name);
@@ -53,7 +53,7 @@ typedef enum {
L7P_DNS_QUERY,
L7P_DNS_RESPONSE,
L7P_MTPROTO_INITIAL,
L7P_LAST, L7P_INVALID=L7P_LAST
L7P_LAST, L7P_INVALID=L7P_LAST, L7P_NONE=L7P_LAST
} t_l7payload;
t_l7payload l7payload_from_name(const char *name);
const char *l7payload_str(t_l7payload l7);