Browse Source

winws: --wf-raw-part

pull/1129/merge
bol-van 21 hours ago
parent
commit
07eee8af25
  1. 4
      docs/changes.txt
  2. 6
      init.d/windivert.filter.examples/README.txt
  3. 29
      init.d/windivert.filter.examples/windivert.discord_media+stun.txt
  4. 8
      init.d/windivert.filter.examples/windivert.stun.txt
  5. 8
      init.d/windivert.filter.examples/windivert.wireguard.txt
  6. 7
      init.d/windivert.filter.examples/windivert_part.discord_media.txt
  7. 3
      init.d/windivert.filter.examples/windivert_part.stun.txt
  8. 3
      init.d/windivert.filter.examples/windivert_part.wireguard.txt
  9. 96
      nfq/nfqws.c
  10. 1
      nfq/params.c
  11. 1
      nfq/params.h

4
docs/changes.txt

@ -541,3 +541,7 @@ nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate
init.d: custom scripts 50-discord-media, 50-stun4all
init.d: windivert filters for discord media, stun, wireguard
readme: hardware problems description
v71.5
winws: --wf-raw-part

6
init.d/windivert.filter.examples/README.txt

@ -1,14 +1,14 @@
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
Задействуются через `winws --wf-raw=@filename`.
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
Дофильтрация производится силами winws.
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw=@windivert.discord_media+stun.txt --filter-l7=stun,discord --dpi-desync=fake`
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
These filters are invoked using `winws --wf-raw=@filename`.
These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
Filters are kernel mode and save great amount of CPU.
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.

29
init.d/windivert.filter.examples/windivert.discord_media+stun.txt

@ -1,29 +0,0 @@
!impostor and !loopback and
(outbound and
((ip and
udp.DstPort>=50000 and udp.DstPort<=50099 and
udp.PayloadLength=74 and
udp.Payload32[0]=0x00010046 and
udp.Payload32[2]=0 and
udp.Payload32[3]=0 and
udp.Payload32[4]=0 and
udp.Payload32[5]=0 and
udp.Payload32[6]=0 and
udp.Payload32[7]=0 and
udp.Payload32[8]=0 and
udp.Payload32[9]=0 and
udp.Payload32[10]=0 and
udp.Payload32[11]=0 and
udp.Payload32[12]=0 and
udp.Payload32[13]=0 and
udp.Payload32[14]=0 and
udp.Payload32[15]=0 and
udp.Payload32[16]=0 and
udp.Payload32[17]=0)
or
(udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40)) and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

8
init.d/windivert.filter.examples/windivert.stun.txt

@ -1,8 +0,0 @@
!impostor and !loopback and
(outbound and
udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40 and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

8
init.d/windivert.filter.examples/windivert.wireguard.txt

@ -1,8 +0,0 @@
!impostor and !loopback and
(outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01 and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

7
init.d/windivert.filter.examples/windivert.discord_media.txt → init.d/windivert.filter.examples/windivert_part.discord_media.txt

@ -1,5 +1,4 @@
!impostor and !loopback and
(outbound and
outbound and ip and
udp.DstPort>=50000 and udp.DstPort<=50099 and
udp.PayloadLength=74 and
udp.Payload32[0]=0x00010046 and
@ -18,6 +17,4 @@
udp.Payload32[14]=0 and
udp.Payload32[15]=0 and
udp.Payload32[16]=0 and
udp.Payload32[17]=0 and
(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)
)
udp.Payload32[17]=0

3
init.d/windivert.filter.examples/windivert_part.stun.txt

@ -0,0 +1,3 @@
outbound and
udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40

3
init.d/windivert.filter.examples/windivert_part.wireguard.txt

@ -0,0 +1,3 @@
outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01

96
nfq/nfqws.c

@ -1447,15 +1447,36 @@ static bool wf_make_filter(
unsigned int IfIdx,unsigned int SubIfIdx,
bool ipv4, bool ipv6,
const char *pf_tcp_src, const char *pf_tcp_dst,
const char *pf_udp_src, const char *pf_udp_dst)
const char *pf_udp_src, const char *pf_udp_dst,
const struct str_list_head *wf_raw_part,
bool bFilterOutLAN)
{
char pf_dst_buf[8192],iface[64];
struct str_list *wfpart;
int n;
const char *pf_dst;
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(&params.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(&params.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : "";
snprintf(iface,sizeof(iface)," ifIdx=%u and subIfIdx=%u and",IfIdx,SubIfIdx);
if (!*pf_tcp_src && !*pf_udp_src) return false;
snprintf(wf,len,"%s and%s%s\n(",
DIVERT_PROLOG,
IfIdx ? iface : "",
ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and"
);
n=0;
if (!LIST_EMPTY(wf_raw_part))
{
LIST_FOREACH(wfpart, wf_raw_part, next)
{
snprintf(wf+strlen(wf),len-strlen(wf),"%s(\n%s\n )", n ? "\n or\n " : "\n " ,wfpart->str);
n++;
}
}
if (*pf_tcp_src || *pf_udp_src)
{
if (*pf_tcp_src && *pf_udp_src)
{
snprintf(pf_dst_buf,sizeof(pf_dst_buf),"(%s or %s)",pf_tcp_dst,pf_udp_dst);
@ -1463,21 +1484,26 @@ static bool wf_make_filter(
}
else
pf_dst = *pf_tcp_dst ? pf_tcp_dst : pf_udp_dst;
snprintf(wf,len,
DIVERT_PROLOG " and%s%s\n ((outbound and %s%s%s)\n or\n (inbound and tcp%s%s%s%s%s%s%s))",
IfIdx ? iface : "",
ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and",
snprintf(wf+strlen(wf),len-strlen(wf), n++ ? "\n or\n " : "\n ");
snprintf(wf+strlen(wf),len-strlen(wf),
"(\n (outbound and %s%s)\n or\n (inbound and tcp%s%s%s%s%s)\n )",
f_tcp_not_empty,
pf_dst,
ipv4 ? ipv6 ? " and " DIVERT_NO_LOCALNETS_DST : " and " DIVERT_NO_LOCALNETSv4_DST : " and " DIVERT_NO_LOCALNETSv6_DST,
*pf_tcp_src ? "" : " and false",
*f_tcpin ? " and " : "",
*f_tcpin ? f_tcpin : "",
*pf_tcp_src ? " and " : "",
*pf_tcp_src ? pf_tcp_src : "",
*pf_tcp_src ? " and " : "",
*pf_tcp_src ? ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC : ""
);
*pf_tcp_src ? pf_tcp_src : "");
}
strncat(wf,"\n)",len-strlen(wf)-1);
if (bFilterOutLAN)
snprintf(wf+strlen(wf),len-strlen(wf),"\nand\n(\n outbound and %s\n or\n inbound and %s\n)\n",
ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_DST : DIVERT_NO_LOCALNETSv4_DST : DIVERT_NO_LOCALNETSv6_DST,
ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC);
return true;
}
@ -1531,7 +1557,9 @@ static void exithelp(void)
" --wf-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --wf-tcp=[~]port1[-port2]\t\t\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-udp=[~]port1[-port2]\t\t\t; UDP port filter. ~ means negation. multiple comma separated values allowed.\n"
" --wf-raw=<filter>|@<filename>\t\t\t; raw windivert filter string or filename\n"
" --wf-raw-part=<filter>|@<filename>\t\t; partial raw windivert filter string or filename\n"
" --wf-filter-lan=0|1\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
" --wf-raw=<filter>|@<filename>\t\t\t; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part\n"
" --wf-save=<filename>\t\t\t\t; save windivert filter string to a file and exit\n"
"\nLOGICAL NETWORK FILTER:\n"
" --ssid-filter=ssid1[,ssid2,ssid3,...]\t\t; enable winws only if any of specified wifi SSIDs connected\n"
@ -1701,7 +1729,7 @@ void check_dp(const struct desync_profile *dp)
DLOG_CONDUP("WARNING !!! fakes or dups will be sent on every processed packet\n");
DLOG_CONDUP("WARNING !!! make sure it's really what you want\n");
#ifdef __CYGWIN__
DLOG_CONDUP("WARNING !!! in most cases this is acceptable only with custom payload based windivert filter (--wf-raw)\n");
DLOG_CONDUP("WARNING !!! in most cases this is acceptable only with custom payload based windivert filter (--wf-raw, --wf-raw-part)\n");
#endif
#endif
}
@ -1841,6 +1869,8 @@ enum opt_indices {
IDX_WF_TCP,
IDX_WF_UDP,
IDX_WF_RAW,
IDX_WF_RAW_PART,
IDX_WF_FILTER_LAN,
IDX_WF_SAVE,
IDX_SSID_FILTER,
IDX_NLM_FILTER,
@ -1967,6 +1997,8 @@ static const struct option long_options[] = {
[IDX_WF_TCP] = {"wf-tcp", required_argument, 0, 0},
[IDX_WF_UDP] = {"wf-udp", required_argument, 0, 0},
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
[IDX_WF_RAW_PART] = {"wf-raw-part", required_argument, 0, 0},
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
@ -1994,9 +2026,9 @@ int main(int argc, char **argv)
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
#ifdef __CYGWIN__
char windivert_filter[16384], wf_pf_tcp_src[4096], wf_pf_tcp_dst[4096], wf_pf_udp_src[4096], wf_pf_udp_dst[4096], wf_save_file[256];
bool wf_ipv4=true, wf_ipv6=true;
bool wf_ipv4=true, wf_ipv6=true, wf_filter_lan=true;
unsigned int IfIdx=0, SubIfIdx=0;
unsigned int hash_wf_tcp=0,hash_wf_udp=0,hash_wf_raw=0,hash_ssid_filter=0,hash_nlm_filter=0;
unsigned int hash_wf_tcp=0,hash_wf_udp=0,hash_wf_raw=0,hash_wf_raw_part=0,hash_ssid_filter=0,hash_nlm_filter=0;
*windivert_filter = *wf_pf_tcp_src = *wf_pf_tcp_dst = *wf_pf_udp_src = *wf_pf_udp_dst = *wf_save_file = 0;
#endif
@ -2037,6 +2069,7 @@ int main(int argc, char **argv)
#ifdef __CYGWIN__
LIST_INIT(&params.ssid_filter);
LIST_INIT(&params.nlm_filter);
LIST_INIT(&params.wf_raw_part);
#else
if (can_drop_root())
{
@ -2953,6 +2986,31 @@ int main(int argc, char **argv)
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
}
break;
case IDX_WF_RAW_PART:
hash_wf_raw_part^=hash_jen(optarg,strlen(optarg));
{
char wfpart[sizeof(windivert_filter)];
if (optarg[0]=='@')
{
size_t sz = sizeof(wfpart)-1;
load_file_or_exit(optarg+1,wfpart,&sz);
wfpart[sz] = 0;
}
else
{
strncpy(wfpart, optarg, sizeof(wfpart));
wfpart[sizeof(wfpart) - 1] = '\0';
}
if (!strlist_add(&params.wf_raw_part,wfpart))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
}
break;
case IDX_WF_FILTER_LAN:
wf_filter_lan=!!atoi(optarg);
break;
case IDX_WF_SAVE:
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
@ -3093,12 +3151,12 @@ int main(int argc, char **argv)
#ifdef __CYGWIN__
if (!*windivert_filter)
{
if (!*wf_pf_tcp_src && !*wf_pf_udp_src)
if (!*wf_pf_tcp_src && !*wf_pf_udp_src && LIST_EMPTY(&params.wf_raw_part))
{
DLOG_ERR("windivert filter : must specify port filter\n");
DLOG_ERR("windivert filter : must specify port or/and partial raw filter\n");
exit_clean(1);
}
if (!wf_make_filter(windivert_filter, sizeof(windivert_filter), IfIdx, SubIfIdx, wf_ipv4, wf_ipv6, wf_pf_tcp_src, wf_pf_tcp_dst, wf_pf_udp_src, wf_pf_udp_dst))
if (!wf_make_filter(windivert_filter, sizeof(windivert_filter), IfIdx, SubIfIdx, wf_ipv4, wf_ipv6, wf_pf_tcp_src, wf_pf_tcp_dst, wf_pf_udp_src, wf_pf_udp_dst, &params.wf_raw_part, wf_filter_lan))
{
DLOG_ERR("windivert filter : could not make filter\n");
exit_clean(1);
@ -3121,7 +3179,7 @@ int main(int argc, char **argv)
HANDLE hMutexArg;
{
char mutex_name[128];
snprintf(mutex_name,sizeof(mutex_name),"Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u",hash_wf_tcp,hash_wf_udp,hash_wf_raw,hash_ssid_filter,hash_nlm_filter,IfIdx,SubIfIdx,wf_ipv4,wf_ipv6);
snprintf(mutex_name,sizeof(mutex_name),"Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u",hash_wf_tcp,hash_wf_udp,hash_wf_raw,hash_wf_raw_part,hash_ssid_filter,hash_nlm_filter,IfIdx,SubIfIdx,wf_ipv4,wf_ipv6);
hMutexArg = CreateMutexA(NULL,TRUE,mutex_name);
if (hMutexArg && GetLastError()==ERROR_ALREADY_EXISTS)

1
nfq/params.c

@ -371,6 +371,7 @@ void cleanup_params(struct params_s *params)
#ifdef __CYGWIN__
strlist_destroy(&params->ssid_filter);
strlist_destroy(&params->nlm_filter);
strlist_destroy(&params->wf_raw_part);
#else
free(params->user); params->user=NULL;
#endif

1
nfq/params.h

@ -200,6 +200,7 @@ struct params_s
#ifdef __CYGWIN__
struct str_list_head ssid_filter,nlm_filter;
struct str_list_head wf_raw_part;
#else
bool droproot;
char *user;

Loading…
Cancel
Save