fly.io wireguard vpn server

diy vpn server on wireguard

SEAN K.H. LIAO

fly.io wireguard vpn server

diy vpn server on wireguard

fly.io and wireguard

fly.io is a compute platform that runs your apps from container images as micro vms on firecracker. Their have docs on how their private networking uses wireguard, and an interesting blog post on embedding wireguard into their CLI.

But what I want is a vpn server that will forward all my traffic, not just access internal services on fly.io. So, back to DIY then. Fortunately, they do mention that their kernels are wireguard enabled.

build the image

Let's start with a Dockerfile, we'll want the wireguard tools and an script:

FROM alpine

RUN apk update && \
    apk add --no-cache \
        wireguard-tools

COPY run.sh .
ENTRYPOINT [ "/run.sh" ]

And for our script:

#!/bin/sh

set -ex

# ip forwarding, not strictly necessary I think?
cat << EOF > /etc/sysctl.d/forward.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
EOF

sysctl -p /etc/sysctl.d/forward.conf

# wireguard config
cat << EOF > /etc/wireguard/wg0.conf
[Interface]
Address = 192.168.100.4/24
ListenPort = 51820
PrivateKey = ${WIREGUARD_PRIVATE_KEY}

# NAT the clients, we don't allocate extra ip addresses for them
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;iptables -A FORWARD -o %i -j ACCEPT
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE;iptables -D FORWARD -o %i -j ACCEPT

[Peer]
# eevee
PublicKey = ......
AllowedIPs = ......
EOF

# bring up wireguard
wg-quick up wg0

# never exit
while true; do
    wg show
    sleep 60
done

deploy the app

We'll need the app definition

# choose a globally unique name
app = "app-name"

# build from our dockerfile
[build]
  dockerfile = "Dockerfile"

  # expose the wireguard port
[[services]]
  internal_port = 51820
  protocol = "udp"
  [[services.ports]]
    port = 51820

Some commands to setup the app:

$ flyctl apps create app-name
$ wg genkey | tee /dev/stderr | wg pubkey
$ flyctl secrets set WIREGUARD_PRIVATE_KEY=$first_line_from_previous_command
$ flyctl deploy
$ flyctl ips list

Then setup clients to connect

[WireGuardPeer]
PublicKey = ...
Endpoint = ...:51820
PersistentKeepalive = 30
AllowedIPs = ...