0
0
mirror of https://github.com/bol-van/zapret.git synced 2025-06-29 18:21:16 +00:00

nfqws: --filter-ssid (linux only)

This commit is contained in:
bol-van 2025-06-04 08:57:57 +03:00
parent 30a947b42b
commit 58d306b552
12 changed files with 399 additions and 43 deletions

View File

@ -508,5 +508,6 @@ v71.1
nfqws,tpws: much faster ipset implementation. move from hash to avl tree
nfqws,tpws: check list files accessibility with dropped privs in --dry-run mode
nfqws,tpws: --debug=android for NDK builds
nfqws: --filter-ssid (linux-only)
install_easy: stop if running embedded release on traditional linux system (some files missing)
install_bin: add "read elf" arch detection method

View File

@ -1,6 +1,6 @@
debian,ubuntu :
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libsystemd-dev
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev
make -C /opt/zapret systemd
FreeBSD :

View File

@ -4,7 +4,7 @@ CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LDFLAGS_ANDROID = -llog
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32

View File

@ -29,6 +29,13 @@
#endif
#ifdef __linux__
#include <linux/nl80211.h>
#include <linux/genetlink.h>
#include <libmnl/libmnl.h>
#include <net/if.h>
#endif
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
{
return htonl(ntohl(netorder_value)+cpuorder_increment);
@ -1832,6 +1839,239 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
}
#if defined(HAS_FILTER_SSID) && defined(__linux__)
// linux-specific wlan retrieval implementation
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct genlmsghdr *genl;
ssize_t rd;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = type;
nlh->nlmsg_flags = flags;
genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
genl->cmd = cmd;
genl->version = version;
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
{
DLOG_PERROR("mnl_socket_sendto");
return false;
}
while ((rd=mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0)
{
switch(mnl_cb_run(buf, rd, 0, 0, cb_data, data))
{
case MNL_CB_STOP:
return true;
case MNL_CB_OK:
break;
default:
return false;
}
}
return false;
}
static void wlan_id_prepare(struct nlmsghdr *nlh)
{
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
}
static int wlan_id_attr_cb(const struct nlattr *attr, void *data)
{
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
{
DLOG_PERROR("mnl_attr_type_valid");
return MNL_CB_ERROR;
}
switch(mnl_attr_get_type(attr))
{
case CTRL_ATTR_FAMILY_ID:
if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
{
DLOG_PERROR("mnl_attr_validate(family_id)");
return MNL_CB_ERROR;
}
*((uint16_t*)data) = mnl_attr_get_u16(attr);
break;
}
return MNL_CB_OK;
}
static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
{
return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_id_attr_cb, data);
}
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
{
uint16_t id;
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0;
}
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
{
struct wlan_interface *wlan = (struct wlan_interface *)data;
switch(mnl_attr_get_type(attr))
{
case NL80211_ATTR_IFINDEX:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
{
DLOG_PERROR("mnl_attr_validate(ifindex)");
return MNL_CB_ERROR;
}
wlan->ifindex = mnl_attr_get_u32(attr);
break;
case NL80211_ATTR_SSID:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
{
DLOG_PERROR("mnl_attr_validate(ssid)");
return MNL_CB_ERROR;
}
snprintf(wlan->ssid,sizeof(wlan->ssid),"%s",mnl_attr_get_str(attr));
break;
case NL80211_ATTR_IFNAME:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
{
DLOG_PERROR("mnl_attr_validate(ifname)");
return MNL_CB_ERROR;
}
snprintf(wlan->ifname,sizeof(wlan->ifname),"%s",mnl_attr_get_str(attr));
break;
}
return MNL_CB_OK;
}
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
{
int ret;
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count);
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
wc->count++;
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w);
}
static bool wlan_init80211(struct mnl_socket** nl)
{
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
{
DLOG_PERROR("mnl_socket_open");
return false;
}
if (mnl_socket_bind(*nl, 0, MNL_SOCKET_AUTOPID))
{
DLOG_PERROR("mnl_socket_bind");
return false;
}
return true;
}
static void wlan_deinit80211(struct mnl_socket** nl)
{
if (*nl)
{
mnl_socket_close(*nl);
*nl = NULL;
}
}
static time_t wlan_info_last = 0;
static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
bool bres = true;
time_t now = time(NULL);
// do not purge too often to save resources
if (wlan_info_last != now)
{
bres = wlan_info(nl,wlan_family_id,w);
wlan_info_last = now;
}
return bres;
}
static struct mnl_socket* nl_wifi = NULL;
static uint16_t id_nl80211;
struct wlan_interface_collection wlans = { .count = 0 };
void wlan_info_deinit(void)
{
wlan_deinit80211(&nl_wifi);
}
bool wlan_info_init(void)
{
wlan_info_deinit();
if (!wlan_init80211(&nl_wifi)) return false;
if (!(id_nl80211 = wlan_get_family_id(nl_wifi)))
{
wlan_info_deinit();
return false;
}
return true;
}
bool wlan_info_get(void)
{
return wlan_info(nl_wifi, id_nl80211, &wlans);
}
bool wlan_info_get_rate_limited(void)
{
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);
}
#endif
#ifdef HAS_FILTER_SSID
const char *wlan_ifname2ssid(const struct wlan_interface_collection *w, const char *ifname)
{
int i;
if (ifname)
{
for (i=0;i<w->count;i++)
if (!strcmp(w->wlan[i].ifname,ifname))
return w->wlan[i].ssid;
}
return NULL;
}
const char *wlan_ifidx2ssid(const struct wlan_interface_collection *w,int ifidx)
{
int i;
for (i=0;i<w->count;i++)
if (w->wlan[i].ifindex == ifidx)
return w->wlan[i].ssid;
return NULL;
}
const char *wlan_ssid_search_ifname(const char *ifname)
{
return wlan_ifname2ssid(&wlans,ifname);
}
const char *wlan_ssid_search_ifidx(int ifidx)
{
return wlan_ifidx2ssid(&wlans,ifidx);
}
#endif
uint8_t hop_count_guess(uint8_t ttl)
{
// 18.65.168.125 ( cloudfront ) 255

View File

@ -1,5 +1,6 @@
#pragma once
#include "nfqws.h"
#include "checksum.h"
#include "packet_queue.h"
#include "pools.h"
@ -272,3 +273,29 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
void dbgprint_socket_buffers(int fd);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);
#ifdef HAS_FILTER_SSID
struct wlan_interface
{
int ifindex;
char ifname[IFNAMSIZ], ssid[33];
};
#define WLAN_INTERFACE_MAX 16
struct wlan_interface_collection
{
int count;
struct wlan_interface wlan[WLAN_INTERFACE_MAX];
};
extern struct wlan_interface_collection wlans;
void wlan_info_deinit(void);
bool wlan_info_init(void);
bool wlan_info_get(void);
bool wlan_info_get_rate_limited(void);
const char *wlan_ssid_search_ifname(const char *ifname);
const char *wlan_ssid_search_ifidx(int ifidx);
#endif

