Ok, I dove deep on the problem, and figured out that AFWall+ must not like the iptables for this system (Android Nougat 7.0.04.13, rooted with TWRP as bootloader and Magisk as root).
I uninstalled AFWall+ and started fresh.
Under:
AFWall+ Preferences > Experimental Features > Startup directory for script, I set it to /data/adb/service.d/
AFWall+ Preferences > Profiles > I enabled multiple profiles and 'Apply rules on profile switch'.
AFWall+ Preferences > Binaries > Iptables binary, I set it to 'Built-in iptables'.
AFWall+ Preferences > Binaries > BusyBox binary, I set it to 'Built-in BusyBox'.
At the top of my .sh scripts, I'd been using (taken from
here):
# NECESSARY AT THE TOP OF EACH SCRIPT!
IP6=/system/bin/ip6tables
IP4=/system/bin/iptables
I changed it to:
# NECESSARY AT THE TOP OF EACH SCRIPT!
IP6=ip6tables
IP4=iptables
And I enabled:
[-12] (tethering) - DHCP+DNS services (dev.afwall.special.tether)
... and aside from Nebulo glitching and not passing DNS requests after an AFWall+ profile change (I have to stop Nebulo and start it for it to work... a bug report is in with the app's developer), everything seems to work!
Still need the auto-flush chain on at least the INPUT chain, though. Maybe the app's dev can hang an auto-flush chain off PREROUTING... blocking incoming packets further upstream means fewer CPU cycles consumed in blocking them, and that's important on a battery-operated device.
{UPDATE}
I've run with the above settings for awhile now, and they're not working correctly. The issues I've had with running the iptables built-in to AFWall+:
1) AFWall+ is very slow to flush and update iptables / ip6tables. It pauses for a long time twice as rules load, and rules loading is painfully slow even between the pauses.
2) Sometimes, AFWall+ reports that it's unable to gain root, then it doesn't load any iptables at all (the Rules window is completely blank) and the firewall disables.
3) Even when AFWall+ does successfully apply the new rules on a change of profile, when I close the AFWall+ window, it shows in the notifications that AFWall+ is applying the rules again. If I then open AFWall+ again and go to the Rules window, the rules are entered twice for each rule. Strangely, it seems it's only doing this for IPv4 rules... running:
adb shell
su
iptables -L
shows the twice-entered rules in the IPv4 iptable, whereas running:
adb shell
su
ip6tables -L
shows the rules don't seem to be twice-entered in the IPv6 iptable.
So I've changed things again:
Under:
AFWall+ Preferences > Experimental Features > Startup directory for script, I set it to /data/adb/service.d/
AFWall+ Preferences > Profiles > I enabled multiple profiles and 'Apply rules on profile switch'.
AFWall+ Preferences > Binaries > Iptables binary, I set it to 'System iptables'.
AFWall+ Preferences > Binaries > BusyBox binary, I set it to 'System BusyBox'.
At the top of my .sh scripts:
# NECESSARY AT THE TOP OF EACH SCRIPT!
IP6=/system/bin/ip6tables
IP4=/system/bin/iptables
Thus far, AFWall+ switches profiles really quickly, and thus far I've not gotten the error dialog stating that AFWall+ couldn't gain root.
I'm using the
Stericson BusyBox.
So it appears there are problems with AFWall+'s built-in iptables and busybox. Or perhaps trying to have AFWall+ do everything (manage profiles, wrangle internal iptables, run internal busybox, etc.) was just too much, and things were timing out, but I've got a 1.3 GHz octa-core CPU and the problems haven't appeared using system iptables and system BusyBox, except for the rules duplication issue when the AFWall+ window is closed (described above).
{/UPDATE}
{UPDATE2}
I'm trying something new in the custom scripts... explicitly denoting the path to iptables, even for the built-in AFWall+ iptables:
# NECESSARY AT THE TOP OF EACH SCRIPT!
# NOTE: You must change each {$IP4S | $IP4A | $IP4D} and {$IP6S | $IP6A | $IP6D}
# to reflect your use of System, AFWall+ or AFWall+(Donate version) iptables
# -------------------------
# System iptables
IP6S=/system/bin/ip6tables
IP4S=/system/bin/iptables
# AFWall+ iptables
IP6A=/data/data/dev.ukanth.ufirewall/app_bin/ip6tables
IP4A=/data/data/dev.ukanth.ufirewall/app_bin/iptables
# AFWall+Donate iptables
IP6D=/data/data/dev.ukanth.ufirewall.donate/app_bin/ip6tables
IP4D=/data/data/dev.ukanth.ufirewall.donate/app_bin/iptables
# -------------------------
So for instance, a ruleset for the system's iptables would be:
# DROP invalid packets
$IP4S -A afwall -m state --state INVALID -j DROP
$IP6S -A afwall -m state --state INVALID -j DROP
... whereas for the in-built iptables in the free version of AFWall+, it'd be:
# DROP invalid packets
$IP4A -A afwall -m state --state INVALID -j DROP
$IP6A -A afwall -m state --state INVALID -j DROP
... and for the iptables in the Donate version of AFWall+ it'd be:
# DROP invalid packets
$IP4D -A afwall -m state --state INVALID -j DROP
$IP6D -A afwall -m state --state INVALID -j DROP
I'm going to switch back to using AFWall+'s built-in iptables to see how it works with the above.
{/UPDATE2}
{ASIDE}
Hmmm... I wonder... if I set AFWall+ to use its internal iptables, but explicitly denoted that the rules I load via dot shell script use the system iptables, would that allow the phone to use both iptables, which would mean I could flush INPUT and OUTPUT chains in the system iptables (via the dot shell script) without affecting the AFWall+ iptables?
Because that'd give us a means of INPUT and OUTPUT packet filtering, whereas now we only have OUTPUT packet filtering (via the 'afwall' chain). Which means we could block scans, exploits, etc.
Must experiment.
{/ASIDE}