Blocking of DoH, DoT, and DoQ using the DPI filter is unsuccessful

I thought that enabling the DPI filter for these blocked apps/protocols would disable clients from using these DNS protocols.

But setting the OS, Firefox, or Chrome to use secure DNS allows one to bypass the Threat Shield DNS or DHCP set DNS server.

Firefox for example:

Afterward, no blocking occurs. The DPI doesn’t seem to block DoH, DoT, or DoQ, and the clients are not restricted by the in-house DNS.

Is this the expected behavior?

How should I debug this Issue? Thank you in advance.
I’m using a clean install with DPI filter enabled, nothing else.

Does it help to add Cloudflare and NextDNS blocking?

There is no Cloudfare DNS (neither any other) in the DPI filter without a subscription (the community plan).

I will do more extensive tests tomorrow. But this should work out of box…

1 Like

Try to block quic protocol. Add firewall rule reject 443 udp from LAN to wan

1 Like

I’m not able to get the DPI filter working (without a subscription). Did a clean install, afterwards a have set the DPI filter, Create rule (blocked Facebook App / Social media) and did expect that Facebook in the browser is blocked? But nothing really happened. How could be the DPI filter tested?

config main 'config'
        option log_blocked '0'
        option enabled '1'
        option firewall_exemption '0'
        list popular_filters 'netify.facebook'
        list popular_filters 'netify.amazon-prime'
        list popular_filters 'netify.whatsapp'
        list popular_filters 'netify.instagram'
        list popular_filters 'netify.netflix'
        list popular_filters 'netify.telegram'
        list popular_filters 'netify.tiktok'
        list popular_filters 'netify.youtube'
        list popular_filters 'netify.facebook-messenger'
        list popular_filters 'netify.twitter'
        list popular_filters 'netify.vimeo'
        list popular_filters 'netify.snapchat'
        list popular_filters 'netify.pinterest'
        list popular_filters 'netify.nordvpn'
        list popular_filters 'DoT'
        list popular_filters 'netify.twitch'
        list popular_filters 'netify.teamviewer'
        list popular_filters 'DoH'

config rule 'ns_421ea29c'
        option enabled '1'
        option device 'br-lan'
        option action 'block'
        list application 'netify.facebook'

I’m looking forward to debug the DPI filter and do some extensive tests…

Cross posting from other thread:

This is indeed a case to keep in mind when I do some tests with netifyd v5 (probably this week)
This might need to be reported over to netify folks

1 Like

I have tried to follow the documentation on ns-dpi | NethSecurity

Some parts seem to be outdated.

# /usr/sbin/netifyd -s
Netify Agent/4.4.7 (openwrt; x86_64; conntrack; netlink; plugins; regex)
✓ agent is running.
• persistent state path: /etc/netify.d
• volatile state path: /var/run/netifyd
• agent timestamp: Mon Nov 17 19:00:36 2025
• agent uptime: 0d 07:05:15
✓ active flows: 476
• CPU cores: 24
✓ CPU utilization (user + system): 0.0%
✓ CPU time (user / system): 0.0s / 0.0s
• maximum memory usage: 58768 kB
✓ br-lan [LAN]: online: packets (dropped / total): 0 / 404
✓ eth1 [WAN]: online: packets (dropped / total): 0 / 575
✓ DNS hint cache: enabled
• DNS hint cache entries: 12
• sink URL: https://sink.netify.ai/provision/
✗ sink services are disabled.
  To enable sink services, run the following command:
  # netifyd --enable-sink
✗ sink uploads are disabled.
  To enable sink uploads, ensure your Agent has been provisioned.
✓ sink agent UUID: 1V-JH-S8-IN
! sink site UUID is not set.
  A new site UUID will be automatically set after this agent has been provisioned by the sink server.
