0

Objective

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: wlan0, tun0 (block incoming connections)
  • Route ALL outbound traffic from eth0 to tun0 (block "lateral" connections; i.e. no LAN access)
    • If tun0 is down, DO NOT allow eth0 to use wlan0 instead (i.e. VPN killswitch)

Mainstream Example

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

Sources:

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 eth0 to 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 (traceroute, 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. 8.8.8.8, 8.8.4.4). 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!

0

So I think I'm going to leave this answer up as I believe I may have just figured out the missing piece (thanks to /var/log/ufw.log) unless someone else sees otherwise:

# Allow DNS queries
# [UFW BLOCK] IN= OUT=wlan0 SRC=192.168.10.x DST=192.168.10.1 LEN=66 TOS=0x00 PREC=0x00 TTL=64 ID=50892 DF PROTO=UDP SPT=22617 DPT=53 LEN=46 
sudo ufw allow out on wlan0 from any to any port 53 proto udp

So my current ruleset looks like this now (note the default outgoing):

Status: active
Logging: on (low)
Default: deny (incoming), deny (outgoing)
New profiles: skip

To                         Action      From
--                         ------      ----
53,67/udp on eth0          ALLOW IN    Anywhere
22/tcp on eth0             ALLOW IN    Anywhere

1194/udp                   ALLOW OUT   Anywhere on wlan0
Anywhere                   ALLOW OUT   Anywhere on eth0
Anywhere                   ALLOW OUT   Anywhere on tun0
53/udp                     ALLOW OUT   Anywhere on wlan0

Commands:

# 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 DNS and VPN traffic only (i.e. Pi -> LAN:1194)
sudo ufw allow out on wlan0 from any to any port 53,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

# Set defaults (also see /etc/default/ufw)
sudo ufw default deny incoming
sudo ufw default deny outgoing

This is also combined with my NAT table entry in /etc/ufw/before.rules mentioned in the original post for handling eth0 -> tun0 "routing."

And finally, my /etc/dnsmasq.conf contains the following single server entry:

# Force VPN by selecting public DNS
server=8.8.8.8

# Do not read from /etc/resolv.conf and friends for system DNS
no-resolv

# Do not poll /etc/resolv.conf and friends for system DNS
no-poll

Doing a traceroute confirms requests going out to 8.8.8.8 is over the VPN and by configuration (DHCP implied), the client will default to the Pi for its DNS which in turn uses this configuration.

That's a wrap!

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.