0

I'm trying to implement a set of iptables rules for OpenVPN:

  1. Everything (without exception) goes through OpenVPN
  2. If OpenVPN is down or inaccessible everything (without exception) cannot access the internet
  3. Local access is always possible, irrespective of the status of OpenVPN

The best (out of six examples) I've seen so far is this, however it still allows access to the internet when the VPN is down through ipv6:

# Clean down existing rules
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -t nat -F
ip6tables -t mangle -F
ip6tables -F
ip6tables -X

# Allow loopback device (internal communication)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic.
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT

# Allow VPN establishment
iptables -A OUTPUT -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -p udp --sport 1194 -j ACCEPT

# Accept all TUN connections (tun = VPN tunnel)
iptables -A OUTPUT -o tun+ -j ACCEPT
iptables -A INPUT -i tun+ -j ACCEPT

# Set default policies to drop all communication unless specifically allowed
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

If I try to blanket block all ipv6 traffic (which is what a number of examples suggest) then I cannot connect to anything:

# Set default policies to drop all communication unless specifically allowed
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP

If I try to mirror what is in the ipv4 section then I have this:

# Allow loopback device (internal communication)
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic.
# (Skipped as I don't know how to do this)

# Allow VPN establishment
ip6tables -A OUTPUT -p udp --dport 1194 -j ACCEPT
ip6tables -A INPUT -p udp --sport 1194 -j ACCEPT

# Accept all TUN connections (tun = VPN tunnel)
ip6tables -A OUTPUT -o tun+ -j ACCEPT
ip6tables -A INPUT -i tun+ -j ACCEPT

Now I'm unable to connect to anywhere and curl https://ipinfo.io/ip just hangs.

How can I fix this?

0

Your example script cleans all rules for IPv4 and IPv6 rulesets... but doesn't add any rules for IPv6.

Notice how the "Clean down existing rules" section calls both iptables and ip6tables, resetting both firewalls to their default "wide open" state. The remaining sections, however, do nothing with ip6tables at all.

  • Yep, I alluded to that in the question. If I blanket block all ipv6 (which is what a couple of examples I've found suggest) then nothing works. – Richard Dec 31 '18 at 20:13
  • Then don't blanket block it – do the same as the IPv4 rules do! – grawity Dec 31 '18 at 20:16
  • Point taken, I'll update the question :) – Richard Dec 31 '18 at 20:16
0

It turns out that I'd not whitelisted the DNS servers of the VPN service. Once I did that, I was able to blacklist ipv6 without an issue.

For the sake of completeness, this is what I finally got to work. Three things to bear in mind:

  1. You should replace [Primary DNS IP here] and [Secondary DNS IP here] with the IP addresses of the DNS servers you're planning to use
  2. Don't forget to edit /etc/resolvconf.conf to add the IP addresses in #1 as nameservers and blacklist your own to avoid DNS leakages.
  3. This assumes your local traffic has an IP range starting 192.168. If not, you'll need to change this.

Code as follows:

# Remove any existing rules
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -F
sudo iptables -X
sudo ip6tables -P INPUT ACCEPT
sudo ip6tables -P FORWARD ACCEPT
sudo ip6tables -P OUTPUT ACCEPT
sudo ip6tables -t nat -F
sudo ip6tables -t mangle -F
sudo ip6tables -F
sudo ip6tables -X

# Allow loopback device (internal communication)
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic
sudo iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT

# Allow DNS (could be VPN provider or someone like Cloudflare's 1.1.1.1)
sudo iptables -A OUTPUT -d [Primary DNS IP here] -j ACCEPT
sudo iptables -A OUTPUT -d [Secondary DNS IP here] -j ACCEPT

# Allow related and established connections
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Allow VPN establishment
sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 53 -j ACCEPT
sudo iptables -A OUTPUT -p udp --dport 1198 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 1198 -j ACCEPT

# Accept all tun0 (VPN tunnel) connections
sudo iptables -A OUTPUT -o tun0 -j ACCEPT
sudo iptables -A INPUT -i tun0 -j ACCEPT

# Allow for nslookup to not throw an error
sudo ip6tables -I OUTPUT 1 -p udp -s 0000:0000:0000:0000:0000:0000:0000:0001 -d 0000:0000:0000:0000:0000:0000:0000:0001 -j ACCEPT

# Drop everything else (ipv4)
sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT DROP
sudo iptables -P FORWARD DROP

# Drop everything (ipv6)
sudo ip6tables -P INPUT DROP
sudo ip6tables -P OUTPUT DROP
sudo ip6tables -P FORWARD DROP
0

Future readers, be aware that the rules presented here "will allow deanonymization because it allows any connection over port 1194, not just traffic originating from OpenVPN". This answer presents a much simpler set of rules which do not require hardcoding any IPs or ports.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.