# netifyd -R -d -I br-lan -E eth1
netifyd[21967]: Error loading URL: /etc/netify.d/sink.url: No such file or directory
netifyd[21967]: Netify Agent/4.4.7 (openwrt; x86_64; conntrack; netlink; dns-cache; plugins; regex)
Loaded 18 of 18 DNS cache entries.
Loaded 9743 flow hash cache entries.
netifyd[21967]: Unable to hash file: /etc/netify.d/netify-sink.conf: No such file or directory
nd-conntrack: Loaded 200 conntrack entries.
nd-conntrack: Created.
void ndSocket::Create(): created
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 39, expr: "app == 'netify.signal' && (other_port == 3478 || local_port == 3478);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 39, expr: "app == 'netify.signal' && protocol_id == 78 && (other_port == 443 || local_port == 443);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 67, expr: "app == 'netify.google-chat' && protocol_id != 67 && (other_port == 5228 || local_port == 5228);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 67, expr: "app == 'netify.kik' && protocol_id != 67 && (other_port == 5223 || local_port == 5223);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 67, expr: "app == 'netify.meta-messaging' && protocol_id != 67 && (other_port == 5222 || local_port == 5222);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 67, expr: "app == 'netify.samsung-push' && protocol_id != 67 && (other_port == 5223 || other_port == 5229 || other_port == 3030 || other_port == 8090);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 74, expr: "app == 'netify.steam' && protocol_id != 74 && other_port >= 27015 && other_port <= 27030;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 78, expr: "app == 'netify.apple-push' && protocol_id == 0 && other_port >= 3478 && other_port <= 3495;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 142, expr: "app == 'netify.whatsapp' && protocol_id != 142 && (other_port == 5222 || local_port == 5222);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 156, expr: "app == 'netify.spotify' && protocol_id != 156 && (other_port == 4070 || local_port == 4070);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 185, expr: "app == 'netify.telegram' && protocol_id != 185 && (other_port == 5222 || local_port == 5222);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 185, expr: "app == 'netify.telegram' && protocol_id == 196;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 191, expr: "app == 'netify.speedtest' && other_port != 443 && (protocol_id == 0 || protocol_id == 7 || protocol_id == 91 || protocol_id == 131);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 194, expr: "app == 'netify.kakaotalk' && protocol_id != 194 && (other_port == 5222 || local_port == 5222);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 238, expr: "app == 'netify.apple-push' && protocol_id != 238 && (other_port == 5223 || local_port == 5223);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 245, expr: "app == 'netify.google-hangouts' && protocol_id != 245 && other_port >= 19302 && other_port <= 19309;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: -1, proto: 248, expr: "app == 'netify.zoom' && protocol_id != 248 && (other_port == 8801 || local_port == 8801);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10003, proto: -1, expr: "protocol_id == 74 && application_id == 0;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10005, proto: 245, expr: "app == 'netify.google' && other_port >= 19302 && other_port <= 19309;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10057, proto: -1, expr: "protocol_id == 43 && application_id == 0 && (other_port == 11095 || local_port == 11095);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10061, proto: -1, expr: "protocol_id == 9 && application_id == 0;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10279, proto: -1, expr: "protocol_id == 191 && application_id == 0;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10864, proto: 67, expr: "app == 'netify.apple' && protocol_id == 0 && other_port >= 3478 && other_port <= 3495;"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10864, proto: 238, expr: "app == 'netify.apple' && (other_port == 5223 || local_port == 5223);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 10910, proto: 67, expr: "app == 'netify.google' && (other_port == 5228 || local_port == 5228);"
bool ndApplications::AddSoftDissector(int, int, const std::string&): app: 11170, proto: 67, expr: "app == 'netify.meta-cdn' && (other_port == 5222 || local_port == 5222);"
Loaded 199 apps, 3374 domains, 783 networks, 26 soft-dissectors, 0 transforms.
netifyd[21967]: Error opening directory: /etc/netify.d/domains.d: No such file or directory
Created 128 flow map buckets.
Initializing nDPI v4.6.0-0-, API v0...
Enabled all protocols.
Banned protocol by ID: 295
Banned protocol by ID: 280
Banned protocol by ID: 258
Banned protocol by ID: 274
Banned protocol by ID: 110
Banned protocol by ID: 265
Banned protocol by ID: 178
Banned protocol by ID: 240
Banned protocol by ID: 252
Banned protocol by ID: 143
Banned protocol by ID: 145
Banned protocol by ID: 140
Banned protocol by ID: 254
Banned protocol by ID: 224
Banned protocol by ID: 317
Banned protocol by ID: 279
Banned protocol by ID: 246
Banned protocol by ID: 289
Banned protocol by ID: 220
Banned protocol by ID: 300
Banned protocol by ID: 180
Banned protocol by ID: 275
Banned protocol by ID: 283
Banned protocol by ID: 322
Banned protocol by ID: 292
Banned protocol by ID: 210
Banned protocol by ID: 318
Banned protocol by ID: 58
Banned protocol by ID: 71
Banned protocol by ID: 179
Banned protocol by ID: 288
Banned protocol by ID: 36
Banned protocol by ID: 119
Banned protocol by ID: 268
Banned protocol by ID: 259
Banned protocol by ID: 270
Banned protocol by ID: 203
Banned protocol by ID: 262
Banned protocol by ID: 122
Banned protocol by ID: 281
Banned protocol by ID: 284
Banned protocol by ID: 241
Banned protocol by ID: 217
Banned protocol by ID: 123
Banned protocol by ID: 126
Banned protocol by ID: 72
Banned protocol by ID: 239
Banned protocol by ID: 293
Banned protocol by ID: 319
Banned protocol by ID: 215
Banned protocol by ID: 137
Banned protocol by ID: 277
Banned protocol by ID: 202
Banned protocol by ID: 325
Banned protocol by ID: 216
Banned protocol by ID: 211
Banned protocol by ID: 193
Banned protocol by ID: 134
Banned protocol by ID: 261
Banned protocol by ID: 315
Banned protocol by ID: 233
Banned protocol by ID: 323
Banned protocol by ID: 157
Banned protocol by ID: 219
Banned protocol by ID: 276
Banned protocol by ID: 212
Banned protocol by ID: 221
Banned protocol by ID: 21
Banned protocol by ID: 250
Banned protocol by ID: 133
Banned protocol by ID: 26
Banned protocol by ID: 218
Banned protocol by ID: 63
Banned protocol by ID: 225
Banned protocol by ID: 187
Banned protocol by ID: 232
Banned protocol by ID: 183
Banned protocol by ID: 231
Banned protocol by ID: 228
Banned protocol by ID: 61
Banned protocol by ID: 303
Banned protocol by ID: 205
Banned protocol by ID: 266
Banned protocol by ID: 321
Banned protocol by ID: 39
Banned protocol by ID: 200
Banned protocol by ID: 328
Banned protocol by ID: 118
Banned protocol by ID: 199
Banned protocol by ID: 290
Banned protocol by ID: 234
Banned protocol by ID: 285
Banned protocol by ID: 324
Banned protocol by ID: 326
Banned protocol by ID: 163
Banned protocol by ID: 149
Banned protocol by ID: 90
Banned protocol by ID: 327
Banned protocol by ID: 299
Banned protocol by ID: 195
Banned protocol by ID: 120
Banned protocol by ID: 169
Banned protocol by ID: 186
Banned protocol by ID: 267
Banned protocol by ID: 320
Banned protocol by ID: 135
Banned protocol by ID: 141
Banned protocol by ID: 197
Banned protocol by ID: 242
Banned protocol by ID: 176
Banned protocol by ID: 147
Banned protocol by ID: 70
Banned protocol by ID: 124
Banned protocol by ID: 136
Online CPU cores: 24
Creating 24 detection threads at offset: 0
virtual void* ndSocketThread::Entry(): started
dpi0: detection thread created on CPU: 0
dpi1: detection thread created on CPU: 1
dpi2: detection thread created on CPU: 2
dpi3: detection thread created on CPU: 3
dpi4: detection thread created on CPU: 4
dpi5: detection thread created on CPU: 5
dpi6: detection thread created on CPU: 6
dpi7: detection thread created on CPU: 7
dpi8: detection thread created on CPU: 8
dpi9: detection thread created on CPU: 9
dpi10: detection thread created on CPU: 10
dpi11: detection thread created on CPU: 11
dpi12: detection thread created on CPU: 12
dpi13: detection thread created on CPU: 13
dpi14: detection thread created on CPU: 14
dpi15: detection thread created on CPU: 15
dpi16: detection thread created on CPU: 16
dpi17: detection thread created on CPU: 17
dpi18: detection thread created on CPU: 18
dpi19: detection thread created on CPU: 19
dpi20: detection thread created on CPU: 20
dpi21: detection thread created on CPU: 21
dpi22: detection thread created on CPU: 22
dpi23: detection thread created on CPU: 23
Purged 0 of 0 flow(s), active: 0, expiring: 0, expired: 0, idle: 0, blocked: 0
br-lan: PCAP capture thread created.
eth1: PCAP capture thread created.
br-lan: PCAP capture started on CPU: 0
Plugin initialized: np-nfa
Plugin detection initialized: np-nfa
netifyd[21967]: np-nfa: Netify Agent Flow Actions Plugin, v1.0.14
netifyd[21967]: np-nfa: Copyright (C) 2022 eGloo Incorporated.
netifyd[21967]: np-nfa: flow action targets: ctlabel, log, nftset
np-nfa: initialized, non-copy mode.
Plugin loaded: np-nfa: /usr/lib/libnetify-flow-actions.so.0
np-nfa: Configuration version: 1
/etc/xtables/connlabel.conf: Loaded 6 CT labels.
Plugin initialized: np-stats
Plugin detection initialized: np-stats
np-stats: initialized
Plugin loaded: np-stats: /usr/lib/libnetify-plugin-stats.so.0
netifyd[21967]: np-stats: Netify Agent Stats Plugin v1.0.17 (C) 2021 eGloo Incorporated.
np-stats: Loading configuration...
Caught signal: [29] I/O possible
np-nfa: Loaded 1 target(s), 1 action(s), 0 global exemption(s).
eth1: PCAP capture started on CPU: 1
ndSocket* ndSocketServer::Accept(): peer: /var/run/netifyd/netifyd.sock
Caught signal: [35] RT35: Client connected
netifyd[21967]: Unhandled signal: RT35
Caught signal: [36] RT36: Update
np-stats: flows: 72/172, filtered: NAT: 44, processing: 0, no packets: 0, unknown map: 56
Purged 0 of 172 flow(s), active: 116, expiring: 0, expired: 0, idle: 56, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 61/243, filtered: NAT: 62, processing: 0, no packets: 40, unknown map: 80
Purged 0 of 243 flow(s), active: 163, expiring: 0, expired: 0, idle: 80, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 54/293, filtered: NAT: 77, processing: 0, no packets: 66, unknown map: 96
Purged 22 of 293 flow(s), active: 175, expiring: 7, expired: 22, idle: 118, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 57/307, filtered: NAT: 91, processing: 0, no packets: 62, unknown map: 97
np-stats: appended 57 new stats record(s).
Purged 32 of 307 flow(s), active: 178, expiring: 12, expired: 32, idle: 129, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 74/316, filtered: NAT: 95, processing: 0, no packets: 50, unknown map: 97
Purged 18 of 316 flow(s), active: 201, expiring: 7, expired: 18, idle: 115, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 64/323, filtered: NAT: 96, processing: 0, no packets: 54, unknown map: 109
Purged 23 of 323 flow(s), active: 191, expiring: 5, expired: 23, idle: 132, blocked: 0
Caught signal: [36] RT36: Update
np-stats: flows: 49/321, filtered: NAT: 90, processing: 0, no packets: 66, unknown map: 116
Purged 21 of 321 flow(s), active: 184, expiring: 7, expired: 21, idle: 137, blocked: 0
...

