Public Access Hotspot using VPN

What I want to do is make a public hotspot, but I don't want a bunch of randos doing sketchy stuff on my main internet connection. So, I'd like to get a VPN subscription, from NordVPN, ExpressVPN etc.. and set that up as an OpenVPN profile on the Wrt router, create an AP and separate subnet for the hotspot and route all of that through the VPN connection. This will result in a double NAT, one at Wrt and the other at the VPN provider, but that's okay. I need this to be totally detached from my main wan and lan. So far I'm been unsuccessful in getting this to work.

I made an interface attached to wlan1-1 (the public AP) with a static IP of 10.100.1.1/24 and enabled DHCP. Connecting clients do get assigned an IP in that range and are given 10.100.1.1 as the default gateway/DNS.

What's stumping me is how I get that subnet to NAT from a different gateway. Bearing in mind the IP/Subnet and gateway from the VPN provider is not always the same so I cannot hard code it. I tried making a 'vpnwan' interface attached to tun0 as unmanaged and then creating the two firewall zones and forwarding rules but that gives clients "Destination port unavailable". I'm thinking I may need to use MWAN3 or something as it is technically a multiwan setup.

With unmanaged devices this would be easy. I'd shunt OpenVPN's route directives to a second routing table, use iptables to mark incoming packets on wlanx-x then use ip rule to redirect them to the second routing table. Just can't quite get my head around how to do this with the UCI stuff.

1 Like

Being not a friend of all this UCI stuff myself, I completely get rid of the standard firewall, just using plain iptables-rules.
And, when using OpenVPN, I am just setting up the minimum UCI stuff, and put everything into openvpn_client.conf.
Will need custom firmware to build, though.

1 Like

@vgaetera , that's the one. Perfect. I was so busy trying to do it from scratch I didn't think to look for an existing package. Cheers.

1 Like

I ended up not using that package after all; and went with unmanaged solution instead using a route-up script in OpenVPN.

#!/bin/sh

## Lan/Wlan Interface we wish to redirect to the VPN
LAN="wlan1"

## Interface of the VPN
VPN="$dev"

