diff options
Diffstat (limited to 'templates')
-rw-r--r-- | templates/manage_wg_peers.sh.j2 | 186 | ||||
-rw-r--r-- | templates/wg0.conf.j2 | 12 |
2 files changed, 198 insertions, 0 deletions
diff --git a/templates/manage_wg_peers.sh.j2 b/templates/manage_wg_peers.sh.j2 new file mode 100644 index 0000000..ed2f800 --- /dev/null +++ b/templates/manage_wg_peers.sh.j2 @@ -0,0 +1,186 @@ +#!/bin/bash +set -e + +WG_SERVER_HOME="{{ wireguard_server_home }}" +WG_PEERS_HOME="${WG_SERVER_HOME}/peers.d" +IP_FILE="${WG_SERVER_HOME}/ips.txt" +SUBNET_PREFIX="{{ wireguard_subnet_prefix }}" +DEFAULT_PORT="{{ wireguard_port }}" +DEFAULT_DNS="8.8.8.8" + +test "${EUID}" -ne 0 && printf "%s\n" "run as root" && exit 1 +umask 077 + +if ! command -v wg &>/dev/null; then + printf "%s\n" "[err] wireguard not installed" + exit 1 +fi + +function usage() { + printf "%s\n" \ + "" \ + "wireguard peer management script" \ + "usage: $(basename ${0}) <action> [-h] <options>" \ + "" \ + "add-peer add a peer to the wg network" \ + "options:" \ + "-s <server> required: wg server endpoint" \ + "-n <name> optional: peer name, default random" \ + "-p <port> optional: wg server port, default ${DEFAULT_PORT}" \ + "-d <dns> optional: dns server, default ${DEFAULT_DNS}" \ + "" \ + "remove-peer remove peer from the wg network" \ + "options:" \ + "-n <name> required: peer name" \ + "" \ + "usage print this help message and exit" \ + "" \ + "configuration files:" \ + "wg server config dir: ${WG_SERVER_HOME}" \ + "wg peers configs dir: ${WG_PEERS_HOME}" + exit 1 +} + +function validate_ip() { + local ip="${1}" + if ! [[ "${ip}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + printf "%s\n" "[err] invalid IP address: ${ip}" + exit 1 + fi +} + +function validate_port() { + local port="${1}" + if ! [[ "${port}" =~ ^[0-9]+$ ]] || [[ "${port}" -lt 1 ]] || [[ "${port}" -gt 65535 ]]; then + printf "%s\n" "[err] invalid port: ${port}" + exit 1 + fi +} + +function get_next_available_ip() { + ( + flock -x 200 + touch "${IP_FILE}" + for i in {2..254}; do + ip="${SUBNET_PREFIX}.${i}" + if ! grep -q "${ip}" "${IP_FILE}"; then + printf "%s\n" "${ip}" + printf "%s\n" "${ip}" >> "${IP_FILE}" + exit 0 + fi + done + printf "%s\n" "[err] no available ips in range ${SUBNET_PREFIX}.2 - ${SUBNET_PREFIX}.254" + exit 1 + ) 200>"${IP_FILE}.lock" +} + +function add_peer() { + if ! test -d "${WG_SERVER_HOME}" || ! test -f "${WG_SERVER_HOME}/wg0.conf"; then + printf "%s\n" "[err] no wg server config found; install the server first" + exit 1 + fi + + if ! test "${server}"; then + printf "%s\n" "[err] missing -s <server>" + exit 1 + fi + + mkdir -p "${WG_PEERS_HOME}/${name}" &>/dev/null + assigned_ip=$(get_next_available_ip) + ( + cd "${WG_PEERS_HOME}/${name}" + wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub" + + cat > "${name}.conf" << EOF +# peer ${name} +[Interface] +PrivateKey = $(cat "${name}.key") +Address = ${assigned_ip}/24 +DNS = ${dns} + +[Peer] +PublicKey = $(wg pubkey < "${WG_SERVER_HOME}/server.key") +PresharedKey = $(cat "${WG_SERVER_HOME}/psk.key") +Endpoint = ${server}:${port} +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = 25 +EOF + printf "%s\n" \ + "[inf] generated peer configuration ${name} to server ${server}" \ + "[inf] config: ${WG_PEERS_HOME}/${name}/${name}.conf" + ) + + ( + peer_public_key=$(wg pubkey < "${WG_PEERS_HOME}/${name}/${name}.key") + cat >> "${WG_SERVER_HOME}/wg0.conf" << EOF + +# peer ${name} +[Peer] +PublicKey = ${peer_public_key} +PresharedKey = $(cat "${WG_SERVER_HOME}/psk.key") +AllowedIPs = ${assigned_ip}/32 +# peer ${name} +EOF + systemctl restart wg-quick@wg0.service + printf "%s\n" "[inf] restarted wg-quick@wg0.service" + ) +} + +function remove_peer() { + if ! test "${name}"; then + printf "%s\n" "[err] missing -n <name>" + exit 1 + fi + + if grep -qi "^# peer ${name}" "${WG_SERVER_HOME}/wg0.conf"; then + sed -i "/# peer ${name}/,/# peer ${name}/ s/^/# /" "${WG_SERVER_HOME}/wg0.conf" + systemctl restart wg-quick@wg0.service + printf "%s\n" "[inf] removed peer ${name} and restarted wg server" + else + printf "%s\n" "[err] no such peer ${name} in ${WG_SERVER_HOME}/wg0.conf" + exit 1 + fi +} + +port="${DEFAULT_PORT}" +dns="${DEFAULT_DNS}" + +if test "${1}"; then + action="${1}" + shift + case "${action}" in + add-peer) + while getopts "s:n:p:d:h" opts; do + case "${opts}" in + s) server="${OPTARG}"; validate_ip "${server}";; + n) name="${OPTARG}";; + p) port="${OPTARG}"; validate_port "${port}";; + d) dns="${OPTARG}"; validate_ip "${dns}";; + h) usage;; + *) usage;; + esac + done + rand=$(printf "%s\n" "${RANDOM}" | md5sum | fold -w4 | head -1) + name="${name:-${rand}}" + add_peer + ;; + remove-peer) + while getopts "n:h" opts; do + case "${opts}" in + n) name="${OPTARG}";; + h) usage;; + *) usage;; + esac + done + remove_peer + ;; + usage) + usage + ;; + *) + usage + ;; + esac +else + usage +fi diff --git a/templates/wg0.conf.j2 b/templates/wg0.conf.j2 new file mode 100644 index 0000000..6b0aa34 --- /dev/null +++ b/templates/wg0.conf.j2 @@ -0,0 +1,12 @@ +[Interface] +PrivateKey = {{ private_key }} +Address = {{ wireguard_subnet_prefix}}.1/24 +ListenPort = {{ wireguard_port }} +PostUp = sysctl -w net.ipv4.ip_forward=1 +PostUp = iptables -A FORWARD -i {{ wireguard_interface }} -o %i -j ACCEPT +PostUp = iptables -A FORWARD -i %i -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o {{ wireguard_interface }} -j MASQUERADE +PostDown = sysctl -w net.ipv4.ip_forward=0 +PostDown = iptables -D FORWARD -i {{ wireguard_interface }} -o %i -j ACCEPT +PostDown = iptables -D FORWARD -i %i -j ACCEPT +PostDown = iptables -t nat -D POSTROUTING -o {{ wireguard_interface }} -j MASQUERADE |