From 3d841a76aa0540a98fa00cd9e2699651e874d51c Mon Sep 17 00:00:00 2001 From: Matthew Saunders Brown Date: Mon, 25 Jan 2021 15:37:53 -0800 Subject: [PATCH] initial commit --- LICENSE | 19 +++ README.md | 40 ++++++ wg-client-add.sh | 146 +++++++++++++++++++++ wg-client-create-zip.sh | 46 +++++++ wg-client-del.sh | 47 +++++++ wg-client-disable.sh | 40 ++++++ wg-client-enable.sh | 54 ++++++++ wg-client-qr-create-png.sh | 45 +++++++ wg-client-qr-display.sh | 39 ++++++ wg-cron.sh | 40 ++++++ wg-install.sh | 255 +++++++++++++++++++++++++++++++++++++ wg-peer-audit.sh | 40 ++++++ 12 files changed, 811 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100755 wg-client-add.sh create mode 100755 wg-client-create-zip.sh create mode 100755 wg-client-del.sh create mode 100755 wg-client-disable.sh create mode 100755 wg-client-enable.sh create mode 100755 wg-client-qr-create-png.sh create mode 100755 wg-client-qr-display.sh create mode 100755 wg-cron.sh create mode 100755 wg-install.sh create mode 100755 wg-peer-audit.sh diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..156bfd4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +MIT License Copyright (c) 2021 Matthew Saunders Brown + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2131fe8 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# wireguard-stack + +A set of bash scripts for installing and managing a WireGuard VPN server. + +## Download & Install + +Start with basic Ubuntu 20.04 install with no extra services or packages installed. + +```bash +cd /usr/local/src/ +wget https://git.stack-source.com/stackaas/stack-vpn/archive/master.tar.gz +tar zxvf master.tar.gz +cd stack-vpn +chmod 750 wg-*.sh +mv wg-*.sh /usr/local/sbin/ +/usr/local/sbin/wg-install.sh +``` + +## Configure Clients + +Download and install client software from [wireguard.com](https://www.wireguard.com/install/). + +Add a client configuration to the server and display a qr code that can be scanned by a client. If the + +```bash +wg-client-add.sh username [device] +wg-client-qr-display.sh username [device] +``` + +If the device option is left off then a "default" device will be added for that client/username. +For example, to add a client config for a user named joe and display the qr code on the console screen run: + +```bash +wg-client-add.sh joe +wg-client-qr-display.sh joe +``` + +# Todo + +Complete documentation that describes in detail the configuration of the WireGuard server coming next. In the meantime review the comments in wg-install.sh to see details. diff --git a/wg-client-add.sh b/wg-client-add.sh new file mode 100755 index 0000000..6fb3904 --- /dev/null +++ b/wg-client-add.sh @@ -0,0 +1,146 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf + +# check for existing config +if [ -f /etc/wireguard/clients/$config ] || [ -f /etc/wireguard/peers/$config ]; then + echo "config for $client $device already exists" + exit 1 +fi + +# set Endpoint to FQDN of this server +endpoint=`hostname -f` + +# alternatively set Endpoint to primary IPv4 of this server +# assumes a single IP on a /24 subnet is provisioned on the server +# you can change this to fit your network, or just set to a specific IP +# this is the IP that clients use to establish vpn connection +# endpoint=`ip -4 -o addr show | awk '{ print $4 }' | grep '/24$' | cut -d / -f 1` + +# get next available IP +# note that tests show this code is quick with a few hundred to low thousands of assigned client IPs +# but can take serveral minutes when assigned client IPs gets in to the 10s or 100s of thousands + +# get array of assigned IPs - no longer used, memory usage too high when larger number of IPs assigned +# addresses=($(grep Address /etc/wireguard/clients/*.conf | cut -d ' ' -f 3 | cut -d "/" -f 1)) + +# address unassigned +address=0 + +# Network: 10.96.0.0/12 +# HostMin: 10.96.0.1 +# HostMax: 10.111.255.254 + +# 06 - 111 +secondoctet=96 +while [ $secondoctet -lt 112 ] && [ $address = 0 ]; do + + # 0 - 255 + thirdoctet=0 + while [ $thirdoctet -lt 256 ] && [ $address = 0 ]; do + + fourthoctet=1 + while [ $fourthoctet -lt 256 ] && [ $address = 0 ]; do + + testaddress=10.$secondoctet.$thirdoctet.$fourthoctet + + # skip reserved addresses + if [ $testaddress = "10.96.0.1" ]; then + fourthoctet=$[$fourthoctet+1] + elif [ $testaddress = "10.111.255.255" ]; then + echo "all available addresses used, can not add more clients" + exit 1 + elif `grep -qr "$testaddress/" /etc/wireguard/clients/`; then + fourthoctet=$[$fourthoctet+1] + else + address=$testaddress + fi + + done + + thirdoctet=$[$thirdoctet+1] + + done + + secondoctet=$[$secondoctet+1] + +done + +# set temp umask for creating wiregaurd configs +UMASK=`umask` +umask 0077 + +# make sure clients config dir exists +if [[ ! -d /etc/wireguard/clients ]]; then + install --owner=root --group=root --mode=700 --directory /etc/wireguard/clients +fi + +# make sure peers config dir exists +if [[ ! -d /etc/wireguard/peers ]]; then + install --owner=root --group=root --mode=700 --directory /etc/wireguard/peers +fi + +key=$(wg genkey) +psk=$(wg genpsk) +publickey_server=$(cat /etc/wireguard/.publickey) +publickey_client=$(wg pubkey <<< $key) + +# create server config for client (peer) +cat << EOF >> /etc/wireguard/peers/"$config" +[Peer] +PublicKey = $publickey_client +PresharedKey = $psk +AllowedIPs = $address/32 +EOF + +# enable client on server +wg addconf wg0 /etc/wireguard/peers/"$config" +# save newly added client to server config +wg-quick save wg0 + +# create config for client +cat << EOF > /etc/wireguard/clients/"$config" +[Interface] +Address = $address/32 +DNS = 10.96.0.1 +PrivateKey = $key + +[Peer] +PublicKey = $publickey_server +PresharedKey = $psk +AllowedIPs = 0.0.0.0/0 +Endpoint = $endpoint:51820 +PersistentKeepalive = 25 +EOF + +# revert umask setting +umask $UMASK diff --git a/wg-client-create-zip.sh b/wg-client-create-zip.sh new file mode 100755 index 0000000..be9412f --- /dev/null +++ b/wg-client-create-zip.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf +image=$config.$device.png + +# check for existing config +if [ -f /etc/wireguard/clients/$config ]; then + + if [ ! -d /var/lib/wireguard ]; then + install --owner=root --group=root --mode=700 --directory /var/lib/wireguard + fi + cd /var/lib/wireguard/ + /usr/bin/zip -j $config.zip /etc/wireguard/clients/$config + +else + echo "config for $client $device does not exist" +fi diff --git a/wg-client-del.sh b/wg-client-del.sh new file mode 100755 index 0000000..f13b04e --- /dev/null +++ b/wg-client-del.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf + +# check for server config +if [ -f /etc/wireguard/peers/$config ]; then + peer=$(grep PublicKey /etc/wireguard/peers/$config|cut -d ' ' -f 3) + wg set wg0 peer $peer remove + wg-quick save wg0 + rm /etc/wireguard/peers/$config + echo "peer and server config for $client $device removed" +fi + +# check for client config +if [ -f /etc/wireguard/clients/$config ]; then + rm /etc/wireguard/clients/$config + echo "client config for $client $device removed" +fi diff --git a/wg-client-disable.sh b/wg-client-disable.sh new file mode 100755 index 0000000..474fdb8 --- /dev/null +++ b/wg-client-disable.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf + +# check for server config +if [ -f /etc/wireguard/peers/$config ]; then + peer=$(grep PublicKey /etc/wireguard/peers/$config|cut -d ' ' -f 3) + wg set wg0 peer $peer remove + wg-quick save wg0 + echo "peer for $client $device disabled" +fi diff --git a/wg-client-enable.sh b/wg-client-enable.sh new file mode 100755 index 0000000..5ad6fbe --- /dev/null +++ b/wg-client-enable.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf + +# check for server config +if [ -f /etc/wireguard/peers/$config ]; then + peer=$(grep PublicKey /etc/wireguard/peers/$config|cut -d ' ' -f 3) + status=$(wg |grep -c $peer) + if [ $status = 0 ]; then + wg addconf wg0 /etc/wireguard/peers/$config + wg-quick save wg0 + echo "peer for $client $device enabled" + elif [ $status = 1 ]; then + echo "peer for $client $device already enabled" + else + echo "unexpected status for peer $client $device ($status)" + fi +elif [ -f /etc/wireguard/clients/$config ]; then + # create server config + # enable server config + echo "server config for $client $device not found, but client config exists." + echo "add programming here to create server config and enable" +else + echo "no configs for $client $device found" +fi diff --git a/wg-client-qr-create-png.sh b/wg-client-qr-create-png.sh new file mode 100755 index 0000000..599f98d --- /dev/null +++ b/wg-client-qr-create-png.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf +image=$config.$device.png + +# check for existing config +if [ -f /etc/wireguard/clients/$config ]; then + + if [ ! -d /var/lib/wireguard ]; then + install --owner=root --group=root --mode=700 --directory /var/lib/wireguard + fi + qrencode -t png -r /etc/wireguard/clients/$config -o /var/lib/wireguard/$image + +else + echo "config for $client $device does not exist" +fi diff --git a/wg-client-qr-display.sh b/wg-client-qr-display.sh new file mode 100755 index 0000000..ad5653d --- /dev/null +++ b/wg-client-qr-display.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# check for and set client name +if [ -n "$1" ]; then + client=$1 + # set beginning of config file name + config=$client +else + echo "client name not set" + exit 1 +fi + +# check if device name was set +if [ -n "$2" ]; then + device=$2 +else + device=default +fi + +# add device name & .conf to config file name +config=$config.$device.conf + +# check for existing config +if [ -f /etc/wireguard/clients/$config ]; then + qrencode -t ansiutf8 < /etc/wireguard/clients/$config +else + echo "config for $client $device does not exist" +fi diff --git a/wg-cron.sh b/wg-cron.sh new file mode 100755 index 0000000..3f9105f --- /dev/null +++ b/wg-cron.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown +# +# wg-cron.sh +# check for peers (clients) with connections older that two minutes +# remove them then add them back to wireguard +# this removes the endpoint (last connected IP) and transfer stats + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# get peer of clients with "minutes" in their last handshake +clients=($(wg|grep -B 4 minutes|grep peer|cut -d ' ' -f 2)) + +# get number of peers found above +clientCount=${#clients[@]} + +# if any peers found cycle through them +if [ $clientCount -gt 0 ]; then + + for (( i=0; i<${clientCount}; i++ )); + do + # remove peer from wireguard + wg set wg0 peer ${clients[$i]} remove + config=$(grep ${clients[$i]} /etc/wireguard/peers/*.conf|cut -d : -f 1) + # add peer back to wireguard + wg addconf wg0 $config + done + + # save to config so that changes survive wireguard restart + wg-quick save wg0 + +fi diff --git a/wg-install.sh b/wg-install.sh new file mode 100755 index 0000000..cd66dd8 --- /dev/null +++ b/wg-install.sh @@ -0,0 +1,255 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown +# +# wireguard installer for Ubuntu 20.04 +# +# this installer expects a clean Ubuntu 20.04 install with +# wireguard, stubby & dnsmasq *not* previously installed + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# do some basic pre-install checks - these are *not* exhaustive +os_id=`lsb_release -is` +os_release=`lsb_release -rs` +if [ $os_id != Ubuntu ] || [ $os_release != 20.04 ]; then + echo "this installer only runs on Ubuntu 20.04, bailing out" + exit 1 +fi + +if [ -d /etc/wiregaurd ]; then + echo "looks like wireguard is already installed, bailing out" + exit 1 +fi + +if [ -d /etc/stubby/ ]; then + echo "looks like stubby is already installed, bailing out" + exit 1 +fi + +if [ -d /etc/dnsmasq.d ]; then + echo "looks like dnsmasq is already installed, bailing out" + exit 1 +fi + +# assumes a single IP on a /24 subnet is provisioned on the server +# you can change this to fit your network, or just set to a specific IP +# used by wireguard for vpn connections & stubby for DNS queries +IPv4=`ip -4 -o addr show | awk '{ print $4 }' | grep '/24$' | cut -d / -f 1` + +# update system +apt -y update +# update grub first, by itself, as it requires special overrides to run unattended +DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install grub-common grub2-common grub-pc grub-pc-bin +DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade +DEBIAN_FRONTEND=noninteractive apt-get -y autoremove + +# set system variables +echo "# for wireguard vpn" > /etc/sysctl.d/60-wireguard.conf +echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/60-wireguard.conf +echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.d/60-wireguard.conf +echo "# for dnsmasq (dns)" >> /etc/sysctl.d/60-wireguard.conf +echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.d/60-wireguard.conf +echo "net.ipv6.ip_nonlocal_bind = 1" >> /etc/sysctl.d/60-wireguard.conf +/sbin/sysctl --system + +# DNS over TLS (DoT) for OS +sed -i 's|#DNS=|DNS=1.1.1.1#one.one.one.one|g' /etc/systemd/resolved.conf +sed -i 's|#FallbackDNS=|FallbackDNS=1.0.0.1#one.one.one.one|g' /etc/systemd/resolved.conf +sed -i "s|#Domains=|Domains=`hostname -d`|g" /etc/systemd/resolved.conf +sed -i 's|#DNSOverTLS=no|DNSOverTLS=yes|g' /etc/systemd/resolved.conf +sed -i 's|#Cache=yes|Cache=no|g' /etc/systemd/resolved.conf +systemctl restart systemd-resolved + +# configure a minimal smtp server so automated emails (cron etc) can be sent +apt -y install exim4-daemon-light mailutils +sed -i "s|dc_eximconfig_configtype='local'|dc_eximconfig_configtype='internet'|g" /etc/exim4/update-exim4.conf.conf +/usr/sbin/update-exim4.conf +systemctl restart exim4 + +# configure automatic updates +apt -y install --no-install-recommends mailutils +apt -y install unattended-upgrades +sed -i 's|APT::Periodic::Download-Upgradeable-Packages "0";|APT::Periodic::Download-Upgradeable-Packages "1";|g' /apt/apt.conf.d/10periodic +sed -i 's|APT::Periodic::AutocleanInterval "0";|APT::Periodic::AutocleanInterval "7";|g' /apt/apt.conf.d/10periodic +echo 'APT::Periodic::Unattended-Upgrade "1";' >> /apt/apt.conf.d/10periodic +sed -i 's|// "${distro_id}:${distro_codename}-updates";| "${distro_id}:${distro_codename}-updates";|g' /etc/apt/apt.conf.d/50unattended-upgrades +sed -i 's|//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";|Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades +sed -i 's|//Unattended-Upgrade::Remove-Unused-Dependencies "false";|Unattended-Upgrade::Remove-Unused-Dependencies "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades +sed -i 's|//Unattended-Upgrade::Automatic-Reboot "false";|Unattended-Upgrade::Automatic-Reboot "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades +# between 8:00 and 9:59am UTC, change to suit your needs +REBOOT_TIME=$(printf "%02d" $((8 + RANDOM % 2))):$(printf "%02d" $((0 + RANDOM % 60))) +sed -i "s|//Unattended-Upgrade::Automatic-Reboot-Time \"02:00\";|Unattended-Upgrade::Automatic-Reboot-Time \"$REBOOT_TIME\";|g" /etc/apt/apt.conf.d/50unattended-upgrades + +# stubby DNS Privacy stub resolver for wireguard clients +apt -y install stubby +cp /etc/stubby/stubby.yml /etc/stubby/stubby.yml.default +echo 'resolution_type: GETDNS_RESOLUTION_STUB' > /etc/stubby/stubby.yml +echo 'dns_transport_list:' >> /etc/stubby/stubby.yml +echo ' - GETDNS_TRANSPORT_TLS' >> /etc/stubby/stubby.yml +echo 'tls_authentication: GETDNS_AUTHENTICATION_REQUIRED' >> /etc/stubby/stubby.yml +echo 'tls_query_padding_blocksize: 128' >> /etc/stubby/stubby.yml +echo 'edns_client_subnet_private : 1' >> /etc/stubby/stubby.yml +echo 'round_robin_upstreams: 1' >> /etc/stubby/stubby.yml +echo 'idle_timeout: 10000' >> /etc/stubby/stubby.yml +echo 'listen_addresses:' >> /etc/stubby/stubby.yml +echo ' - 127.0.0.1' >> /etc/stubby/stubby.yml +echo ' - 0::1' >> /etc/stubby/stubby.yml +echo " - $IPv4" >> /etc/stubby/stubby.yml +echo 'upstream_recursive_servers:' >> /etc/stubby/stubby.yml +echo ' - address_data: 1.1.1.1' >> /etc/stubby/stubby.yml +echo ' tls_auth_name: "one.one.one.one"' >> /etc/stubby/stubby.yml +echo ' - address_data: 1.0.0.1' >> /etc/stubby/stubby.yml +echo ' tls_auth_name: "one.one.one.one"' >> /etc/stubby/stubby.yml +echo ' - address_data: 2606:4700:4700::1111' >> /etc/stubby/stubby.yml +echo ' tls_auth_name: "one.one.one.one"' >> /etc/stubby/stubby.yml +echo ' - address_data: 2606:4700:4700::1001' >> /etc/stubby/stubby.yml +echo ' tls_auth_name: "one.one.one.one"' >> /etc/stubby/stubby.yml +systemctl restart stubby.service + +# download adware + malware hosts file, used by dnsmasq +wget --output-document=/usr/local/etc/hosts https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts + +# dnsmasq will use adware + malware hosts file +# and listen on wireguard server private lan IP +# can be used by clients for adblocking +apt -y install dnsmasq +echo "domain-needed" > /etc/dnsmasq.d/local.conf +echo "bogus-priv" >> /etc/dnsmasq.d/local.conf +echo "no-resolv" >> /etc/dnsmasq.d/local.conf +echo "no-poll" >> /etc/dnsmasq.d/local.conf +echo "server=127.0.0.1" >> /etc/dnsmasq.d/local.conf +echo "addn-hosts=/usr/local/etc/hosts" >> /etc/dnsmasq.d/local.conf +# cache is disabled for extra privacy, but this impacts performance +# enable cache for increased performance, at the expense of privacy +echo "cache-size=0" >> /etc/dnsmasq.d/local.conf +echo "no-negcache" >> /etc/dnsmasq.d/local.conf +echo "listen-address=10.96.0.1" >> /etc/dnsmasq.d/local.conf +echo "no-dhcp-interface=10.96.0.1" >> /etc/dnsmasq.d/local.conf +echo "bind-interfaces" >> /etc/dnsmasq.d/local.conf +systemctl restart dnsmasq.service + +# install and configure ufw firewall +apt -y install ufw +# enable wireguard port +ufw allow from any to $IPv4 port 51820 proto udp +# allow dns queries for wireguard clients +ufw allow from 10.96.0.0/12 to any port 53 proto udp +ufw allow from 10.96.0.0/12 to any port 53 proto tcp +# enable ssh for remote server management +# consider restricting this to specific IP(s) if you can +ufw allow 22/tcp +# nat/fowaring/masquerade rules for wireguard +# taken from https://www.linuxbabe.com/ubuntu/wireguard-vpn-server-ubuntu +# get line number of last ufw-before-forward entry in ufw before.rules config file +BRLINE=`grep -n 'ufw-before-forward' /etc/ufw/before.rules |tail -1|cut -f1 -d':'` +# insert/append after before.rules line number and increment +sed -i "$BRLINE""a # allow forwarding for trusted network, for wireguard" /etc/ufw/before.rules +BRLINE=$((BRLINE+1)) +sed -i "$BRLINE""a -A ufw-before-forward -s 10.96.0.0/12 -j ACCEPT" /etc/ufw/before.rules +BRLINE=$((BRLINE+1)) +sed -i "$BRLINE""a -A ufw-before-forward -d 10.96.0.0/12 -j ACCEPT" /etc/ufw/before.rules +# append to the end of before.rules +echo >> /etc/ufw/before.rules +echo "# NAT table rules" >> /etc/ufw/before.rules +echo "*nat" >> /etc/ufw/before.rules +echo ":POSTROUTING ACCEPT [0:0]" >> /etc/ufw/before.rules +echo "-A POSTROUTING -o eth0 -j MASQUERADE" >> /etc/ufw/before.rules +echo >> /etc/ufw/before.rules +echo "# End each table with the 'COMMIT' line or these rules won't be processed" >> /etc/ufw/before.rules +echo "COMMIT" >> /etc/ufw/before.rules + +ufw enable + +# install & configure wireguard +apt -y install net-tools wireguard wireguard-tools qrencode + +# this will be the private network used by wireguard server & clients +# Network: 10.96.0.0/12 +# Address: 10.96.0.1 +# Netmask: 255.240.0.0 = 12 +# Wildcard: 0.15.255.255 +# Broadcast: 10.111.255.255 +# HostMin: 10.96.0.1 +# HostMax: 10.111.255.254 +# Hosts/Net: 1048574 (Private Internet) + +# set temp umask for creating wiregaurd configs +UMASK=`umask` +umask 0077 +# create keys +wg genkey > /etc/wireguard/.privatekey +cat /etc/wireguard/.privatekey | wg pubkey > /etc/wireguard/.publickey +# Generate wg0.conf +echo "[Interface]" >> /etc/wireguard/wg0.conf +echo "Address = 10.96.0.1/12" >> /etc/wireguard/wg0.conf +echo "ListenPort = 51820" >> /etc/wireguard/wg0.conf +echo "PrivateKey = "$(cat /etc/wireguard/.privatekey) >> /etc/wireguard/wg0.conf +echo "SaveConfig = true" >> /etc/wireguard/wg0.conf +echo >> /etc/wireguard/wg0.conf +# make backup copy of initial wg0.conf. can be used to reset server config +# and optionally re-enable peers if anything gets fubared +cp /etc/wireguard/wg0.conf /etc/wireguard/.wg0.conf +# make sure perms are correct. redundant, umask should have taken care of this +chmod 600 /etc/wireguard/* +chmod 600 /etc/wireguard/.wg0.conf + +# create dirs for client & peer configs +install --owner=root --group=root --mode=700 --directory /etc/wireguard/clients +install --owner=root --group=root --mode=700 --directory /etc/wireguard/peers + +# revert umask setting +umask $UMASK + +systemctl enable wg-quick@wg0.service +systemctl start wg-quick@wg0.service + +# set up wireguard timer for wg-cron.sh +# removes inactive peers (clients) endpoint (last connected IP) data from wireguard +# /usr/lib/systemd/system/wg-cron.timer +echo '[Unit]' > /usr/lib/systemd/system/wg-cron.timer +echo 'Description=wiregaurd cron every 5 minutes' >> /usr/lib/systemd/system/wg-cron.timer +echo '' >> /usr/lib/systemd/system/wg-cron.timer +echo '[Timer]' >> /usr/lib/systemd/system/wg-cron.timer +echo 'OnCalendar=*:0/5' >> /usr/lib/systemd/system/wg-cron.timer +echo 'Unit=wg-cron.service' >> /usr/lib/systemd/system/wg-cron.timer +echo '' >> /usr/lib/systemd/system/wg-cron.timer +echo '[Install]' >> /usr/lib/systemd/system/wg-cron.timer +echo 'WantedBy=multi-user.target' >> /usr/lib/systemd/system/wg-cron.timer +# /usr/lib/systemd/system/wg-cron.service +echo '[Unit]' > /usr/lib/systemd/system/wg-cron.service +echo 'Description=wireguard cron' >> /usr/lib/systemd/system/wg-cron.service +echo '' >> /usr/lib/systemd/system/wg-cron.service +echo '[Service]' >> /usr/lib/systemd/system/wg-cron.service +echo 'Type=simple' >> /usr/lib/systemd/system/wg-cron.service +echo 'ExecStart=/usr/local/sbin/wg-cron.sh' >> /usr/lib/systemd/system/wg-cron.service +echo '' >> /usr/lib/systemd/system/wg-cron.service +echo '[Install]' >> /usr/lib/systemd/system/wg-cron.service +echo 'WantedBy=multi-user.target' >> /usr/lib/systemd/system/wg-cron.service +# enable wg-cront.timer +systemctl daemon-reload +systemctl enable wg-cron.timer +systemctl start wg-cron.timer + +# install wg-*.sh scripts in to /usr/local/sbin/ +cp wg-*.sh /usr/local/sbin/ +chmod 755 /usr/local/sbin/wg-*.sh + +# display installation confirmation message +echo "WireGuard is now installed and configured and running." +echo "You can begin adding clients with the wg-client-add.sh script." + +# display instructions for enabling email notifications +echo "" +echo "To route system emails and to enable unattended upgrade notifications" +echo "run these two commands, replacing user@example.com with your email address." +echo "" +echo "echo \"root: user@example.com\" >> /etc/aliases" +echo "sed -i 's|//Unattended-Upgrade::Mail \"\";|Unattended-Upgrade::Mail \"user@example.com\";|g' /etc/apt/apt.conf.d/50unattended-upgrades" diff --git a/wg-peer-audit.sh b/wg-peer-audit.sh new file mode 100755 index 0000000..738e611 --- /dev/null +++ b/wg-peer-audit.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# wireguard-stack +# A set of bash scripts for installing and managing a WireGuard VPN server. +# https://git.stack-source.com/msb/wireguard-stack +# MIT License Copyright (c) 2021 Matthew Saunders Brown +# +# wg-peer-audit.sh +# check that peer config file exists for all currently active peers +# this is basis of a "cleanup" script to remove configs for invalid +# old or deleted clients + +# require root +if [ "${EUID}" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# get all peers in running wireguard server +peers=($(wg|grep peer|cut -d ' ' -f 2)) + +# get number of peers found above +peersCount=${#peers[@]} + +# if any peers found cycle through them +if [ $peersCount -gt 0 ]; then + + for (( i=0; i<${peersCount}; i++ )); + do + grep -q ${peers[$i]} /etc/wireguard/peers/*.conf + match=$? + if [[ $match != 0 ]]; then + echo "did not find peer config for: ${peers[$i]}" + echo "consider removing peer now" + #wg set wg0 peer ${peers[$i]} remove + #wg-quick save wg0 + fi + done + +fi