You are most certainly running iptables over nftables, as this is the default on Debian buster. To confirm this is the case, check for (nf_tables):
# ip6tables-restore --version ip6tables-restore v1.8.2 (nf_tables)
Now in the ip6tables manual, there always has been:
-4, --ipv4
This option has no effect in iptables and iptables-restore. If a rule using the -4 option is inserted with (and only with) ip6tables-restore, it will be silently ignored. Any other uses will throw an error. This option allows IPv4 and IPv6 rules in a single rule file for use with both iptables-restore and ip6tables-restore.
The trouble is that you're now running ip6tables-nft-restore rather than ip6tables-legacy-restore.
There is no mention of -4 in differences to legacy iptables, meaning there shouldn't be a difference about it, but here it is. This really looks like a bug: either the new version ip6tables-nft-restore should cope with it, or the documentation should reflect it as an additional difference to be acceptable.
By the way the other way around (-6 with iptables-nft-restore) doesn't look better: it's accepted instead of ignored, leading to -A INPUT -p ipv6-icmp -j ACCEPT in addition to -A INPUT -p icmp -j ACCEPT in IPv4 protocol (this will never happen, except maybe with a custom test, and the IP stack will ignore it anyway).
Possible workarounds:
file a bug report, insisting on a regression which would break existing rules and documentation. This would help other people too.
split rules
split your file into two files but apply a different filter to each, something like:
grep -v -- '^ *-4 ' < before > after.v6 grep -v -- '^ *-6 ' < before > after.v4
create a wrapper for ip6tables-restore in /usr/local/sbin/ip6tables-restore doing about the same (and also do the same for iptables-restore), allowing to keep a single rule
Give up (for now) iptables over nftables and revert to legacy iptables:
# readlink -f $(which ip6tables-restore) /usr/sbin/xtables-nft-multi # update-alternatives --config ip6tables There are 2 choices for the alternative ip6tables (providing /usr/sbin/ip6tables). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/sbin/ip6tables-nft 20 auto mode 1 /usr/sbin/ip6tables-legacy 10 manual mode 2 /usr/sbin/ip6tables-nft 20 manual mode Press <enter> to keep the current choice[*], or type selection number: 1 update-alternatives: using /usr/sbin/ip6tables-legacy to provide /usr/sbin/ip6tables (ip6tables) in manual mode # readlink -f $(which ip6tables-restore) /usr/sbin/xtables-legacy-multi
The link of the related command also changed, fine.
Do the same with iptables.
Current rules are still running over nftables. You can dump them with iptables-nft-save + ip6tables-nft-save and restore them with iptables-save + ip6tables-save. This will result in rules running twice: once with kernel's iptables backend, once with kernel's nftables backend, and NAT might not always work correctly with this on kernel 4.19 (usually the first loaded module wins: here nft_nat). Better reboot, or know how to flush rules and remove relevant (nat) nftables modules.
embrace the new features and use directly nft.
There are commands available to help here (but they have the same problem as above): iptables-translate / ip6tables-translate and iptables-restore-translate / ip6tables-restore-translate, but the result usually needs reworking anyway (especially with fancy matches like u32). Nftables has a family type inet which can actually mix IPv4 and IPv6 rules (might require a newer kernel for this in nat), so it would simplify things.