Parental controls won't work by the recipe for me, my "working" solution is rather complicated

I can't make parental controls both simple and reliable. The recipe on the openwrt documentation pages do work fine for new connections, but killing already established connections is quite a challenge.
My best indicator is that youtube seldom stops. Sadly not simply buffering is what tricks me (e.g. I scroll into longer videos to see the effect).

What I tried is the following:

A) The old recipe:

# Insert rule for forwarding established connection traffic, just before the final rule (reject)
new_rule_num=$(iptables -v -L FORWARD --line-numbers | grep reject | cut -d ' ' -f 1)
iptables -I FORWARD $new_rule_num -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Delete first rule for forwarding established connection traffic
old_rule_num=$(iptables -v -L FORWARD --line-numbers | grep ESTABLISHED | cut -d ' ' -f 1 | sed -n 1p)
iptables -D FORWARD $old_rule_num
# Get rid of any duplicate ESTABLISHED rules (these seem to be caused when restarting the firewall)
est_count=$(iptables -v -L FORWARD --line-numbers | grep ESTABLISHED | wc -l)
while [ $est_count -gt 1 ]; do
      old_rule_num=$(iptables -v -L FORWARD --line-numbers | grep ESTABLISHED | cut -d ' ' -f 1 | sed -n 1p)
      iptables -D FORWARD $old_rule_num
      est_count=$(iptables -v -L FORWARD --line-numbers | grep ESTABLISHED | wc -l)
done

Checking by

iptables -v -L FORWARD --line-numbers

it does reorder the iptables ("Insert rule for forwarding established connection traffic, just before the final rule (reject)"), but without the desired effect.

B) The new recipe at https://openwrt.org/docs/guide-user/firewall/fw3_configurations/fw3_parent_controls broke for me, because of multiple matches by

iptables-save -c -t filter | grep 'FORWARD.*ESTABLISHED'

Joining the lines with '\n' separator) did fix it, though I'm still not sure why I have multiple matches. The modified script (I hope that I've understood the logic of the original one):

for IPT in iptables ip6tables ; do
  ipt_out="$(${IPT}-save -c -t filter)"
  ipt_out_in="$(${IPT}-save -c -t filter | grep 'FORWARD.*ESTABLISHED' | sed -e :a -e '$!N; s%\n%\\n%; ta')"
  echo $ipt_out | sed -e "/FORWARD.*ESTABLISHED/d; /FORWARD.*reject/i $(echo $ipt_out_in)" | ${IPT}-restore -c -T filter
done

Now it moves the matching 'FORWARD.*ESTABLISHED' rules just before the 'FORWARD.*reject' one, just as the logic of the script implies. Still, youtube videos are not cut after running the script.

C) Posts of the forum (like Unable to get Parental Controls to work and Firewall problem in LEDE) did not provide me a working solution.
However, the latter post advices inserting/removing reject rules for each impacted MACs. (... while the examples above imply it is not needed. Or is it?)

My actual way of parental controlling now looks like doing the /etc/config/firewall reconfiguration which additionally triggers (B) + manually running (C) + running (A). This constellation seems to be working, but did not thoroughly tested it yet.
What puzzles me is

  • (B) and (A) should have similar effects. Still, without running (A) youtube keeps working.
  • The original solution neither bothers with (C). Skipping it from the above chain won't kill youtube sessions.
  • So in general instead of the simple recipe, a rather complicated solution seems to be working - for me. Not really being a networking guy, I don't know why.

Any ideas or comments? I'd appreciate if someone could point me in the right direction. Thank you in advance.

This is by nature of how most stateful firewalls work. Once a connection is established, it continues to pass traffic. For efficiency reasons this check is usually done as one of the first rules.

If you want to block existing connections in the firewall, it needs to be done before the check for related/established.

(C) sounds like it causes existing connections to be terminated.

What is the use case you’re trying to solve? Where/when, other than in your tests, does the “simple” approach fail?

1 Like

What is the use case you’re trying to solve? Where/when, other than in your tests, does the “simple” approach fail?

The use case is parental controlling my nieche. The only way of making him NOT watching streamed stuff or playing online during the whole night is (effectively...) restricting his access. Here did the simple approach fail miserably. Now the (A)+(B)+(C) combo looks promising, though not pretty at all.

can't use just make cron to disable and restart wan interface when rule changes, so force the reconnect?

1 Like

Maybe it would make more sense to add the reject rule in the 'firewall.user' script, so that it can be placed from the starting of the firewall service to the top of the forward chain, rather than moving the checking established rule lower and adding extra load.

 -A FORWARD -m comment --comment "!fw3: Custom forwarding rule chain" -j forwarding_rule

This is the first rule in the forwarding chain, so you could add your scheduled reject rule there.

What about a conntrack flush? Clear out connections and make them all reestablish (only to be blocked by rules)

3 Likes

Can nf_conntrack_tcp_loose help here?

nf_conntrack_tcp_loose - BOOLEAN
	0 - disabled
	not 0 - enabled (default)

	If it is set to zero, we disable picking up already established
	connections.

Some how this was disabled by default on my device.

2 Likes