Given the following interfaces on a Raspberry Pi:
- eth0 (192.168.0.0/24) - Private network (i.e. NAT)
- wlan0 (192.168.10.0/24) - Public network with Internet access (i.e. LAN)
- tun0 (VPN) - VPN connection
Build a firewall that achieves the following:
- Deny ALL inbound traffic to:
tun0(block incoming connections)
- Route ALL outbound traffic from
tun0(block "lateral" connections; i.e. no LAN access)
tun0is down, DO NOT allow
wlan0instead (i.e. VPN killswitch)
I've seen numerous "VPN killswitch" examples at this point with UFW and they all share a common configuration:
# Defaults ufw default deny outgoing ufw default deny incoming # Allow local over ethernet (without VPN) sudo ufw allow out to 192.168.0.0/24 # Allow out to LAN sudo ufw allow in to 192.168.0.0/24 # Allow in to LAN # Allow outgoing over ethernet to VPN sudo ufw allow out to [VPN] port 1194 proto udp # Allow outgoing over tun0 sudo ufw allow out on tun0 # Allow out over VPN
My NAT Example (Alternative)
Granted, in my application, I have an intermediate device (Raspberry Pi) in play that acts as a router, firewall, DNS & DHCP server, and VPN client so it is a slightly different setup. However, it would seem that the NAT table (
/etc/ufw/before.rules) handles the
ufw allow out/in to 192.168.0.0/24 statements and pretty much routes all outbound traffic coming from
tun0 (second objective item) as-is:
# NAT table to "forward" private network to VPN tunnel *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 192.168.0.0/24 -o tun0 -j MASQUERADE COMMIT
This should "forward" anything coming from the private network (
eth0) into the VPN tunnel (
tun0), correct? Or do I need
FORWARD clauses in here as well?
After that, I'm not sure at this point if there is anything else I would need to configure, such as:
# Set defaults (also see /etc/default/ufw) sudo ufw default deny incoming sudo ufw default deny outgoing # Allow incoming requests to DNS/DHCP services (UDP) on eth0 interface only (i.e. Private Network -> Pi:43,67/udp) sudo ufw allow in on eth0 from any to any port 53,67 proto udp # Allow incoming requests to SSH service (TCP) on eth0 interface only (i.e. Private Network -> Pi:22/tcp) sudo ufw allow in on eth0 from any to any port 22 proto tcp # Allow outbound on wlan0 interface for VPN traffic only (i.e. Pi -> LAN:1194) sudo ufw allow out on wlan0 from any to any port 1194 proto udp # Allow all outbound traffic on eth0 (i.e. Pi -> Private Network) sudo ufw allow out on eth0 # Allow all outbound traffic on VPN tunnel only (i.e. Pi -> VPN) sudo ufw allow out on tun0
In the tests I've done (
ping, etc.) with the NAT table alone, I can see my outbound Internet connection stops at the Raspberry Pi when I disconnect the VPN. However, what I'm still trying to confirm is whether this covers all possible leak scenarios (i.e. DNS, etc.).
Note: I am also using
dnsmasq so the Raspberry Pi is also the DNS server issued by the DHCP server to clients on the private network. I wonder if all I need to do is either configure
dnsmasq to forward DNS queries through
tun0 only (if that's even possible), or settle for forwarding onto public DNS instead (i.e. 22.214.171.124, 126.96.36.199). Also, as of right now, this setup blocks my outbound connections still, but issuing a
sudo ufw allow out on wlan0 restores that connection (with VPN killswitch still in effect). So I feel like I'm close and maybe just a couple more rules off.
Would greatly appreciate someone taking the time to look over these details and provide their feedback!