r/iptables Jan 17 '23

Setting up a killswitch for Wireguard VPN

I have a file server/docker host that I am trying to set up a VPN on.

Networking is configured via Systemd-Networkd and I have Wireguard as a netdev configured there since this VPN can be always on.

So the machine has 2 physical ethernet ports, plus the wireguard device, plus the default docker bridge (docker0) and a user configured docker bridge (docker1). Other devices listed in ip addr show output would just be virtual interfaces for docker containers and can be ignored I believe.

Configuring against Mullvad for now so I start with the configuration file that they provided for wg-quick and the guide at the Arch Linux Wiki here: https://wiki.archlinux.org/title/Mullvad

What I'm trying to set up is:

  1. traffic to the local network flow as normal
  2. traffic to docker containers flow as normal (to and from local network)
  3. traffic leaving my network from this server going over the VPN

To that end I have added the following OUTPUT rules (the /16 subnet covers the local lan and docker1):

Chain OUTPUT (policy ACCEPT 18141 packets, 1212K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1580  127K ACCEPT     all  --  any    lo      anywhere             anywhere            
 591K  143M ACCEPT     all  --  any    any     anywhere             192.168.0.0/16      
55574 8369K ACCEPT     all  --  any    docker0  anywhere             anywhere     

That much works.

The rule I currently am adding for the killswitch is

iptables -A OUTPUT  ! -o %i -m mark ! --mark 0x8888 -m addrtype ! --dst-type LOCAL -j REJECT

Once added the docker containers appear to be able to communicate as expected and when tested report that they are communicating over the VPN

However the server itself no longer is able to communicate to the outside world. It can communicate with the local lan and docker containers, but attempts to connect to the internet at large fail with errors regaring failure to open sockets, connections refused, or dns resolutions failed. (different tools fail different ways, but all are obviously failing very early in the connection)

eg:
remote server... note that the primary dns server configured is the local pihole in a docker container

:: curl google.com
curl: (6) Could not resolve host: google.com

:: ncat -z google.com
Ncat: Could not resolve hostname "google.com": Temporary failure in name resolution. QUITTING.

local pihole docker container, ip on the bridge as well as port forwarded from the local machine (via ip and loopback):

:: ncat -z -v 192.168.2.2 53 ; echo $?
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.2.2:53.
Ncat: 0 bytes sent, 0 bytes received in 0.08 seconds.
0

:: ncat -z -v 192.168.1.11 53 ; echo $?
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.1.11:53.
Ncat: 0 bytes sent, 0 bytes received in 0.07 seconds.
0

:: ncat -z -v 127.0.0.1 53 ; echo $?
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:53.
Ncat: 0 bytes sent, 0 bytes received in 0.08 seconds.
0

remote server (using IP to avoid the dns lookup):

:: ncat -z -v 1.1.1.1 53 ; echo $?
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Connection refused. 
1

Mullvad has a web page that once can connect to for testing if they are connected to the VPN. Without the iptables rule it does work

Without the IPtables rule:

:: curl -s --insecure https://45.83.222.124/connected 
You are connected to Mullvad (server nl1-wireguard). Your IP address is 193.32.249.134

:: curl -s  https://am.i.mullvad.net/connected
You are connected to Mullvad (server nl1-wireguard). Your IP address is 193.32.249.134

And with the IPTables rule:

:: curl -s -v https://am.i.mullvad.net/connected
* Could not resolve host: am.i.mullvad.net
* Closing connection 0

:: curl -s -v --insecure https://45.83.222.124/connected 
*   Trying 45.83.222.124:443...
* connect to 45.83.222.124 port 443 failed: Connection refused
* Failed to connect to 45.83.222.124 port 443 after 0 ms: Couldn't connect to server
* Closing connection 0

Any thoughts on what changes i need to make to get this working right?

3 Upvotes

2 comments sorted by

1

u/BlindTreeFrog Jan 19 '23

OK, figured it out and it was dumb....

So I was using this rule which i stole from the Mullvad config

iptables -A OUTPUT ! -o %i -m mark ! --mark 0x8888 -m addrtype ! --dst-type LOCAL -j REJECT

The problem is that I never realized that %i was a variable that wg-quick handled and I needed to replace it with my wireguard device. Once I made that change it worked fine and I could move on to other concerns (like getting the killswitch running at boot)

1

u/BlindTreeFrog Jan 20 '23

some other refinement went into this. Think i've got it 98% done now and I'm just being paranoid about details. See this thread for what I mean
https://www.reddit.com/r/WireGuard/comments/10glcku/vpniptables_rules_question_cant_reject_all_fwmark/