I've been looking into application-level parental controls on openwrt recently and couldn't help but question what people are actually using for this.
I know OpenAppFilter exists, so application filtering on openwrt is obviously not something new.
I also work with some devices running much older versions from before the nftables transition. On those we use xt_ndpi, which makes this pretty straightforward since you can match an application directly from iptables and act on it.
With current openwrt though, I'm not really sure what the equivalent is. libndpi is already available and can identify applications, but I couldn't find something in the official package feeds that gives you the same kind of straightforward application matching/enforcement with fw4/nftables.
How are people are handling this today. Is OpenAppFilter what most people use when they actually need DPI based parental controls?
And is there some technical reason why we don't really have an xt_ndpi-like way of doing this with the current nftables stack, or has there just not been much demand for it?
Application level controls are typically done at the host device and/or within the app itself if you need anything fine-grained.
Because everything these days is encrypted, DPI can only go so far regarding analysis and/or blocking of specific content. You can use DNS filtering for coarse controls (i.e. block everything from a specific social media service, adult websites, etc.). These tend to be rather blunt, but they do work if your needs are not granular.
For example, you can block all of YouTube, but you cannot block ads or specific video content since you can't actually see what is being searched/viewed at the router level.
I'm not really looking at filtering specific content inside an application. I agree that at that point the endpoint is probably the right place to do it.
I'm more curious about blocking the application itself. For example, identify a flow as WhatsApp or YouTube and then block that entire flow for a particular client/or everyone.
That's what xt_ndpi made fairly easy on older iptables based systems. nDPI obviously can't tell me what video somebody is watching, but it can still classify a lot of encrypted traffic as YouTube, WhatsApp, Instagram, etc.
DNS filtering also only gets you so far here. It works well when an application maps cleanly to a set of domains, but starts getting messy once services share CDNs, use many changing domains, hardcoded IPs, DoH/DoT, or when blocking one domain ends up affecting other parts of the same service.
So I'm mostly wondering what happened to that kind of application-level matching with the move to nftables/fw4, and whether people still use DPI for this case.
Yeah, DNS is not a perfect solution, but it is a common one. Many of the DNS tools (Adguard, PiHole, etc.) maintain lists that are sufficiently extensive and dynamic to cover most of the CDNs and auxiliary services for major / well known properties. YMMV, of course.
That said, I'm not an expert on DPI solutions, so hopefully someone else can chime in about how effective they are these days.
My first method of parental control, many years ago, was based on proxying (squid), which was quite flexible and efficient, regarding the possible rules, i.e. blocking IP-based domains was rather trivial, but quite slow.
This was the main reason to change to DNS-based filtering, and to prevent certain circumvention techniques, i.using DoH or well-known VPNs, by special firewall blocks. DNS based filtering is fast, even when done in the most flexible way, by using a DB, to do user or device specific filtering. BUT all these methods depend upon the quality of the blacklists. Not having used DPI for filtering, first of all I suspect drastic speed penalties, and false positives, i.e. how to differentiate youtube videos on a web site for comics from adult movies ?
I think we are talking about two different levels of filtering here. I wouldn't expect DPI to tell me if a YouTube video is comics or adult content. The approach for that would be HTTPS interception/MITM.
What I mean by application-level filtering is much simpler: identify that a flow belongs to YouTube, WhatsApp, Facebook, etc. and then allow or block that application for a client.
This is the sort of thing nDPI can still do even with encrypted traffic. For example, this is from ndpiReader on my router where it is identifying flows as TLS.Facebook, QUIC.Google, etc. It obviously can't see what someone is doing inside Facebook or what video they're watching.
The reason I'm interested in this over plain DNS/IP blocking is that I don't want to block some shared CDN or critical infrastructure domain/IP and accidentally break unrelated services. I want to identify the application itself and block that, rather than maintain a list of domains or IPs that may be shared or keep changing.
I see. Makes some sense to me, as additional functionality of "parental control", which mainly means to filter adult web sites/content. I tried to block facebook using DNS and examination of conntrack flows during certain periods of time, but finally gave up, because not being reliable. Will have a look at ndpiReader.. Actually, I used iptables and nftables simultaneously in openwrt, with careful separation of rules/hooks in custom built image, from src.
Question: Does ndpiReader really identify flow characteristics, or simply SNI sniffing ?
ndpiReader itself is basically just the example app. The actual detection is done by libndpi. The one in the screenshot is a patched version where I changed the realtime output to continuously report detected flows.
It’s not just SNI sniffing. SNI/hostname is one of the signals nDPI can use, especially for TLS/QUIC, but it also uses protocol dissectors and other packet/flow characteristics depending on what it is trying to identify.
That said, if you see something like TLS.Facebook <graph.facebook.com>, then obviously the hostname is doing a lot of the work for that particular flow.
Small world. I put something up a few hours ago that sits right next to this.
It is a LuCI frontend for netifyd, the nDPI agent that is already in the feeds
and still builds on current kernels. Per application and per device, live and
for the past hour.
It does not block, so it is not what you are after. But it will tell you what
nDPI can actually put a name to on your own network, which you want to know
before you build enforcement on top of it. Services it does not know can be
added.
Ah, looks like a cool project. I actually started with netifyd too when I was playing around with this idea, but later shifted to using libndpi directly.
As I think you get the point I'm trying to make, in a utopian world, having a LuCI package where I can just block Instagram or WhatsApp for a client would be sick. Of course, this would probably work alongside DNS filtering rather than replace it.
How this should actually be done on modern OpenWrt is still the question. xt_ndpi was pretty cool back in the day.
(For anyone who lacks context, you could basically do something like iptables -I FORWARD -m ndpi --whatsapp -j DROP and match an application directly in the firewall. It made application blocking feel like just another firewall rule instead of having to maintain domains/IPs or some separate policy layer. That approach got left behind with the move away from iptables/xtables.)
One idea I had was to send only unclassified flows through NFQUEUE to something using libndpi, let nDPI inspect enough packets to classify the flow, then mark the conntrack entry. nftables could act on that mark afterwards, and packets from an already classified flow.
No idea yet if that's the best way to do it, especially with performance consideration. Curious what people who know netfilter better think.