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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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" (только одна директория)
|
||||
|
||||
132
nfq2/desync.c
132
nfq2/desync.c
@@ -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
|
||||
{
|
||||
|
||||
19
nfq2/nfqws.c
19
nfq2/nfqws.c
@@ -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, ¶ms.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:
|
||||
|
||||
@@ -532,6 +532,8 @@ void init_params(struct params_s *params)
|
||||
LIST_INIT(¶ms->blobs);
|
||||
LIST_INIT(¶ms->lua_init_scripts);
|
||||
|
||||
params->reasm_payload_disable = params->payload_disable = 1<<L7P_NONE;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
LIST_INIT(¶ms->ssid_filter);
|
||||
LIST_INIT(¶ms->nlm_filter);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user