0

I'm building a virtual Ubuntu Server(LXC on Proxmox) that shall act as router and tunnel some devices(e.g. AppleTV) of my local network through a VPN (expressVPN). Connecting and routing to different VPN destinations (different countries) is working.

But some services still know that I'm not calling from the country the VPN Server is standing in. (I think its called DNS leaking???)

Thats because my client, let's say the AppleTV box uses e.g. 1.1.1.1 as DNS. It doesn't know the DNS server the VPN Server published to my gateway.

To prevent that from happening I'ld like to use the VPN's DNS service I receive when connecting. I pointed the AppleTV to my gateway as DNS and wrote some iptables rules to DNAT the requests to the DNS servers provided by the VPN server. (Hope that makes sense)

# Route DNS Traffic
iptables -t nat -A PREROUTING -p tcp --dst x.x.x.x --dport 53 -j DNAT --to-destination 10.54.0.1:53
iptables -t nat -A PREROUTING -p udp --dst x.x.x.x --dport 53 -j DNAT --to-destination 10.54.0.1:53

That works well.

Question

How to automatically generate these rules when establishing the OpenVPN connection? The specific DNS Address will change when connection to another VPN station (e.g. different country). Or is there a better solution?

I was thinking about putting it in the update-systemd-resolved, but that seems way to complicated. I assume there is a easy way to go.

I'm thankful for any hint.

2 Answers 2

0

Welcome, you may use the up and down command in your openvpn *.conf file These allow to execute custom scripts. script-security 2 is requirede if you go this Road Example:

script-security 2
up /usr/local/bin/set-redirect-dns.sh
down /usr/local/bin/unset-redirect-dns.sh

The real iptables commands are in these scripts. Please check with the man page if script-security 2 is fine for you.

1
  • at the moment I'm using up and down to feed resolved with the vpns infos like DNS. e.g. up /etc/openvpn/update-systemd-resolved I'll give it a try to add some iptable rules. I just thought there is an out of the box solution. I assumed this as a common problem.
    – Michael
    Jan 5, 2023 at 15:28
0

I'll answer my own question to show my solution.

I learned that resolved uses a dns via stub (127.0.0.53) and therefore knows how to use the DNS of the VPN.

I "just" had to forward/nat the DNS requests from the LAN clients who are using this server as a gateway (and DNS).

In the openvpn client configuration I added the following lines:

mci@vpngateway:/etc/openvpn$ head destinations/belgium_udp.ovpn -n4
script-security 2
up /etc/openvpn/linkup.sh
down /etc/openvpn/linkdown.sh
down-pre

My scripts are up...

mci@vpngateway:/etc/openvpn$ cat linkup.sh 
#!/bin/bash

# First let systemd-resolved do its magic
/etc/openvpn/update-systemd-resolved $@

# Set iptable rules
/etc/openvpn/iptables_baserules.sh

# Set DNS
/etc/openvpn/iptables_setdns.sh

and down

mci@vpngateway:/etc/openvpn$ cat linkdown.sh 
#!/bin/bash

# First delete DNS iptables rules
/etc/openvpn/iptables_removedns.sh

# After let systemd-resolved do its magic
/etc/openvpn/update-systemd-resolved $@

basic rules to mostly drop other things

mci@vpngateway:/etc/openvpn$ cat iptables_baserules.sh 
#!/bin/bash

# Flush
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X

# Block All
iptables -P OUTPUT DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP

# allow Localhost
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

iptables -A INPUT -p udp --sport 53 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

# Make sure you can communicate with any DHCP server
iptables -A OUTPUT -d 255.255.255.255 -j ACCEPT
iptables -A INPUT -s 255.255.255.255 -j ACCEPT

# Make sure that you can communicate within your own network
iptables -A INPUT -s x.x.x.0/24 -d x.x.x.0/24 -j ACCEPT
iptables -A OUTPUT -s x.x.x.0/24 -d x.x.x.0/24 -j ACCEPT

# Allow established sessions to receive traffic:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow TUN
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A OUTPUT -o tun0 -j ACCEPT

# allow VPN connection
iptables -I OUTPUT 1 -p udp --destination-port 1195 -m comment --comment "Allow VPN connection" -j ACCEPT
iptables -I OUTPUT 1 -p tcp --destination-port 1195 -m comment --comment "Allow VPN connection" -j ACCEPT

# Block All
iptables -A OUTPUT -j DROP
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP

note these rules, I had to add them so the node itself could lookup a name after the vpn connection got closed (maybe because I'ld like to switch the vpn config to another server).

iptables -A INPUT -p udp --sport 53 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

Last thing is to dynamicaly add the DNS nat

mci@vpngateway:/etc/openvpn$ cat iptables_setdns.sh 
#!/bin/bash

# Route DNS Traffic
# Get DNS from VPN
dns=$(resolvectl dns -i tun0)
dns=${dns##* }
echo "Found DNS on tun0: ${dns}"
iptables -t nat -A PREROUTING -p tcp --dst x.x.x.x --dport 53 -j DNAT --to-destination ${dns}:53
iptables -t nat -A PREROUTING -p udp --dst x.x.x.x --dport 53 -j DNAT --to-destination ${dns}:53

and remove it afterwards

mci@vpngateway:/etc/openvpn$ cat iptables_removedns.sh 
#!/bin/bash

# Route DNS Traffic
# Get DNS from VPN
dns=$(resolvectl dns -i tun0)
dns=${dns##* }
echo "Found DNS on tun0: ${dns}"
iptables -t nat -D PREROUTING -p tcp --dst x.x.x.x --dport 53 -j DNAT --to-destination ${dns}:53
iptables -t nat -D PREROUTING -p udp --dst x.x.x.x --dport 53 -j DNAT --to-destination ${dns}:53

Maybe this will help somebody else who is building a vpn gateway.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .