Open tycho opened 4 years ago
One downside to the net.ipv6.conf.all.disable_ipv6
approach is that setting it back to 0
will not necessarily cause IPv6 address assignments to come back in a timely fashion.
SLAAC addresses obtained via router advertisements would come back quickly, depending on the router advertisement interval (typically only a few seconds in most configurations).
DHCPv6 addresses are another story, because whatever is managing the interface (NetworkManager or systemd-networkd, for example) would have to explicitly request a new address assignment. This will eventually happen automatically, but it does take longer (in my local testing it took about 2-3 minutes before it noticed the missing DHCPv6 lease and refreshed it).
That said, I still think the net.ipv6.conf.all.disable_ipv6
approach is probably the better one.
It was like that in the past actually, but the problem was that it didn't do anything after a while, as you've mentioned. So it's a very problematic approach.
Well, even if the iptables rules were working as intended, the input/output drop rules would eventually cause the IPv6 leases to expire anyway, because the system would be prohibited from communicating to maintain the leases.
Yeah, but they won't come back this way. I've already thought it's not working as intended and think about making the ipv6 protection just like the kill switch... Blocking everything.
They do come back. Once disable_ipv6
is restored to 0
, SLAAC addresses come back almost instantly, and DHCPv6 addresses come back after a few minutes. Using the sysctl
also has the advantage of clearly communicating to other things that the interfaces have had a state change. Silently dropping IPv6 via iptables until the leases die off just makes things think the system has poor/broken IPv6 connectivity instead of no IPv6 connectivity.
I don't get your point. If connectivity comes back at some point but the users expects it not to come back, it's really bad and shouldn't be done this way. So sysctl is out.
We must be talking past each other. I'm saying it comes back once the VPN is disconnected. It should not come back on its own while disable_ipv6=1
.
Oh, yeah, I meant it comes back while the VPN is on, making it possible to connect via IPv6 to services and not go over the VPN.
Okay. Under what conditions has it been observed to come back while the VPN is on and disable_ipv6=1
? The only case I can think of is that something else independently explicitly enables IPv6 again.
I mean, even if the iptables approach was working (e.g. if it was using -I
instead of -A
), there's nothing to prevent the table from being automatically stomped on by whatever's managing the rules there and negating the IPv6 leak prevention there, either.
Check out #59 and also this reddit thread.
I'm all for going back and not playing with the IPv6 firewall rules, but it leaked...
Could do both. Insert (instead of append) the rules first, and then do the disable_ipv6=1
sysctl. So even if the sysctl gets reverted somehow, the firewall rules would be in place. It's still not perfect, but less likely to result in leakage.
I was more thinking about doing
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP
And upon disconnecting restoring again. Basically how the Kill Switch works.
That should work. It's a bit heavy-handed, but I think it'd functionally do the right thing. I think the sysctl is still necessary on top of it, though (i.e. for link state change notifications via netlink).
I have a bunch of iptables rules already set up so that I can route networking for virtual machines running on my local machine. The commands that
protonvpn-cli-ng
uses to drop IPv6 traffic end up doing nothing, as they're appended to the end of the relevant chains, after my existing rules selectively allowing traffic.For example, my
OUTPUT
chain contains something like this (simplified for readability):protonvpn-cli-ng
adds this rule after it, which is never hit:As a result, IPv6 traffic ends up leaking.
One option to solve this would be to disable IPv6 entirely while connected: e.g. save off the value of
net.ipv6.conf.all.disable_ipv6
before connecting, set it to1
while connected and restore it to the previous value when disconnected. This would disable IPv6 on all interfaces, which would probably be better than aDROP
rule anyway because applications wouldn't even attempt to make any IPv6 connections when that's set.