## Generate a table number unique to the VPN adapter name
## Note: If you are redirecting more than one VPN connection
## Do not mix tun and tap if possible, if you do; make sure the
## device numbers of each are different from each other
TABLE=$(expr 100 + ${VPN//[!0-9]/})

## Comment used in iptables rules so they can be filtered
COMMENT="$VPN-$TABLE-rule-identifier"

## delete old ip rules if they exist.
while ip rule del lookup $TABLE 2>/dev/null; do true; done

## Clear out the VPN routing table of old routes
ip route flush table $TABLE 2>/dev/null

## Add rules to redirect interfaces to VPN routing table
ip rule add iif $VPN lookup $TABLE
ip rule add iif $LAN lookup $TABLE

## Get the link route of the interface we wish to redirect
SN=$(ip route list dev $LAN | grep link | head -1 | awk '{print $1}')
## Add it to the VPN routing table
ip route add $SN dev $LAN table $TABLE

## Get the link route of the VPN interface
SN=$(ip route list dev $VPN | grep link | head -1 | awk '{print $1}')
## Add it to the VPN routing table
ip route add $SN dev $VPN table $TABLE

## Get the gateway of the VPN that has been added to the main routing table
GW=$(ip route list dev $VPN | grep via | head -1 | awk '{print $3}')
## Add the gateway to the VPN routing table
ip route add default via $GW dev $VPN table $TABLE
## Remove VPN gateways added by OpenVPN from the main routing table
ip route list dev $VPN | grep via | sed 's/^/ip route del /' | sh
## Remove any IPv6 route entries added by OpenVPN
ip -6 route list dev $VPN | sed 's/^/ip -6 route del /' | sh

## Remove iptables rules left from older VPN connections
iptables-save | grep $COMMENT | grep POSTROUTING | cut -d' ' -f2- | sed 's/^/iptables -t nat -D /' | sh
iptables-save | grep $COMMENT | cut -d' ' -f2- | sed 's/^/iptables -D /' | sh
ip6tables-save | grep $COMMENT | cut -d' ' -f2- | sed 's/^/ip6tables -D /' | sh
## Allow forwarding between the LAN and VPN interfaces
iptables -I FORWARD -i $LAN -o $VPN -m comment --comment "$COMMENT" -j ACCEPT
iptables -I FORWARD -i $VPN -o $LAN -m comment --comment "$COMMENT" -j ACCEPT
## Enable NAT on the VPN interface
iptables -t nat -I POSTROUTING -o $VPN -m comment --comment "$COMMENT" -j MASQUERADE
## Block all output of LAN to this device to stop clients accessing LuCI, SSH etc..
iptables -I OUTPUT -o $LAN -m comment --comment "$COMMENT" -j DROP
## Allow UDP port 67:68 so clients can get DCHP service
iptables -I OUTPUT -o $LAN -p udp --dport 67:68 -m comment --comment "$COMMENT" -j ACCEPT
## Block forwarding to anything but the VPN interface from LAN
## to stop clients accessing other local subnets
iptables -I FORWARD -i $LAN ! -o $VPN -m comment --comment "$COMMENT" -j DROP
## Block all IPv6 on LAN
ip6tables -I OUTPUT -o $LAN -m comment --comment "$COMMENT" -j DROP
ip6tables -I FORWARD -i $LAN -m comment --comment "$COMMENT" -j DROP

You may find your DNS requests will give the game away.

The wlan1 interface pushes 8.8.8.8 and 8.8.4.4 to clients for DNS so their requests go through the VPN. Clients wouldn't be able to access local DNS anyway as they're blocked from doing so. Even if I allowed local DNS, I use recursive lookup with DNSSEC.

# network
config interface 'FREEWIFI'
        option proto 'static'
        option netmask '255.255.255.0'
        option ipaddr '10.100.1.1'
        option delegate '0'

# wireless        
config wifi-iface 'wifinet0'
        option device 'radio1'
        option mode 'ap'
        option network 'FREEWIFI'
        option isolate '1'
        option ssid 'Public Hotspot'

# dhcp
config dhcp 'FREEWIFI'
        option start '100'
        option leasetime '12h'
        option limit '150'
        option interface 'FREEWIFI'
        list dhcp_option '6,8.8.8.8,8.8.4.4'

I think I've covered everything, but stuff like this is complex. No doubt I'll find some potential risk somewhere. I still have bandwidth limiting to do as well. Might also be an idea to block common P2P tracker ports.

Itn looks good. You can use route-noexec in openvpn config so it will not add route to main table.

Yeah, I looked at that. But I don't trust OpenVPN to not change their environment variable names at some point and I read a few bug reports of EVs not being correctly set by OpenVPN sometimes. So I made the decision to not use them. I do use $dev to get the interface name and I'm debating removing that.

LOL, while browsing through the documentation I see this option for interfaces

ip4table | IPv4 routing table for routes of this interface. E.g., when proto = dhcp, the dhcp client will add routes to that table

That will teach me to read the docs properly beforehand. That option simplifies things greatly.

1 Like

Unfortunately netifd doesn't support the OpenVPN protocol.
Thus, PBR configuration requires to utilize hotplug or OpenVPN scripts.

The VPN-PBR app actually works quite well for me, specifically for OpenVPN.
It allows to achieve the required result with just a few lines of settings.

I think we're going to eventually go for separate devices. We can get used thin clients off e-bay for next to nothing. A high power RT2870 and panel antenna and we can bolt the whole thing together to one unit. The thin clients also have standard panel mounts which we have everywhere. Since the VPN provider allows multiple logins, we can have several and move them around to adjust coverage areas. Setup is also WAY easier (although still tricky to completely block free users from the rest of the network) as the device is now dedicated and not multi-use. We have one dead zone with no ethernet, so may need a dual radio device in there.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.