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

winws2: use windivert bulk mode

This commit is contained in:
bol-van
2026-01-31 16:54:17 +03:00
parent b157613b1a
commit 7d9f5a4b83
4 changed files with 75 additions and 44 deletions

View File

@@ -211,3 +211,5 @@ v0.8.1
* zapret-obfs: ippxor, udp2icmp, synhide
* nfqws2: LUA_COMPAT_VER=5
* winws2: --wf-raw-filter
* nfqws2: conntrack_feed
* winws2: use windivert bulk mode

View File

@@ -1491,7 +1491,7 @@ bool windivert_init(const char *filter)
return false;
}
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa)
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
{
UINT recv_len;
DWORD err;
@@ -1510,8 +1510,10 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
}
usleep(0);
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, NULL, &ovl))
*wa_count *= sizeof(WINDIVERT_ADDRESS);
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, wa_count, &ovl))
{
*wa_count /= sizeof(WINDIVERT_ADDRESS);
*len = recv_len;
return true;
}
@@ -1540,6 +1542,7 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
}
if (!GetOverlappedResult(hFilter,&ovl,&rd,TRUE))
continue;
*wa_count /= sizeof(WINDIVERT_ADDRESS);
*len = rd;
return true;
case ERROR_INSUFFICIENT_BUFFER:
@@ -1555,9 +1558,9 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
}
return false;
}
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa)
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
{
return windivert_recv_filter(w_filter,packet,len,wa);
return windivert_recv_filter(w_filter,packet,len,wa,wa_count);
}
static bool windivert_send_filter(HANDLE hFilter, const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa)

View File

@@ -135,7 +135,7 @@ bool logical_net_filter_present(void);
bool logical_net_filter_match(void);
bool nlm_list(bool bAll);
bool windivert_init(const char *filter);
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa);
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count);
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
#else
#define ensure_dir_access(dir) ensure_file_access(dir)

View File

