User Tools

Site Tools


vpn-rpi4

This is an old revision of the document!


ExpressVPN Access Point using a Raspberry Pi 4

  • Hardware: Raspberry Pi 4, model B
  • OS: Raspbian GNU/Linux 10 (buster)
  • Network:
    • eth0 (wired) connected to home network:
      • CIDR: 192.168.167.0/24
      • Gateway / router: 192.168.167.1

Desired outcome

  • Raspberry Pi 4 acting as WiFi access point
  • Provides own DHCP service, so it can nominate …
  • … itself as gateway
  • … itself as DNS server
  • Provides internet access to WiFi client stations …
  • … via ExpressVPN when that's connected
  • … via home network when it is now

Setup

Create the following in /etc/network/interfaces.d/ as root:

eth0:

auto eth0
iface eth0 inet manual

wlan0:

auto wlan0
iface wlan0 inet manual
  nohook wpa_supplicant	# Conflicts with running in Access Point mode

br0:

auto br0
iface br0 inet static
  address 192.168.167.48
  gateway 192.168.167.1
  bridge_ports eth0 wlan0

  # Ethernet Bridging: Block DHCP from our WiFi stations going out over our
  # wired connection (we want to be the ones to answer DHCP requests, not our
  # ISP)
  up   ebtables -t filter -A FORWARD --protocol 0x0800 --ip-protocol UDP --ip-destination-port 67 -j DROP
  down ebtables -t filter -D FORWARD --protocol 0x0800 --ip-protocol UDP --ip-destination-port 67 -j DROP

  # Internet Protocol Network Address Translation when using this bridge, and
  # any ExpressVPN tun0 which come and go with VPN connections
  up   iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
  up   iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
  down iptables -t nat -D POSTROUTING -o br0 -j MASQUERADE
  down iptables -t nat -D POSTROUTING -o tun0 -j MASQUERADE

Then run:

sudo apt remove openresolv
sudo apt install dnsmasq hostapd

Remove /etc/resolv.conf if it is a symbolic link, and recreate as a regular file:

nameserver 1.0.0.1
nameserver 8.8.4.4
nameserver 1.1.1.1
nameserver 8.8.8.8

Modify /etc/dnsmasq.conf:

dhcp-range=192.168.167.40,192.168.167.47,1h
dhcp-authoritative
clear-on-reload
bridge-interface=br0,wlan0

Restart dnsmasq service to pick up changes:

sudo systemctl restart dnsmasq

Modify /etc/default/hostapd and change value of DAEMON_CONF:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

Create /etc/hostapd/hostapd.conf:

ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
auth_algs=1
beacon_int=100

ssid=teleport
wpa_passphrase=CHANGEME

country_code=US

interface=wlan0
bridge=br0
driver=nl80211

wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

macaddr_acl=0

logger_syslog=0
logger_syslog_level=4
logger_stdout=-1
logger_stdout_level=0

hw_mode=a
wmm_enabled=1

# N
ieee80211n=1
require_ht=1
ht_capab=[MAX-AMSDU-3839][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]

# AC
ieee80211ac=1
require_vht=1
ieee80211d=0
ieee80211h=0
vht_capab=[MAX-AMSDU-3839][SHORT-GI-80]
vht_oper_chwidth=1
channel=36
vht_oper_centr_freq_seg0_idx=42

ignore_broadcast_ssid=0

Restart service hostapd to pick up changes:

sudo systemctl restart hostapd

Now apply network changes, and disable DHCP client daemon since we don't want our bridge's slave interfaces getting ideas above their station.

systemctl disable --now dhcpcd systemd-resolved
ifdown --verbose --all
ifup   --verbose --all

Debugging

pi@raspberrypi4:~ $ ip -br link
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0             UP             dc:a6:32:20:f7:7d <BROADCAST,MULTICAST,UP,LOWER_UP>
wlan0            UP             dc:a6:32:20:f7:7e <BROADCAST,MULTICAST,UP,LOWER_UP>
br0              UP             dc:a6:32:20:f7:7d <BROADCAST,MULTICAST,UP,LOWER_UP>


pi@raspberrypi4:~ $ ip -br addr
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP
wlan0            UP
br0              UP             192.168.167.48/24 fe80::dea6:32ff:fe20:f77d/64


pi@raspberrypi4:~ $ sudo iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  386 25981 MASQUERADE  all  --  *      br0     0.0.0.0/0            0.0.0.0/0
    0     0 MASQUERADE  all  --  *      tun0    0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination


pi@raspberrypi4:~ $ sudo ebtables -L
Bridge table: filter

Bridge chain: INPUT, entries: 0, policy: ACCEPT

Bridge chain: FORWARD, entries: 1, policy: ACCEPT
-p 0x800 --ip-proto udp --ip-dport 67 -j DROP

Bridge chain: OUTPUT, entries: 0, policy: ACCEPT


pi@raspberrypi4:~ $ ip route
default via 192.168.167.1 dev br0 onlink
192.168.167.0/24 dev br0 proto kernel scope link src 192.168.167.48


pi@raspberrypi4:~ $ journalctl -u hostapd
-- Logs begin at Wed 2020-04-29 22:45:20 BST, end at Wed 2020-04-29 22:47:25 BST. --
Apr 29 22:45:56 raspberrypi4 systemd[1]: Starting Advanced IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator...
Apr 29 22:45:56 raspberrypi4 hostapd[710]: Configuration file: /etc/hostapd/hostapd.conf
Apr 29 22:45:56 raspberrypi4 hostapd[710]: wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
Apr 29 22:45:56 raspberrypi4 systemd[1]: Started Advanced IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator.


pi@raspberrypi4:~ $ journalctl -u dnsmasq
-- Logs begin at Wed 2020-04-29 22:45:20 BST, end at Wed 2020-04-29 22:47:25 BST. --
Apr 29 22:45:56 raspberrypi4 systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server...
Apr 29 22:45:56 raspberrypi4 dnsmasq[711]: dnsmasq: syntax check OK.
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: started, version 2.80 cachesize 150
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: DNS service limited to local subnets
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify dumpfile
Apr 29 22:45:56 raspberrypi4 dnsmasq-dhcp[751]: DHCP, IP range 192.168.167.40 -- 192.168.167.47, lease time 1h
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: reading /etc/resolv.conf
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: using nameserver 10.89.0.1#53
Apr 29 22:45:56 raspberrypi4 dnsmasq[751]: read /etc/hosts - 5 addresses
Apr 29 22:45:56 raspberrypi4 systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.
Apr 29 22:46:16 raspberrypi4 dnsmasq-dhcp[751]: DHCPREQUEST(br0) 192.168.167.44 8c:85:90:53:bd:55
Apr 29 22:46:16 raspberrypi4 dnsmasq-dhcp[751]: DHCPACK(br0) 192.168.167.44 8c:85:90:53:bd:55 Roberts-MBP
vpn-rpi4.1588197316.txt.gz · Last modified: 2020/04/29 21:55 by robm