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:
parent
30a947b42b
commit
58d306b552
@ -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
|
||||
|
@ -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 :
|
||||
|
@ -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
|
||||
|
240
nfq/darkmagic.c
240
nfq/darkmagic.c
@ -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
|
||||
|
@ -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
|
||||
|
48
nfq/desync.c
48
nfq/desync.c
@ -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(¶ms.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(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, NULL, NULL, NULL);
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.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(¶ms.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, NULL, NULL, NULL);
|
||||
dp = dp_find(¶ms.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(¶ms.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(¶ms.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(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->l7proto, NULL, NULL, NULL);
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.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(¶ms.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, hostname, ctrack ? ctrack->l7proto : UNKNOWN, NULL, NULL, NULL);
|
||||
dp = dp_find(¶ms.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(¶ms.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)
|
||||
{
|
||||
|
77
nfq/nfqws.c
77
nfq/nfqws.c
@ -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,¶ms.ssid_filter))
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
while (p)
|
||||
{
|
||||
e = strchr(p,',');
|
||||
if (e) *e++=0;
|
||||
if (*p && !strlist_add(¶ms.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,¶ms.nlm_filter))
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
while (p)
|
||||
{
|
||||
e = strchr(p,',');
|
||||
if (e) *e++=0;
|
||||
if (*p && !strlist_add(¶ms.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:
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#define HAS_FILTER_SSID 1
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
extern bool bQuit;
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
15
nfq/params.h
15
nfq/params.h
@ -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;
|
||||
};
|
||||
|
13
nfq/pools.c
13
nfq/pools.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user