View File

@ -223,7 +223,7 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
static bool dp_match(
struct desync_profile *dp,
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto,
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto, const char *ssid,
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
{
bool bHostlistsEmpty;
@ -241,6 +241,11 @@ static bool dp_match(
if (dp->filter_l7 && !l7_proto_match(l7proto, dp->filter_l7))
// L7 filter does not match
return false;
#ifdef HAS_FILTER_SSID
if (!LIST_EMPTY(&dp->filter_ssid) && !strlist_search(&dp->filter_ssid,ssid))
return false;
#endif
bHostlistsEmpty = PROFILE_HOSTLISTS_EMPTY(dp);
if (!dp->hostlist_auto && !hostname && !bHostlistsEmpty)
// avoid cpu consuming ipset check. profile cannot win if regular hostlists are present without auto hostlist and hostname is unknown.
@ -271,7 +276,7 @@ static bool dp_match(
}
static struct desync_profile *dp_find(
struct desync_profile_list_head *head,
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto,
uint8_t l3proto, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto, const char *ssid,
bool *bCheckDone, bool *bCheckResult, bool *bExcluded)
{
struct desync_profile_list *dpl;
@ -279,12 +284,12 @@ static struct desync_profile *dp_find(
{
char ip_port[48];
ntop46_port(dest, ip_port,sizeof(ip_port));
DLOG("desync profile search for %s target=%s l7proto=%s hostname='%s'\n", proto_name(l3proto), ip_port, l7proto_str(l7proto), hostname ? hostname : "");
DLOG("desync profile search for %s target=%s l7proto=%s ssid='%s' hostname='%s'\n", proto_name(l3proto), ip_port, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
}
if (bCheckDone) *bCheckDone = false;
LIST_FOREACH(dpl, head, next)
{
if (dp_match(&dpl->dp,l3proto,dest,hostname,l7proto,bCheckDone,bCheckResult,bExcluded))
if (dp_match(&dpl->dp,l3proto,dest,hostname,l7proto,ssid,bCheckDone,bCheckResult,bExcluded))
{
DLOG("desync profile %d matches\n",dpl->dp.n);
return &dpl->dp;
@ -1107,6 +1112,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
bool bSack,DF;
uint16_t nmss;
char host[256];
const char *ifname = NULL, *ssid = NULL;
uint32_t desync_fwmark = fwmark | params.desync_fwmark;
extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst);
@ -1122,6 +1128,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, &ctrack_replay, &bReverse) || bReverse)
return verdict;
ifname = bReverse ? ifin : ifout;
#ifdef HAS_FILTER_SSID
ssid = wlan_ssid_search_ifname(ifname);
if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid);
#endif
dp = ctrack_replay->dp;
if (dp)
DLOG("using cached desync profile %d\n",dp->n);
@ -1133,7 +1144,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!(ctrack_replay->hostname = strdup(host)))
DLOG_ERR("strdup(host): out of memory\n");
}
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, NULL, NULL, NULL);
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
ctrack_replay->dp_search_complete = true;
}
if (!dp)
@ -1155,6 +1166,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
ctrack_replay = ctrack;
}
}
ifname = bReverse ? ifin : ifout;
#ifdef HAS_FILTER_SSID
ssid = wlan_ssid_search_ifname(ifname);
if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid);
#endif
if (dp)
DLOG("using cached desync profile %d\n",dp->n);
else if (!ctrack || !ctrack->dp_search_complete)
@ -1170,7 +1186,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG_ERR("strdup(host): out of memory\n");
}
}
dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, NULL, NULL, NULL);
dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
if (ctrack)
{
ctrack->dp = dp;
@ -1574,7 +1590,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->l7proto : l7proto,
ctrack_replay ? ctrack_replay->l7proto : l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
if (ctrack_replay)
{
@ -2368,6 +2384,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
bool DF;
char host[256];
t_l7proto l7proto = UNKNOWN;
const char *ifname = NULL, *ssid = NULL;
extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst);
@ -2379,6 +2396,12 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis->ip, dis->ip6, NULL, dis->udp, &ctrack_replay, &bReverse) || bReverse)
return verdict;
ifname = bReverse ? ifin : ifout;
#ifdef HAS_FILTER_SSID
ssid = wlan_ssid_search_ifname(ifname);
if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid);
#endif
dp = ctrack_replay->dp;
if (dp)
DLOG("using cached desync profile %d\n",dp->n);
@ -2390,7 +2413,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (!(ctrack_replay->hostname = strdup(host)))
DLOG_ERR("strdup(host): out of memory\n");
}
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, NULL, NULL, NULL);
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
ctrack_replay->dp_search_complete = true;
}
if (!dp)
@ -2415,6 +2438,11 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
ctrack_replay = ctrack;
}
}
ifname = bReverse ? ifin : ifout;
#ifdef HAS_FILTER_SSID
ssid = wlan_ssid_search_ifname(ifname);
if (ssid) DLOG("found ssid for %s : %s\n",ifname,ssid);
#endif
if (dp)
DLOG("using cached desync profile %d\n",dp->n);
else if (!ctrack || !ctrack->dp_search_complete)
@ -2430,7 +2458,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
DLOG_ERR("strdup(host): out of memory\n");
}
}
dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, NULL, NULL, NULL);
dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, ssid, NULL, NULL, NULL);
if (ctrack)
{
ctrack->dp = dp;
@ -2703,7 +2731,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->l7proto : l7proto,
ctrack_replay ? ctrack_replay->l7proto : l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
if (ctrack_replay)
{

View File

@ -306,6 +306,12 @@ static int nfq_main(void)
if (!nfq_init(&h,&qh))
goto err;
if (params.filter_ssid_present && !wlan_info_init())
{
DLOG_ERR("cannot initialize wlan info capture\n");
goto err;
}
if (params.daemon) daemonize();
sec_harden();
@ -330,6 +336,9 @@ static int nfq_main(void)
while ((rd = recv(fd, buf, sizeof(buf), 0)) >= 0)
{
ReloadCheck();
if (params.filter_ssid_present)
if (!wlan_info_get_rate_limited())
DLOG_ERR("cannot get wlan info\n");
if (rd)
{
int r = nfq_handle_packet(h, (char *)buf, (int)rd);
@ -346,9 +355,12 @@ static int nfq_main(void)
} while(e==ENOBUFS);
nfq_deinit(&h,&qh);
wlan_info_deinit();
return 0;
err:
if (Fpid) fclose(Fpid);
nfq_deinit(&h,&qh);
wlan_info_deinit();
return 1;
}
@ -1127,6 +1139,20 @@ static bool parse_fooling(char *opt, unsigned int *fooling_mode)
return true;
}
static bool parse_strlist(char *opt, struct str_list_head *list)
{
char *e,*p = optarg;
while (p)
{
e = strchr(p,',');
if (e) *e++=0;
if (*p && !strlist_add(list, p))
return false;
p = e;
}
return true;
}
static void split_compat(struct desync_profile *dp)
{
if (!dp->split_count)
@ -1532,6 +1558,9 @@ static void exithelp(void)
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
" --filter-l7=[http|tls|quic|wireguard|dht|discord|stun|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
#ifdef HAS_FILTER_SSID
" --filter-ssid=ssid1[,ssid2,ssid3,...]\t\t; per profile wifi SSID filter\n"
#endif
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
@ -1805,6 +1834,9 @@ enum opt_indices {
IDX_FILTER_TCP,
IDX_FILTER_UDP,
IDX_FILTER_L7,
#ifdef HAS_FILTER_SSID
IDX_FILTER_SSID,
#endif
IDX_IPSET,
IDX_IPSET_IP,
IDX_IPSET_EXCLUDE,
@ -1926,6 +1958,9 @@ static const struct option long_options[] = {
[IDX_FILTER_TCP] = {"filter-tcp", required_argument, 0, 0},
[IDX_FILTER_UDP] = {"filter-udp", required_argument, 0, 0},
[IDX_FILTER_L7] = {"filter-l7", required_argument, 0, 0},
#ifdef HAS_FILTER_SSID
[IDX_FILTER_SSID] = {"filter-ssid", required_argument, 0, 0},
#endif
[IDX_IPSET] = {"ipset", required_argument, 0, 0},
[IDX_IPSET_IP] = {"ipset-ip", required_argument, 0, 0},
[IDX_IPSET_EXCLUDE] = {"ipset-exclude", required_argument, 0, 0},
@ -2810,6 +2845,16 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
#ifdef HAS_FILTER_SSID
case IDX_FILTER_SSID:
if (!parse_strlist(optarg,&dp->filter_ssid))
{
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
params.filter_ssid_present = true;
break;
#endif
case IDX_IPSET:
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg))
@ -2914,38 +2959,18 @@ int main(int argc, char **argv)
break;
case IDX_SSID_FILTER:
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
if (!parse_strlist(optarg,&params.ssid_filter))
{
char *e,*p = optarg;
while (p)
{
e = strchr(p,',');
if (e) *e++=0;
if (*p && !strlist_add(&params.ssid_filter, p))
{
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
p = e;
}
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
break;
case IDX_NLM_FILTER:
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
if (!parse_strlist(optarg,&params.nlm_filter))
{
char *e,*p = optarg;
while (p)
{
e = strchr(p,',');
if (e) *e++=0;
if (*p && !strlist_add(&params.nlm_filter, p))
{
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
p = e;
}
DLOG_ERR("strlist_add failed\n");
exit_clean(1);
}
break;
case IDX_NLM_LIST:

View File

@ -2,6 +2,10 @@
#include <stdbool.h>
#ifdef __linux__
#define HAS_FILTER_SSID 1
#endif
#ifdef __CYGWIN__
extern bool bQuit;
#endif

View File

@ -42,6 +42,7 @@ int DLOG_FILENAME(const char *filename, const char *format, va_list args)
r=-1;
return r;
}
typedef void (*f_log_function)(int priority, const char *line);
static char log_buf[1024];
@ -301,6 +302,9 @@ static void dp_clear_dynamic(struct desync_profile *dp)
ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&dp->pf_udp);
#ifdef HAS_FILTER_SSID
strlist_destroy(&dp->filter_ssid);
#endif
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
struct blob_collection_head **fake,*fakes[] = {&dp->fake_http, &dp->fake_tls, &dp->fake_unknown, &dp->fake_unknown_udp, &dp->fake_quic, &dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, NULL};
for(fake=fakes;*fake;fake++) blob_collection_destroy(*fake);

View File

@ -1,5 +1,6 @@
#pragma once
#include "nfqws.h"
#include "pools.h"
#include "conntrack.h"
#include "desync.h"
@ -135,6 +136,13 @@ struct desync_profile
struct port_filters_head pf_tcp,pf_udp;
uint32_t filter_l7; // L7_PROTO_* bits
#ifdef HAS_FILTER_SSID
// per profile ssid filter
// annot use global filter because it's not possible to bind multiple instances to a single queue
// it's possible to run multiple winws instances on the same windivert filter, but it's not the case for linux
struct str_list_head filter_ssid;
#endif
// list of pointers to ipsets
struct ipset_collection_head ips_collection, ips_collection_exclude;
@ -209,7 +217,12 @@ struct params_s
t_conntrack conntrack;
bool ctrack_disable;
bool autottl_present,cache_hostname;
bool autottl_present;
#ifdef HAS_FILTER_SSID
bool filter_ssid_present;
#endif
bool cache_hostname;
unsigned int ipcache_lifetime;
ip_cache ipcache;
};

View File

@ -159,6 +159,19 @@ void strlist_destroy(struct str_list_head *head)
strlist_entry_destroy(entry);
}
}
bool strlist_search(const struct str_list_head *head, const char *str)
{
struct str_list *entry;
if (str)
{
LIST_FOREACH(entry, head, next)
{
if (!strcmp(entry->str, str))
return true;
}
}
return false;
}

View File

@ -34,6 +34,11 @@ struct str_list {
};
LIST_HEAD(str_list_head, str_list);
bool strlist_add(struct str_list_head *head, const char *filename);
void strlist_destroy(struct str_list_head *head);
bool strlist_search(const struct str_list_head *head, const char *str);
typedef struct hostfail_pool {
char *str; /* key */
int counter; /* value */
@ -49,10 +54,6 @@ void HostFailPoolPurge(hostfail_pool **pp);
void HostFailPoolPurgeRateLimited(hostfail_pool **pp);
void HostFailPoolDump(hostfail_pool *p);
bool strlist_add(struct str_list_head *head, const char *filename);
void strlist_destroy(struct str_list_head *head);
struct hostlist_file {
char *filename;