I did:

uci set dpi.config.log_blocked=1
uci commit dpi
/etc/init.d/dpi restart
service netifyd reload

started to observe the logs

tested access to Facebook

and it was for the first time partly working :person_shrugging:
(blocking Facebook in Firefox and not blocking in Chrome - QUIC?)

I will observe and replicate on other Nethsecurity firewalls I’m running

PS: another firewall rules not blocking Facebook at all, and on third firewall - chrome and firefox blocked access to Facebook

I’m confused - will try DoH etc.

not blocking in Chrome

Cache will always bypass most of the blocks, not because the block isn’t working, but because browser will show you the cached data before sending a request. If you browse around, you’ll have the illusion that is working, but no requests are being sent. With the current implementation the entire conntrack entry is being tossed away by the firewall, you can see that in the developer tools on the browser.

Logs of the packets will be present on the /var/log/messages, no need to put netifyd on debug mode (with next iterations blocks will be notified better, we have tools to do that now)

1 Like

Solved

I have somehow forced Nethsecurity firewall to block DoH, so ChromeOS (Windows/MacOS?) is not able to upgrade DNS protocol to DoH, and only plain DNS is used and a plain DNS request can be redirected to internal DNS.

Solution:

After making changes to DPI filter be patient. Take some time, maybe restart the firewall. Clear the DNS cache (client OS related), open a new browser window in a anonymous mode, etc. This was the cause, why I did encounter random behavior…

1 Like

Different behavior in chrome and firefox is caused by different DNS settings (the cache doesn’t resist for weeks). Secure DNS is now a setting of the browser, not only the OS. And the problem was maybe also solved by restarting the firewalls.