Disclaimer and Warning
The information provided in this article is for educational and informational purposes only. It is offered without any warranty—express or implied—regarding its accuracy, reliability, or fitness for a particular purpose.
You are solely responsible for any changes you make to your system. Misconfiguring firewall rules, DNS settings, or system services may lead to loss of internet access, broken services, or other unintended consequences.
Before proceeding:
- Back up your current configuration and any important data.
- Test changes cautiously, preferably on a non-critical system.
- Expect trial and error, especially if your system setup differs from the examples provided.
By using the instructions in this article, you agree that the author shall not be held liable for any damage, data loss, security breaches, or connectivity issues that may arise.
Proceed at your own risk.
In an era of mass surveillance and increasingly sophisticated tracking, using a VPN is no longer just for privacy advocates or hackers—it’s basic digital hygiene. But merely connecting to a VPN isn’t enough. A misconfigured system can still leak DNS requests or route sensitive traffic outside the encrypted tunnel. This guide will walk you through how to configure a leak-proof, DNS-hardened VPN setup on Ubuntu or Debian using UFW (Uncomplicated Firewall).
Objective
The aim is simple: force all internet traffic through the VPN and prevent even a single packet from escaping through your physical network interface when the VPN is disconnected. This requires:
- A strict firewall configuration (UFW)
- DNS leak prevention
- Disabling system services that override your settings
Step 1: Reset the Firewall
Before anything else, clean the slate.
bashCopyEditsudo ufw reset
sudo ufw default deny incoming
sudo ufw default deny outgoing
sudo ufw default deny routed
This ensures nothing moves in or out of your machine unless explicitly allowed.
Step 2: Allow Only VPN Traffic
Start by allowing only essential traffic.
bashCopyEdit# Allow loopback interface for internal services
on lo
sudo ufw allow in
sudo ufw allow out on lo# Allow outgoing traffic to VPN server (adjust port/protocol as needed)
sudo ufw allow out to any port 443 proto udp# Allow traffic only on the VPN interface
on tun0
sudo ufw allow in
sudo ufw allow out on tun0# Block outgoing traffic on your physical NIC (replace with your actual interface, e.g., enp2s0)
sudo ufw deny out on enp2s0# Enable the firewall
sudo ufw enable
Once this is in place, the system won’t connect to the internet unless the VPN is active.
Step 3: Confirm VPN Routing
Make sure your VPN is up and that the tun0
interface exists.
bashCopyEditip a show tun0
Now check if you're routing traffic through the VPN:
bashCopyEditcurl ifconfig.me
This IP should match your VPN, not your ISP.
Step 4: Prevent DNS Leaks
Leaking DNS queries can expose your activity, even if your traffic is tunneled. Let’s plug that hole.
bashCopyEdit# Check current DNS resolver
resolvectl status
If you see a local IP (like 192.168.0.1
), that's your router—and it shouldn't be there.
bashCopyEdit# Block local DNS entirely
sudo ufw deny out to 192.168.0.1 port 53# Allow DNS only via VPN
sudo ufw allow out on tun0 to 1.1.1.1 port 53
sudo ufw allow out on tun0 to 1.0.0.1 port 53
sudo ufw allow out on tun0 to any port 53
Step 5: Override systemd-resolved
Even with UFW set, systemd-resolved can override your DNS and break the setup. Kill it completely.
bashCopyEdit# Stop and disable the DNS resolver
--now systemd-resolved
sudo systemctl disable# Remove symlink and set your DNS manually
-f /etc/resolv.conf
sudo rmecho -e "nameserver 1.1.1.1\nnameserver 1.0.0.1" | sudo tee
/etc/resolv.conf# Make it immutable
sudo chattr +i /etc/resolv.conf# Restart network services
sudo systemctl restart NetworkManager
This locks DNS settings to Cloudflare and prevents changes by any automated service.
Step 6: Reboot and Test
Now reboot:
bashCopyEditsudo reboot
After rebooting, verify:
bashCopyEdit# Should show VPN IP
curl ifconfig.me# Should use Cloudflare or VPN DNS
nslookup google.com# Should not show router IP as DNS
resolvectl status
Conclusion
You now have a secure, airtight VPN setup:
- All traffic routed through
tun0
(VPN tunnel) - No fallback to your physical interface if the VPN drops
- DNS queries go only to trusted servers
- Even systemd can’t override your choices
In short: no leaks, no exceptions. Mission accomplished.
om tat sat
Member discussion: