]> git.kreider.io Git - wiki.git/commitdiff
(no commit message)
authorrich <rich@web>
Sun, 29 Mar 2026 13:40:48 +0000 (09:40 -0400)
committerIkiWiki <ikiwiki.info>
Sun, 29 Mar 2026 13:40:48 +0000 (09:40 -0400)
notes/linux/wireguard.mdwn

index e25c2a6746295994d09f2aee57c990bf71134cdc..625872dea6ab832b5df55d2fbc41fe549a62401c 100644 (file)
@@ -1 +1,412 @@
-# Wireguard on Debian
+# WireGuard VPN Setup on Debian 13
+
+Clean, minimal, self-hosted WireGuard setup with:
+
+- Full tunnel support
+- NAT for internet access
+- Multi-user capability
+- Per-user access control via firewall
+
+---
+
+## 0. Assumptions
+
+- Public interface: `eth0`
+- VPN subnet: `10.10.10.0/24`
+- Server is publicly reachable
+
+Replace `eth0` with your real interface name if needed, such as `ens18`, `ens3`, or `enp1s0`.
+
+---
+
+## 1. Install WireGuard
+
+```
+apt update
+apt install wireguard
+```
+
+---
+
+## 2. Enable IP Forwarding
+
+```
+sysctl -w net.ipv4.ip_forward=1
+```
+
+Persist it:
+
+```
+echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
+sysctl -p
+```
+
+---
+
+## 3. Generate Keys
+
+```
+cd /etc/wireguard
+
+wg genkey | tee server.key | wg pubkey > server.pub
+wg genkey | tee client.key | wg pubkey > client.pub
+
+chmod 600 *.key
+```
+
+---
+
+## 4. Server Configuration
+
+Create:
+
+```
+nano /etc/wireguard/wg0.conf
+```
+
+```
+[Interface]
+Address = 10.10.10.1/24
+PrivateKey = <contents of server.key>
+ListenPort = 51820
+
+# NAT + forwarding
+PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
+PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
+
+PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
+PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
+PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
+
+[Peer]
+PublicKey = <contents of client.pub>
+AllowedIPs = 10.10.10.2/32
+```
+
+Notes:
+
+- `Address = 10.10.10.1/24` is the server's VPN IP.
+- `AllowedIPs = 10.10.10.2/32` means that client owns only `10.10.10.2`.
+- Do not reuse keys between devices.
+
+---
+
+## 5. Start WireGuard
+
+```
+wg-quick up wg0
+systemctl enable wg-quick@wg0
+```
+
+Check status:
+
+```
+wg show
+ip addr show wg0
+```
+
+---
+
+## 6. Client Configuration
+
+Use this on Windows, Linux, or macOS:
+
+```
+[Interface]
+Address = 10.10.10.2/24
+PrivateKey = <contents of client.key>
+DNS = 1.1.1.1
+
+[Peer]
+PublicKey = <contents of server.pub>
+Endpoint = YOUR_SERVER_IP:51820
+AllowedIPs = 0.0.0.0/0
+PersistentKeepalive = 25
+```
+
+Notes:
+
+- `AllowedIPs = 0.0.0.0/0` sends all client traffic through the VPN.
+
+- If you only want access to specific private networks, replace `0.0.0.0/0` with those subnets.
+
+Example split tunnel:
+
+```
+AllowedIPs = 10.10.10.0/24, 192.168.50.0/24
+```
+
+---
+
+## 7. Open Firewall Port
+
+If using UFW:
+
+```
+ufw allow 51820/udp
+```
+
+Or raw iptables:
+
+```
+iptables -A INPUT -p udp --dport 51820 -j ACCEPT
+```
+
+---
+
+## 8. Test Connection
+
+From the client:
+
+```
+curl ip.me
+```
+
+Expected result:
+
+- If full tunnel is enabled, this should show the server's public IP.
+
+Also test:
+
+```
+ping 10.10.10.1
+```
+
+---
+
+## 9. Add Additional Users
+
+Generate new keys:
+
+```
+wg genkey | tee user2.key | wg pubkey > user2.pub
+chmod 600 user2.key
+```
+
+Add to server config:
+
+```
+[Peer]
+PublicKey = <contents of user2.pub>
+AllowedIPs = 10.10.10.3/32
+```
+
+Apply changes:
+
+```
+wg syncconf wg0 <(wg-quick strip wg0)
+```
+
+Client config example for user2:
+
+```
+[Interface]
+Address = 10.10.10.3/24
+PrivateKey = <contents of user2.key>
+DNS = 1.1.1.1
+
+[Peer]
+PublicKey = <contents of server.pub>
+Endpoint = YOUR_SERVER_IP:51820
+AllowedIPs = 0.0.0.0/0
+PersistentKeepalive = 25
+```
+
+---
+
+## 10. Access Control and Network Design
+
+WireGuard handles authentication by key.
+
+WireGuard does **not** decide what a connected peer is allowed to reach.  
+That is handled by your firewall, typically with `iptables` or `nftables`.
+
+Think of it like this:
+
+- WireGuard key + peer IP = identity
+- Firewall rules = authorization
+
+### Important
+
+The examples below use:
+
+- `10.10.10.2` = full access user
+- `10.10.10.3` = restricted user
+- `10.10.10.4` = internet-only user
+
+Adjust these to your actual peer IP assignments.
+
+---
+
+### Scenario A: Public server only, no private networks behind it
+
+This is the simplest case.
+
+The server only has:
+
+- `eth0` facing the internet
+- `wg0` for VPN clients
+
+There is no LAN behind the server. You just want clients to:
+
+- connect to the server
+- route internet traffic through it
+- maybe reach services running on the server itself
+
+#### Full tunnel user
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.2 -o eth0 -j ACCEPT
+iptables -A FORWARD -o wg0 -d 10.10.10.2 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+```
+
+#### Internet-only restricted user
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.4 -o eth0 -j ACCEPT
+iptables -A FORWARD -o wg0 -d 10.10.10.4 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+iptables -A FORWARD -i wg0 -s 10.10.10.4 -j DROP
+```
+
+That last rule says:
+
+- allow that peer out to the internet
+- drop any other forwarded access attempt
+
+If the user also needs to reach services hosted directly on the VPN server itself, that is controlled by `INPUT` rules, not `FORWARD`.
+
+Example: allow SSH from one VPN peer to the server:
+
+```
+iptables -A INPUT -i wg0 -s 10.10.10.3 -p tcp --dport 22 -j ACCEPT
+```
+
+Example: block all other VPN clients from SSH to the server:
+
+```
+iptables -A INPUT -i wg0 -p tcp --dport 22 -j DROP
+```
+
+---
+
+### Scenario B: Server has private networks behind it
+
+Use this if the Debian server can route to private networks such as:
+
+- `192.168.1.0/24`
+- `10.0.0.0/24`
+- `172.16.50.0/24`
+
+In this case, your VPN clients can be selectively allowed to those networks.
+
+#### Full access user to all routed private networks
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.2 -j ACCEPT
+```
+
+That is broad. It allows that peer to anything the server can route to.
+
+#### Restricted user to a single host
+
+Example: only allow `10.10.10.3` to reach `192.168.1.50`
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.50 -j ACCEPT
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP
+```
+
+#### Restricted user to a whole subnet
+
+Example: only allow `10.10.10.3` to reach `192.168.1.0/24`
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.0/24 -j ACCEPT
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP
+```
+
+#### Internet plus one private subnet
+
+Example: allow `10.10.10.3` to:
+
+- use the server as an internet gateway
+- access `192.168.1.0/24`
+- nothing else
+
+```
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.0/24 -j ACCEPT
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -o eth0 -j ACCEPT
+iptables -A FORWARD -o wg0 -d 10.10.10.3 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP
+```
+
+#### Client-side route restriction
+
+You should also tighten the client config.
+
+If a peer should only reach one private subnet, do not send all traffic through the tunnel.
+
+Example client config:
+
+```
+AllowedIPs = 10.10.10.0/24, 192.168.1.0/24
+```
+
+That gives split-tunnel access only to:
+
+- the VPN subnet
+- the private subnet behind the server
+
+---
+
+## 11. Remove or Revoke Access
+
+Remove a peer immediately:
+
+```
+wg set wg0 peer <public_key> remove
+```
+
+Or edit `wg0.conf` and reload:
+
+```
+wg syncconf wg0 <(wg-quick strip wg0)
+```
+
+---
+
+## 12. Common Issues
+
+- IP forwarding not enabled
+- Wrong public interface name
+- Firewall blocking UDP 51820
+- NAT rule missing
+- Server not publicly reachable
+- Client `AllowedIPs` too broad or too narrow
+- Client clock wildly wrong
+- Forgot `PersistentKeepalive = 25` for clients behind NAT
+
+---
+
+## 13. Key Concepts
+
+- Each peer should have its own keypair
+- No passwords or usernames in WireGuard
+- One device should not share another device's key
+- VPN peer IPs should be treated like identities
+- Firewall rules decide what each peer can reach
+
+---
+
+## 14. Recommended Next Step
+
+This walkthrough uses `iptables` because it is straightforward and familiar.
+
+For a cleaner long-term setup on Debian 13, consider moving the policy to `nftables`, especially if you will have:
+
+- multiple users
+- different access classes
+- persistent firewall rules you want managed sanely
+
+---