add initial 3 lessons
This commit is contained in:
+285
@@ -0,0 +1,285 @@
|
||||
# Raspberry Pi VPN (Networking)
|
||||
|
||||
In this lesson you'll build a personal VPN server on your Raspberry Pi using
|
||||
**WireGuard** — the modern standard for VPNs. It gives you a private road into
|
||||
your home network: when you're at school, at a friend's house, or on vacation,
|
||||
you can reach devices on your home Wi-Fi — the Pi, a NAS, a media server, a smart
|
||||
home dashboard — as if your phone were plugged into the house.
|
||||
|
||||
As a side effect, the road is encrypted, so nobody in between can read what
|
||||
you're accessing.
|
||||
|
||||
## How it works
|
||||
|
||||
A quick networking refresher so the steps make sense:
|
||||
|
||||
- Devices on your home network get **local** IP addresses like
|
||||
`192.168.1.42`. To the internet, your whole house appears as **one** public IP
|
||||
address (the router's).
|
||||
- By default the internet can only knock on the front door — the router. To reach
|
||||
devices *inside* the house, we set up one exception: the Pi runs a VPN server,
|
||||
and the router forwards that one port to it.
|
||||
- A VPN creates an **encrypted tunnel** between your phone and the Pi. Inside the
|
||||
tunnel we use our own private addresses: the Pi is `10.100.0.1`, your phone is
|
||||
`10.100.0.2`.
|
||||
- When you connect, your phone has two identities at once: it's on your carrier's
|
||||
network *and* on your home network. Anything in your home range
|
||||
(`192.168.1.x`) travels through the tunnel into the house.
|
||||
|
||||
```
|
||||
phone --encrypted tunnel--> Pi --home network--> NAS, Pi, media server, ...
|
||||
```
|
||||
|
||||
**Check your own network first:** find your Pi's local IP on the Pi with
|
||||
`hostname -I`. This lesson assumes it looks like `192.168.1.42`, so the home
|
||||
range is `192.168.1.0/24`. If your router uses a different range (some use
|
||||
`192.168.0.x` or `10.0.0.x`), substitute yours everywhere.
|
||||
|
||||
## What you need
|
||||
|
||||
- A Raspberry Pi running Raspberry Pi OS, connected to your home network (wired
|
||||
ethernet is best and easiest)
|
||||
- Your phone, with the official **WireGuard** app (iOS or Android)
|
||||
- Access to your router's admin page (usually `192.168.1.1` in a browser)
|
||||
|
||||
## Step 1 — Install WireGuard on the Pi
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install -y wireguard wireguard-tools nftables qrencode
|
||||
```
|
||||
|
||||
(`qrencode` prints a scannable QR code; `nftables` handles the forwarding rules
|
||||
later.)
|
||||
|
||||
## Step 2 — Create the server's keys
|
||||
|
||||
Every WireGuard device has a **private key** (a secret) and a **public key**
|
||||
(safe to share). Think of them like a password and a public address. The Pi gets
|
||||
its pair now:
|
||||
|
||||
```
|
||||
sudo -i
|
||||
cd /etc/wireguard
|
||||
umask 077
|
||||
wg genkey | tee server.key | wg pubkey > server.pub
|
||||
cat server.key
|
||||
```
|
||||
|
||||
- `sudo -i` logs you in as the administrator account (root). Type `exit` at the
|
||||
end of each root session to go back to your normal user.
|
||||
- `umask 077` makes sure new files are only readable by you.
|
||||
- Copy the long string from `cat server.key` — you'll paste it into the config in
|
||||
the next step. **Never share your private key.** The public key (`server.pub`)
|
||||
is fine to share.
|
||||
|
||||
## Step 3 — Write the server config
|
||||
|
||||
Still as root, open the config file:
|
||||
|
||||
```
|
||||
nano /etc/wireguard/wg0.conf
|
||||
```
|
||||
|
||||
Type this, replacing the last line with your server's private key:
|
||||
|
||||
```
|
||||
[Interface]
|
||||
Address = 10.100.0.1/24, fd08:4711::1/64
|
||||
ListenPort = 47111
|
||||
PrivateKey = PASTE_YOUR_SERVER_PRIVATE_KEY_HERE
|
||||
```
|
||||
|
||||
Save (`Ctrl+O`, `Enter`) and quit (`Ctrl+X`). What the lines mean:
|
||||
|
||||
- `Address` — the Pi's address inside the tunnel (`10.100.0.1`).
|
||||
- `ListenPort` — the port clients connect to. `47111`, UDP.
|
||||
|
||||
## Step 4 — Let the Pi forward traffic
|
||||
|
||||
To send your phone's traffic on to other devices in the house, the Pi has to be
|
||||
willing to pass packets through. Two things enable that: **IP forwarding**
|
||||
(allow packets through) and **NAT** (let tunnel devices share the Pi's internet
|
||||
connection — you'll want it if you ever tunnel more than just home access).
|
||||
|
||||
First, edit `/etc/sysctl.d/99-sysctl.conf` (`nano /etc/sysctl.d/99-sysctl.conf`).
|
||||
Make sure these two lines exist **without** a `#` in front of them (remove the `#`
|
||||
if there is one):
|
||||
|
||||
```
|
||||
net.ipv4.ip_forward = 1
|
||||
net.ipv6.conf.all.forwarding = 1
|
||||
```
|
||||
|
||||
Save and quit, then apply:
|
||||
|
||||
```
|
||||
sysctl --system
|
||||
```
|
||||
|
||||
Second, open the server config again (`nano /etc/wireguard/wg0.conf`) and add
|
||||
these two lines inside the `[Interface]` section (paste them exactly as one line
|
||||
each):
|
||||
|
||||
```
|
||||
PostUp = nft add table ip wireguard; nft add chain ip wireguard wireguard_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip wireguard wireguard_chain counter packets 0 bytes 0 masquerade; nft add table ip6 wireguard; nft add chain ip6 wireguard wireguard_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip6 wireguard wireguard_chain counter packets 0 bytes 0 masquerade
|
||||
PostDown = nft delete table ip wireguard; nft delete table ip6 wireguard
|
||||
```
|
||||
|
||||
`PostUp`/`PostDown` are commands that run automatically when the tunnel starts and
|
||||
stops — here they add and remove the NAT rule. Ugly-looking, but it's copy-paste
|
||||
and it's what the official docs recommend.
|
||||
|
||||
When you're done, type `exit` to leave root.
|
||||
|
||||
## Step 5 — Start the VPN
|
||||
|
||||
```
|
||||
sudo systemctl enable wg-quick@wg0
|
||||
sudo systemctl start wg-quick@wg0
|
||||
sudo wg
|
||||
```
|
||||
|
||||
If `sudo wg` prints an interface called `wg0` with a public key and a listening
|
||||
port, the server is up. `enable` makes it start automatically after every reboot,
|
||||
so you only ever run the `start` command after changing the config.
|
||||
|
||||
## Step 6 — Open a door in the router
|
||||
|
||||
Your phone needs to reach the Pi through the internet. Two things in your router's
|
||||
admin page:
|
||||
|
||||
1. **Give the Pi a fixed local IP.** Find the current one on the Pi with
|
||||
`hostname -I`, then add a **DHCP reservation** in the router (binds that IP to
|
||||
the Pi's MAC address). If the Pi's IP ever changes, the port forward breaks.
|
||||
2. **Add a port forward: UDP port `47111` → the Pi's local IP.**
|
||||
|
||||
Also find your home's **public IP** — it's often shown on the router's front page
|
||||
("WAN IP"), or open `https://ifconfig.co` on any device at home. You'll paste it
|
||||
into the client config next.
|
||||
|
||||
## Step 7 — Add your phone as a client
|
||||
|
||||
WireGuard calls every connected device a **peer**. Back on the Pi:
|
||||
|
||||
```
|
||||
sudo -i
|
||||
cd /etc/wireguard
|
||||
umask 077
|
||||
name=phone
|
||||
wg genkey | tee ${name}.key | wg pubkey > ${name}.pub
|
||||
wg genpsk > ${name}.psk
|
||||
```
|
||||
|
||||
That created the phone's key pair plus a **preshared key** (an extra per-device
|
||||
layer of encryption).
|
||||
|
||||
Register the phone in the server config — this appends a `[Peer]` section to
|
||||
`wg0.conf`:
|
||||
|
||||
```
|
||||
echo "[Peer]" >> wg0.conf
|
||||
echo "PublicKey = $(cat ${name}.pub)" >> wg0.conf
|
||||
echo "PresharedKey = $(cat ${name}.psk)" >> wg0.conf
|
||||
echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> wg0.conf
|
||||
```
|
||||
|
||||
Then tell the running server about the change (this reloads the config without
|
||||
kicking off connected clients):
|
||||
|
||||
```
|
||||
wg syncconf wg0 <(wg-quick strip wg0)
|
||||
```
|
||||
|
||||
Now build the config file the phone will use:
|
||||
|
||||
```
|
||||
echo "[Interface]" > ${name}.conf
|
||||
echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> ${name}.conf
|
||||
echo "PrivateKey = $(cat ${name}.key)" >> ${name}.conf
|
||||
echo "" >> ${name}.conf
|
||||
echo "[Peer]" >> ${name}.conf
|
||||
echo "PublicKey = $(cat server.pub)" >> ${name}.conf
|
||||
echo "PresharedKey = $(cat ${name}.psk)" >> ${name}.conf
|
||||
echo "Endpoint = 203.0.113.10:47111" >> ${name}.conf
|
||||
echo "AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.1.0/24" >> ${name}.conf
|
||||
echo "PersistentKeepalive = 25" >> ${name}.conf
|
||||
```
|
||||
|
||||
Replace `203.0.113.10` with **your home's public IP**, and `192.168.1.0/24` with
|
||||
**your home range** if it's different. What the important lines do:
|
||||
|
||||
- `AllowedIPs` decides what travels through the tunnel. Here it's the tunnel
|
||||
itself plus your whole home range — so home devices are reachable. Everything
|
||||
else (normal web browsing, apps) goes over your carrier's network directly,
|
||||
exactly as usual.
|
||||
(If you ever want *everything* tunneled — e.g. to route it through a future
|
||||
Pi-hole — you'd replace that line with `AllowedIPs = 0.0.0.0/0, ::/0`.)
|
||||
- `PersistentKeepalive = 25` — phones sit behind carriers' NAT, so this sends a
|
||||
small packet every 25 seconds to keep the tunnel's door open.
|
||||
|
||||
## Step 8 — Connect your phone
|
||||
|
||||
Still as root, print the config as a QR code:
|
||||
|
||||
```
|
||||
qrencode -t ansiutf8 < ${name}.conf
|
||||
```
|
||||
|
||||
On your phone: open the WireGuard app → tap the blue **+** → scan the QR code →
|
||||
toggle the tunnel **on**. (If you're using the Pi over SSH from a laptop, the QR
|
||||
code appears in your terminal window — just scan it with the phone.) Then `exit`
|
||||
root.
|
||||
|
||||
## Step 9 — Check it works
|
||||
|
||||
The interesting test is from **outside** the house: turn your phone's Wi-Fi off
|
||||
and use cellular data.
|
||||
|
||||
1. On the Pi, run `sudo wg`. Your phone should appear with
|
||||
`latest handshake: X seconds ago` and a transfer count.
|
||||
2. Open your Pi's local address in your phone's browser —
|
||||
`http://192.168.1.42` or `http://192.168.1.42/admin` (use your Pi's own local
|
||||
IP). If the page loads from a school Wi-Fi network, your phone is effectively
|
||||
sitting in your house.
|
||||
3. Try SSH: `ssh YOUR_USER@192.168.1.42` from Termux (Android) or any SSH client
|
||||
on iPhone. If you get a shell, remote access is fully working.
|
||||
|
||||
## What you can do now
|
||||
|
||||
Rule of thumb: anywhere you would have typed a `192.168.1.x` address while at
|
||||
home, that same address now works from anywhere in the world.
|
||||
|
||||
- Web interfaces: Pi-hole admin, your NAS, Home Assistant — open them in the
|
||||
browser.
|
||||
- SSH into any device in the house.
|
||||
- Stream from a media server or download files from a NAS.
|
||||
|
||||
One caveat: device **names** like `raspberrypi.local` only resolve *inside* the
|
||||
house, so over the tunnel, use IP addresses.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Phone never shows a handshake:** check the port forward is UDP (not TCP) on
|
||||
port `47111` pointing at the Pi's current local IP; check the `Endpoint` line
|
||||
has your *current* public IP (it can change — call your ISP for a static one if
|
||||
it's changing often); check keys were copied without extra spaces.
|
||||
- **Can't connect from home Wi-Fi, but cellular works:** common and often
|
||||
unfixable — many routers can't loop a forwarded port back to devices already
|
||||
inside the network (no "NAT loopback"). Test with cellular data.
|
||||
- **Connected, but home devices are unreachable:** the `AllowedIPs` line in the
|
||||
client config has the wrong home range — it must match your router's subnet,
|
||||
the same range your Pi's IP lives in. Also make sure Step 4 (IP forwarding) is
|
||||
done.
|
||||
- **A device works at home but not over the tunnel:** use its IP address instead
|
||||
of its name (see the caveat above), and double-check the device is actually on
|
||||
your home network.
|
||||
|
||||
## Security notes
|
||||
|
||||
- Anyone with your phone's config file can walk into your home network. Treat it
|
||||
like a password — don't screenshot it into a shared chat.
|
||||
- Your Pi is now reachable from the internet. Keeping a firewall enabled (for
|
||||
example with `ufw`) is a good next step.
|
||||
- Lost a device? Delete its `[Peer]` section from `wg0.conf` and run
|
||||
`wg syncconf wg0 <(wg-quick strip wg0)` again — its keys stop working.
|
||||
Reference in New Issue
Block a user