1

I bought a subscription to a VPN service and I am using the openvpn 2.5.1 client to connect to it. I am using Ubuntu 20.10.

I now want to emulate the "kill switch" feature of most proprietary VPN client.

That is, I want to block any connection that is not tunneled through the VPN. Said otherwise, if the VPN connection drops for some reason (eg. server unreachable), I want all internet connection to be blocked.

To achieve this result, I am following this tutorial.

I have come up with the following iptables rules:

*filter

# Drop all packets
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP

# Allow incoming packets only for related and established connections
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Allow loopback and tunnel interface
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o tun0 -p icmp -j ACCEPT

# Allow local LAN
-A OUTPUT -d 192.168.1.0/24 -j ACCEPT

# Allow VPN's DNS servers
# Gli indirizzi del server DNS di NordVPN sono 103.86.96.100 e 103.86.99.100
-A OUTPUT -d <DNS_SERVER_1> -j ACCEPT
-A OUTPUT -d <DNS_SERVER_2> -j ACCEPT

# Allow the VPN itself (both protocol/port and interface)
# We use TCP/443
#-A OUTPUT -p udp -m udp --dport 1194 -j ACCEPT
#-A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A OUTPUT -p tcp --dport 443 -j ACCEPT
-A OUTPUT -o tun0 -j ACCEPT

COMMIT

and I am importing it with sudo iptables-restore < ./vpn_iptables_killswitch_rules.ipv4.

After the import I am able to connect to the VPN successfully. That is, the openvpn client establishes the connection successfully.

However, I am unable to resolve domain name in IP addresses. In fact, ping google.com returns a temporary failure in name resolution, while traceroute 8.8.8.8 works without problems.

This should not happen since I have whitelisted the DNS servers on my rules.

A nmcli connection show <SSID> shows that the connection is using the DNS servers provided by my VPN provided and is ignoring the DNS servers provided by DHCP.

What I am doing wrong here?

1

Run the command tcpdump port domain and then try to reach a hostname while connected to your VPN to see if the packages are actually sent to the expected DNS servers, and if you can see any response coming back in order to figure out what is going on.

If the DNS requests are sent to the wrong DNS servers, you can change your setup. Or even better, since you are already using iptables for this, you can add some iptables rules to the nat table that redirects all outgoing DNS packets addressed to any DNS server outside of your LAN to your VPN DNS servers:

*nat
# Redirect all outgoing DNS requests to a specific server (both TCP and UDP)
-A PREROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -p tcp -m tcp --dport 53 -m state --state NEW -j DNAT --to-destination <DNS_SERVER_1>
-A PREROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -p udp -m tcp --dport 53 -m state --state NEW -j DNAT --to-destination <DNS_SERVER_1>

(Be aware that these are rules for the nat table, so be sure to separate your filter rules from your nat rules by having your filter rules below the *filter line and your nat rules below the *nat line.)

You can also use iptables to log packages to see what are actually matched by your rules in order to troubleshoot.

Sending and receiving of UDP packets seems to be working since you are able to do traceroute which defaults to UDP mode on linux, so it seems kind of strange that DNS doesn't work.

Your last rule "-A OUTPUT -p tcp --dport 443 -j ACCEPT" seems to be accepting ALL outgoing https connections on ANY interfaces. This will also allow https requests to be sent outside of the VPN tunnel. You should probably put in the address of your VPN server in this rule.

6
  • Thank you. It was due to (1) NetworkManager was managing the /etc/resolv.conf (2) NetWorkManager did not update /etc/resolv.conf with the DNS servers of my VPN despite issuing nmcli connection modify <SSID> ipv4.dns "<DNS1> <DNS2>" and nmcli connection modify <SSID> ipv4.ignore-auto-dns yes for some reason. /etc/resolv.conf was still pointing to loopback. Thanks for pointing out that the current configuration would accept all outgoing HTTPS traffic! Are the DNS requests supposed to travel through TCP 443 as well? – robertspierre Feb 28 at 9:57
  • You should really have your DNS requests go though the VPN tunnel as well, or else the network you connect to might eavesdrop or even modify the responses. DNS has always been meant for both UDP and TCP. DNS requests are mainly over UDP, but larger DNS responses will require the response to be in a TCP session when it exceeds the maximum packet size for a single UDP packet, so it should absolutely be allowed as well. You also have DNS over TLS (port 853) and DNS over HTTPS (port 443) which can also allow supported clients to resolve DNS requests. Some clients supports these as standard. – knowsshit Feb 28 at 10:30
  • Thank you. How can I have my "DNS requests go through the VPN tunnel as well"? Does it mean that the DNS requests should exit from my network on TCP 443 (the port of the VPN tunnel) to go to the VPN server, or exiting on port 53 and going directly to the DNS server would be fine as well? – robertspierre Feb 28 at 10:47
  • While connected to your VPN service, all your DNS requests should leave your network in the VPN tunnel (tcp port 443 to your VPN provider). You can run the command "tcpdump not port 443" to see traffic that is not on port 443. If you can see the requests with tcpdump, they are going unencrypted outside of the VPN tunnel. You can use the route command to ensure that certain destinations are reached through certain interfaces: ip route add <DNS_SERVER_1>/32 dev tun0 Repeat for any other DNS servers. – knowsshit Feb 28 at 16:47
  • If you want ALL your traffic to go through the VPN tunnel you can add a route for your VPN server to leave through your local gateway, delete your default route and add a new default route for your VPN interface: ip route add <IP_TO_VPNSERVER>/32 via <YOUR_DEFAULT_GW> dev eth0 ip route del default ip route add default via <VPN_DEFAULT_GW> dev tun0 You will need to replace your default gw when taking down the tunnel: ip route del default via <VPN_DEFAULT_GW> dev tun0 route add default gw <YOUR_DEFAULT_GW> – knowsshit Feb 28 at 17:00
0

For what it's worth, using the suggestion on this SE, I wrote a VPN "client" (it really interfaces with openvpn) that:

  1. Set up the killswitch for you
  2. Configure DNS resolution to use the DNS servers of the VPN provider (and allow them through the killswitch)

You can find it here

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.