vpn-stack/install.sh
Matthew Saunders Brown ebc32cae86 Switch from Ubuntu to Debian compatibility with signifant reworking of code and installer.
Installer now expects Debian 12 and requires base-stack repo installed first
New systemd files
New wg-client-zip-email.sh script
Moved bash scripts into sbin dir
Install & configure firewalld instead of ufw
wg.sh now has configurable options
- DNS nameserver settings
- endpoint (FQDN or IP)
- AllowedIPs (defaults to 0.0.0.0/0)
Change the client network from 10.96.0.0/12 (1,048,574 max clients / IPs) to 10.96.0.0/16 (65,025 max clients / IPs)
2024-07-24 14:00:18 -07:00

233 lines
9.7 KiB
Bash
Executable File

#!/bin/bash
#
# vpn-stack
# A set of bash scripts for installing and managing a WireGuard VPN server.
# https://git.stack-source.com/msb/vpn-stack
# Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
# wireguard installer for Debian 12
#
# this installer expects a clean Debian 12 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 2>/dev/null`
os_release=`lsb_release -rs 2>/dev/null`
if [ $os_id != Debian ] || [ $os_release != 12 ]; then
echo "this installer only runs on Debian 12, 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
# check for / set hostname
# autodetection that should work on Debian 12
# 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 route get 1.1.1.1| head -n 1 | cut -d ' ' -f 7`
# make sure systemd-resolved is installed, and resolvconf is not installed
DEBIAN_FRONTEND=noninteractive apt-get -y purge resolvconf
DEBIAN_FRONTEND=noninteractive apt-get -y install systemd-resolved
# 1.1.1.1 (Cloudflare) DNS w/ DNS over TLS (DoT) for OS
sed -i 's|#DNS=|DNS=1.1.1.1|g' /etc/systemd/resolved.conf
sed -i 's|#FallbackDNS=|FallbackDNS=1.0.0.1|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=.*|Cache=no|g' /etc/systemd/resolved.conf
systemctl restart systemd-resolved
# configure a minimal smtp server so automated emails (cron etc) can be sent
DEBIAN_FRONTEND=noninteractive apt-get -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
# stubby DNS Privacy stub resolver for wireguard clients
DEBIAN_FRONTEND=noninteractive apt-get -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
# remove ipv6 records
sed -i '/::/d' /usr/local/etc/hosts
# dnsmasq will use adware + malware hosts file
# and listen on wireguard server private lan IP
# can be used by clients for adblocking
# create temporary policy-rc.d to stop dnsmasq from starting during install
# otherwise dnsmasq will fail to start due to ports in use and will show
# errors. not really a problem as later config resoves this, but the errors
# may cause concern for users running the install
install -m 755 /dev/null /usr/sbin/policy-rc.d
echo '#!/bin/sh' > /usr/sbin/policy-rc.d
echo 'exit 101' >> /usr/sbin/policy-rc.d
DEBIAN_FRONTEND=noninteractive apt-get -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
# remove temporary policy-rc.d
rm -f /usr/sbin/policy-rc.d
sed -i 's|After=network.target|After=wg-quick@wg0.service|g' /lib/systemd/system/dnsmasq.service
systemctl daemon-reload
# install & configure wireguard
DEBIAN_FRONTEND=noninteractive apt-get -y install net-tools wireguard wireguard-tools qrencode zip
# this will be the private network used by wireguard server & clients
# Network: 10.96.0.0/16
# Address: 10.96.0.1
# Netmask: 255.255.0.0
# Wildcard: 0.0.255.255
# Broadcast: 10.96.255.255
# HostMin: 10.96.0.1
# HostMax: 10.96.255.254
# Hosts/Net: 65025 (Private Internet)
# 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/16" >> /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
systemctl restart dnsmasq.service
# install wg*.sh scripts in to /usr/local/sbin/
cp sbin/wg*.sh /usr/local/sbin/
chmod 755 /usr/local/sbin/wg*.sh
# set up wireguard timer for wg-cron.sh
# removes inactive peers (clients) endpoint (last connected IP) data from wireguard
mkdir -p /usr/local/lib/systemd/system
cp systemd/wg-cron.* /usr/local/lib/systemd/system/
chmod 644 /usr/local/lib/systemd/system/wg-cron.*
systemctl daemon-reload
systemctl enable wg-cron.timer
systemctl start wg-cron.timer
# get public interface (e.g. eth0, enp0s10, etc.) for adding to firewall config
INTERFACE=$(ip route get 1.1.1.1 | sed -n 's/.*dev \([^\ ]*\).*/\1/p')
# configure firewalld
if [[ -f /etc/firewalld/zones/public.xml ]]; then
rm /etc/firewalld/zones/public.xml
firewall-cmd --reload
fi
firewall-cmd --permanent --zone=external --add-interface=$INTERFACE
firewall-cmd --permanent --zone=external --add-service=wireguard
firewall-cmd --permanent --zone=internal --add-interface=wg0
firewall-cmd --permanent --zone=internal --add-service=dns
firewall-cmd --permanent --zone=internal --remove-service=mdns
firewall-cmd --permanent --zone=internal --remove-service=samba-client
firewall-cmd --permanent --zone=internal --remove-service=dhcpv6-client
# configure cross-zone forwarding
firewall-cmd --permanent --new-policy=internal2external
firewall-cmd --permanent --policy=internal2external --set-target=ACCEPT
firewall-cmd --permanent --policy=internal2external --add-ingress-zone=internal
firewall-cmd --permanent --policy=internal2external --add-egress-zone=external
firewall-cmd --reload
# configure draconian ssh failure blocking
sed -i "s|maxretry.*|maxretry = 1|g" /etc/fail2ban/jail.d/defaults-debian.conf
systemctl restart fail2ban
# 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."
echo ""
echo "Reasonable defaults have been set. There are a couple of adjustable"
echo "settings in /usr/local/sbin/wg.sh if you need to customize your installation."
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"