@@ -658,17 +658,22 @@ exiterr:
#elif defined (__CYGWIN__)
#define WINDIVERT_BULK_MAX 128
// do not make it less than 65536 - loopback packets can be up to 64K
#define WINDIVERT_PACKET_BUF_SIZE 192000
static int win_main()
{
size_t len, modlen;
size_t len, packet_len, left, modlen;
unsigned int id;
uint8_t verdict;
bool bOutbound;
uint32_t mark;
WINDIVERT_ADDRESS wa;
char ifname[IFNAMSIZ];
int res=0;
uint8_t packet[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
WINDIVERT_ADDRESS wa[WINDIVERT_BULK_MAX];
uint8_t *packets = NULL, *packet, *mod=NULL;
unsigned int n,wa_count;
// windows emulated fork logic does not cover objects outside of cygwin world. have to daemonize before inits
if (params.daemon) daemonize();
@@ -685,7 +690,10 @@ static int win_main()
res=w_win32_error; goto ex;
}
catch_signals();
if (!(packets = malloc(WINDIVERT_PACKET_BUF_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE)))
{
res=ERROR_NOT_ENOUGH_MEMORY; goto ex;
}
for (;;)
{
@@ -730,10 +738,11 @@ static int win_main()
goto ex;
}
for (id = 0;; id++)
for (id = 0;;)
{
len = sizeof(packet);
if (!windivert_recv(packet, &len, &wa))
len = WINDIVERT_PACKET_BUF_SIZE;
wa_count = WINDIVERT_BULK_MAX;
if (!windivert_recv(packets, &len, wa, &wa_count))
{
if (errno == ENOBUFS)
{
@@ -758,39 +767,60 @@ static int win_main()
ReloadCheck();
lua_do_gc();
*ifname = 0;
snprintf(ifname, sizeof(ifname), "%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx);
DLOG("\npacket: id=%u len=%zu %s IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%u.%u\n", id, len, wa.Outbound ? "outbound" : "inbound", wa.IPv6, wa.IPChecksum, wa.TCPChecksum, wa.UDPChecksum, wa.Network.IfIdx, wa.Network.SubIfIdx);
if (wa.Impostor)
for (n=0, packet=packets, left = len ; n<wa_count ; n++, packet+=packet_len, left-=packet_len, id++)
{
DLOG("windivert: passing impostor packet\n");
verdict = VERDICT_PASS;
}
else
{
mark = 0;
// pseudo interface id IfIdx.SubIfIdx
modlen = sizeof(packet);
verdict = processPacketData(&mark, wa.Outbound ? "" : ifname, wa.Outbound ? ifname : "", packet, len, packet, &modlen);
}
switch (verdict & VERDICT_MASK)
{
case VERDICT_PASS:
DLOG("packet: id=%u reinject unmodified\n", id);
if (!windivert_send(packet, len, &wa))
DLOG_ERR("windivert: reinject of packet id=%u failed\n", id);
break;
case VERDICT_MODIFY:
DLOG("packet: id=%u reinject modified len %zu => %zu\n", id, len, modlen);
if (!windivert_send(packet, modlen, &wa))
DLOG_ERR("windivert: reinject of packet id=%u failed\n", id);
break;
default:
DLOG("packet: id=%u drop\n", id);
if (wa[n].IPv6)
{
if (left<sizeof(WINDIVERT_IPV6HDR) || left<(packet_len = sizeof(WINDIVERT_IPV6HDR) + ntohs(((WINDIVERT_IPV6HDR*)packet)->Length)))
{
DLOG_ERR("invalid ipv6 packet\n");
break;
}
}
else
{
if (left<sizeof(WINDIVERT_IPHDR) || left<(packet_len = ntohs(((WINDIVERT_IPHDR*)packet)->Length)))
{
DLOG_ERR("invalid ipv4 packet\n");
break;
}
}
*ifname = 0;
snprintf(ifname, sizeof(ifname), "%u.%u", wa[n].Network.IfIdx, wa[n].Network.SubIfIdx);
DLOG("\npacket: id=%u len=%zu %s IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%u.%u\n", id, packet_len, wa[n].Outbound ? "outbound" : "inbound", wa[n].IPv6, wa[n].IPChecksum, wa[n].TCPChecksum, wa[n].UDPChecksum, wa[n].Network.IfIdx, wa[n].Network.SubIfIdx);
if (wa[n].Impostor)
{
DLOG("windivert: passing impostor packet\n");
verdict = VERDICT_PASS;
}
else
{
mark = 0;
modlen = RECONSTRUCT_MAX_SIZE;
verdict = processPacketData(&mark, wa[n].Outbound ? "" : ifname, wa[n].Outbound ? ifname : "", packet, packet_len, mod, &modlen);
}
switch (verdict & VERDICT_MASK)
{
case VERDICT_PASS:
DLOG("packet: id=%u reinject unmodified\n", id);
if (!windivert_send(packet, packet_len, wa+n))
DLOG_ERR("windivert: reinject of packet id=%u failed\n", id);
break;
case VERDICT_MODIFY:
DLOG("packet: id=%u reinject modified len %zu => %zu\n", id, packet_len, modlen);
if (!windivert_send(mod, modlen, wa+n))
DLOG_ERR("windivert: reinject of packet id=%u failed\n", id);
break;
default:
DLOG("packet: id=%u drop\n", id);
}
}
}
}
ex:
free(mod);
free(packets);
win_dark_deinit();
lua_shutdown();
rawsend_cleanup();
@@ -1423,26 +1453,22 @@ dont_add:
}
#define DIVERT_NO_LOCALNETSv4_DST "(" \
"(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))"
#define DIVERT_NO_LOCALNETSv4_SRC "(" \
"(ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and " \
"(ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and " \
"(ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and " \
"(ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and " \
"(ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255))"
#define DIVERT_NO_LOCALNETSv6_DST "(" \
"(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))"
#define DIVERT_NO_LOCALNETSv6_SRC "(" \
"(ipv6.SrcAddr > ::1) and " \
"(ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and " \
"(ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and " \
"(ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and " \