commit bc567c478a50119d3f8ec61621a6c3885e033e30 Author: Paul-Christian Volkmer Date: Sun Nov 27 14:16:49 2022 +0100 Initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..982aadc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.d/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c371660 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM rust:slim AS build + +RUN rustup target add x86_64-unknown-linux-musl +RUN apt update && apt install -y musl-tools musl-dev +RUN cargo install --target x86_64-unknown-linux-musl boringtun-cli + +### + +FROM alpine + +ENV WG_QUICK_USERSPACE_IMPLEMENTATION boringtun +ENV WG_LOG_LEVEL info +ENV WG_LOG_FILE /var/log/boringtun +ENV WG_SUDO 1 + +RUN apk --update add iproute2 wireguard-tools-wg-quick libqrencode +COPY --from=build /usr/local/cargo/bin/boringtun-cli /usr/local/bin/boringtun +COPY create-config.sh entrypoint.sh ./ + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..80913a7 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# WireGuard docker image using BoringTun + +WireGuard docker setup using BoringTun. + +## Overview + +This project provides a docker image to create a simple personal WireGuard VPN using BoringTun. + +Using BoringTun enables the use of a userspace implementation on hosts that do not provide a WireGuard kernel module. + +Required configuration files will be generated on first run using environment variables. Client configurations are +available as config files and QR codes. + +## Build + +When creating the image, BoringTun is compiled in a docker build stage and later copied into final image. + +``` +$ docker-compose build +``` + +## Run + +Customize the file `docker-compose`. You can change the following environment variables as needed + +* `DEVICE`: Some `tun` device, e.g. `tun0` +* `SERVER_HOST`: The host name of your server +* `SERVER_PORT`: The port the service should listen at +* `NETWORK`: Some custom /24 network. e.g. `192.168.42.0` +* `CLIENTS`: Number of clients for which configurations are to be created. Do not use more than 240 clients. + +If no environment variables are set, config creation script will ask you for settings. + +### Create config files + +Run the service to create required keys and config files in directory `config.d`. It will print out used configuration params. + +``` +$ docker-compose run wg + +Starting wireguard_wg_1 ... done +Attaching to wireguard_wg_1 +wg_1 | - Writing config to file tun0.conf +wg_1 | - Using endpoint hostname example.com +wg_1 | - Using port 51820 +wg_1 | - Using network 192.168.42.0/24 +wg_1 | - Generating 5 client configs and client QR codes +wireguard_wg_1 exited with code 0 +``` + +### Remove old and create new config files + +Remove existing config files or rename device in `docker-compose.yml`. Run command `docker-compose up` again. + +### Run the service + +Start the service in detached mode. + +``` +$ docker-compose up -d +``` + +## Client configurations + +You will find client configuration files for each client as config file and PNG file containing a QR code with +client configuration in directory `config.d`. \ No newline at end of file diff --git a/config.d/.gitkeep b/config.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/create-config.sh b/create-config.sh new file mode 100755 index 0000000..bad66ac --- /dev/null +++ b/create-config.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Remove leftover config files +rm *.conf 2>/dev/null +rm *-client_*.png 2>/dev/null + +while [[ -z $DEVICE ]]; do + echo -n "Device (eg tun0): " + read DEVICE +done +echo " - Writing config to file $DEVICE.conf" + +while [[ -z $SERVER_HOST ]]; do + echo -n "Endpoint hostname: " + read SERVER_HOST +done +echo " - Using endpoint hostname $SERVER_HOST" + +if [[ -z $SERVER_PORT ]]; then + echo -n "Endpoint port: " + read SERVER_PORT +fi +echo " - Using port $SERVER_PORT" + +if [[ -z $NETWORK ]]; then + echo -n "Network (/24): " + read NETWORK +fi +echo " - Using network $NETWORK/24" +NETWORK=$(echo -n $NETWORK | sed -r "s/\.[0-9]+$//") + +while [[ -z $CLIENTS ]]; do + echo -n "Number of clients: " + read CLIENTS +done +echo " - Generating $CLIENTS client configs and client QR codes" + +SERVER_SEC_KEY=$(wg genkey) +SERVER_PUB_KEY=$(echo $SERVER_SEC_KEY | wg pubkey) + +declare -a CLIENT_SEC_KEYS +declare -a CLIENT_PUB_KEYS + +# Generate client keys +for (( i=1; i<=$CLIENTS; i++ )); do + CLIENT_SEC_KEY=$(wg genkey) + CLIENT_PUB_KEY=$(echo $CLIENT_SEC_KEY | wg pubkey) + + CLIENT_SEC_KEYS[$i]=$CLIENT_SEC_KEY + CLIENT_PUB_KEYS[$i]=$CLIENT_PUB_KEY +done + +cat <> $DEVICE.conf +############## +# SERVER +############## + +[Interface] +Address = $NETWORK.1/24 +ListenPort = $SERVER_PORT +PrivateKey = $SERVER_SEC_KEY + +PostUp = iptables -A FORWARD -i $DEVICE -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -D FORWARD -i $DEVICE -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + +EOF + +# Print out client peers +for (( i=1; i<=$CLIENTS; i++ )); do +cat << EOF >> $DEVICE.conf +# Client $i +[Peer] +PublicKey = ${CLIENT_PUB_KEYS[$i]} +AllowedIPs = $NETWORK.$(($i+10))/32 + +EOF +done + +# Print out client configs + +for (( i=1; i<=$CLIENTS; i++ )); do +cat <> $DEVICE-client_$i.conf +############## +# CLIENT $i +############## + +[Interface] +Address = $NETWORK.$(($i+10))/24 +ListenPort = $SERVER_PORT +PrivateKey = ${CLIENT_SEC_KEYS[$i]} + +[Peer] +PublicKey = $SERVER_PUB_KEY +AllowedIPs = 0.0.0.0/0, ::/0 +Endpoint = $SERVER_HOST:$SERVER_PORT +EOF +done + +# Create QR-codes for clients +if [ ! -z "$(which qrencode 2>/dev/null)" ]; then + for (( i=1; i<=$CLIENTS; i++ )); do + qrencode -t png -o "$DEVICE-client_$i.png" < $DEVICE-client_$i.conf + done +fi diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..00276cc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: '2.1' + +services: + + wg: + build: . + ports: + - "51820:51820/udp" + cap_add: + - NET_ADMIN + sysctls: + - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.rp_filter=2 + devices: + - "/dev/net/tun:/dev/net/tun" + volumes: + - "./config.d:/etc/wireguard/" + environment: + DEVICE: tun0 + SERVER_HOST: example.com + SERVER_PORT: 51820 + NETWORK: 192.168.42.0 + CLIENTS: 5 + diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..eb5a320 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +set -e + +if [ -z $DEVICE ]; then + DEVICE="tun0" +fi + +if [ ! -f "/etc/wireguard/$DEVICE.conf" ]; then + cd /etc/wireguard + /create-config.sh + exit 0 +fi + +echo "Starting wg-quick on $DEVICE" +touch "${WG_LOG_FILE}" +wg-quick up $DEVICE +echo "done!" + +tail -f "${WG_LOG_FILE}"