Build a Raspberry Pi dual-WiFi VPN router with WireGuard to use with Apple TV
Contents #
- Why someone might want to do this
- Minimum requirements
- Install Raspberry Pi OS on the SD card using Raspberry Pi imager
- Install drivers for the second WiFi interface
- Install RaspAP
- Install your WireGuard config
- Connect the Apple TV
1. Why someone might want to do this #
I want to use an Apple TV behind a WireGuard VPN. My home networking uses a mesh WiFi system to cover the house adequately, so a wired ethernet solution is out of the question. I also don’t want to spend a lot of money on new hardware. As I had an extra Raspberry Pi 4 on hand, I thought I’d try configuring that as a VPN router.
I could have the Pi provide connectivity to the Apple TV with an ethernet cable, but I also have a HomePod Mini I want to use as a speaker for the Apple TV. That leaves me with WiFi as the only option.
As I set out to build this system, I had to crab bits and pieces from different blog posts and forums. Now that I’ve done it, I wanted to write up the full set of instructions and have all the information in one place.
While you should be able to follow along with these commands relatively easily, this guide does assume basic familiarity with the Linux CLI environment, for example with editing files and restarting services.
2. Minimum requirements #
- Raspberry Pi 4
- SD card for the Pi
- Power supply for the Pi
- Dual-band USB WiFi adapter with 802.11ac
- A case for the Pi
- Another computer to use for configuring the Pi
3. Install Raspberry Pi OS on the SD card using Raspberry Pi imager #
Download Raspberry Pi imager to install Raspberry Pi OS onto your SD card. Follow the instructions in Raspberry Pi imager to select the operating system and SD card. Before you click “write,” click on the button with the gear icon to set up options like allowing SSH, the default user, and the details of your local WiFi network. Save the settings, click “write,” and wait for the imaging to complete.
Plug your newly flashed SD card into your Raspberry Pi and power it on. It should be all set up and connected to your network. Consult your router to learn the new ip address of your Pi. Mine showed up with an address of 192.168.7.183.
4. Install drivers for the second WiFi interface #
Log into the Pi using the username and password you added through Raspberry Pi imager:
ssh pi@192.168.7.183
Before plugging in the second WiFi adapter, you need to update the system and install additional software and drivers.
First, make sure the system is up to date:
sudo apt update && sudo apt upgrade -y
Now install necessary packages and software to enable building the WiFi driver from source:
sudo apt install -y raspberrypi-kernel-headers bc build-essential dkms git
Reboot the Pi to start using the new headers and updated software:
sudo reboot now
Log back in and download the source for the WiFi driver:
mkdir -p ~/src
cd ~/src
git clone https://github.com/morrownr/8821cu-20210118.git
Change into the directory:
cd ~/src/8821cu-20210118
Configure the Makefile to make it suitable for the Pi. If your Pi is 32 bit:
./ARM_RPI.sh
Or if your Pi is 64 bit:
./ARM64_RPI.sh
Install the driver and reboot:
sudo ./install-driver.sh NoPrompt && sudo reboot now
Plug in the AC WiFi adapter and log back in. Check to see that both WiFi interfaces are active:
ip addr show
You should now see two wireless interfaces. wlan0
is the internal WiFi, and wlan1
should be the new WiFi adapter.
5. Install RaspAP #
RaspAP gets you up and running with “feature-rich wireless router software that just works.”
RaspAP’s full install instructions are available here, but if you’re comfortable with it you can invoke the quick installer:
curl -sL https://install.raspap.com | bash
I accepted the defaults and answered “yes” to the questions the installer asks, among them where to save the default directory for the lighttpd web server, whether to install ad blocking, and whether to install OpenVPN and WireGuard. For the purposes of this tutorial, the only one you’re required to say yes to is installing WireGuard.
When the installation script has finished, reboot the Pi:
sudo reboot now
When the Pi comes back online, it will now be broadcasting a WiFi network with the SSID of raspi-webgui
. By default, it uses the internal WiFi, or wlan0
, to broadcast this network. As such, it will no longer be available at the address you’ve been using to log in. It will still be available from the address assigned to wlan1
, which in my case is 192.168.7.184.
As noted in the RaspAP quick-start documentation, here are the default settings for the new WiFi network:
Following a reboot, the wireless AP network will be configured as follows:
IP address: 10.3.141.1
Username: admin
Password: secret
DHCP range: 10.3.141.50 — 10.3.141.255
SSID: raspi-webgui
Password: ChangeMe
For now, connect to the new raspi-webgui
WiFi network from your computer, open a web browser, and access the admin panel for RaspAP.
First, some housekeeping. To change the admin password, click on “Authentication” from the left menu, provide the old password, enter a new one, and click “Save settings.”
Next, we’ll change the WiFi network settings. Click on “Hotspot” in the left menu, change the SSID to a name you prefer, and select the faster Wireless Mode of 802.11n - 2.4 GHz
. Click “Save settings.”
Now click on the “Security” tab and change the pre-shared key (PSK) from ChangeMe
to something you prefer. Click “Save settings” again, and then click “Restart hotspot.”
You’ll need to reconnect to the network using the new SSID and password.
At this point, you probably won’t have a working internet connection through the Pi. RaspAP works great out of the box assuming a wired ethernet connection is providing access to the internet. But with a dual-WiFi system, further configuration is necessary. I gather much of what follows can be done via the admin interface, but for me it was more straightforward to make the changes via the command line.
The WiFi settings are all set, but now we need to enable forwarding of traffic on the network interfaces and configure wlan1
as a gateway.
Log into the Pi from the terminal. While connected to the Pi’s WiFi network, use the new login:
ssh pi@10.3.141.1
Enable forwarding of traffic on IPv4 and IPv6:
sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sudo sed -i 's/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/g' /etc/sysctl.conf
Modify /etc/dhcpcd.conf
to add a gateway rule for wlan1
and lower precedence through a higher metric for wlan0
:
# RaspAP default configuration
hostname
clientid
persistent
option rapid_commit
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
option ntp_servers
require dhcp_server_identifier
slaac private
nohook lookup-hostname
interface wlan1
gateway
# RaspAP wlan0 configuration
interface wlan0
static ip_address=10.3.141.1/24
static routers=10.3.141.1
static domain_name_server=9.9.9.9 1.1.1.1
metric 500
In my testing, this step was the most important to getting dual-WiFI working with RaspAP while using wlan0
as the access point and wlan1
as the gateway.
Restart the hostapd
daemon and the WiFi broadcast by the Pi:
sudo systemctl restart hostapd.service
When the WiFi network comes back online, you should have a working internet connection.
6. Install your WireGuard config #
The Pi is all ready to be a VPN router. Open the RaspAP web interface and click on the “WireGuard” link from the left menu. Obtain a WireGuard configuration from your VPN provider. I’ve been happy with ProtonVPN, but any service that offers WireGuard configurations should be fine.
Upload the configuration to RaspAP. Toggle the option for “Apply iptables rules for AP interface” to be active. This setting will ensure that firewall rules for forwarding all traffic are created when the WireGuard connection is initiated and then destroyed when the connection is stopped by adding the following declarations:
PostUp = iptables -A FORWARD -i wlan0 -o wg0 -j ACCEPT; iptables -A FORWARD -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE; iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -D FORWARD -i wlan0 -o wg0 -j ACCEPT; iptables -D FORWARD -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE; iptables -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Without this option, your traffic probably won’t flow correctly through your router and VPN.
Click “Save settings,” and then click “Start WireGuard.”
All your traffic should now be going over the VPN connection. You can use curl ifconfig.me
either from the Pi or your local computer command line to check to see if your outgoing IP address has changed to match the VPN.
7. Connect the Apple TV #
If you’re using your new Pi VPN router with an Apple TV, all that remains is to open the Apple TV network settings and connect to the new WiFi network. Likewise, if you have one, connect a HomePod Mini to the new network just as you’d connect it to any other network.