Add files installer

This commit is contained in:
Varckin 2024-08-14 15:11:24 +03:00 committed by GitHub
commit d8528fcad4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 713 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Markus Varckin
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 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.

44
README.md Normal file
View File

@ -0,0 +1,44 @@
# AmneziaWG installer
**This project is a bash script that aims to setup a [AmneziaWG](https://docs.amnezia.org/ru/documentation/amnezia-wg/) VPN on a Linux server, as easily as possible!**
## Requirements
Supported distributions:
- AlmaLinux >= 9
- Debian >= 11
- Rocky Linux >= 9
- Ubuntu >= 22.04
others can work but not tested
2Gb of free space is required for temporary files.
## Usage
Before installation it is strictly recommended to upgrade your system to the latest available version and perform the reboot afterwards.
Use curl or wget to download the script:
```bash
curl -O https://github.com/Varckin/AmneziaWG-Install/main/amneziawg-install.sh
```
```bash
wget https://github.com/Varckin/AmneziaWG-Install/main/amneziawg-install.sh
```
Set permissions:
```bash
chmod +x amneziawg-install.sh
```
And execute:
```bash
./amneziawg-install.sh
```
Answer the questions asked by the script and it will take care of the rest.
It will install AmneziaWG (kernel module and tools) on the server, configure it, create a systemd service and a client configuration file.
Run the script again to add or remove clients!

648
amneziawg-install.sh Normal file
View File

@ -0,0 +1,648 @@
#!/bin/bash
# AmneziaWG server installer
# https://github.com/Varckin/AmneziaWG-Install
RED='\033[0;31m'
ORANGE='\033[0;33m'
GREEN='\033[0;32m'
NC='\033[0m'
AMNEZIAWG_DIR="/etc/amnezia/amneziawg"
function isRoot() {
if [ "${EUID}" -ne 0 ]; then
echo "You need to run this script as root"
exit 1
fi
}
function checkVirt() {
if [ "$(systemd-detect-virt)" == "openvz" ]; then
echo "OpenVZ is not supported"
exit 1
fi
if [ "$(systemd-detect-virt)" == "lxc" ]; then
echo "LXC is not supported (yet)."
echo "WireGuard can technically run in an LXC container,"
echo "but the kernel module has to be installed on the host,"
echo "the container has to be run with some specific parameters"
echo "and only the tools need to be installed in the container."
exit 1
fi
}
function checkOS() {
source /etc/os-release
OS="${ID}"
if [[ ${OS} == "debian" || ${OS} == "raspbian" ]]; then
if [[ ${VERSION_ID} -lt 11 ]]; then
echo "Your version of Debian (${VERSION_ID}) is not supported. Please use Debian 11 Bullseye or later"
exit 1
fi
OS=debian # overwrite if raspbian
elif [[ ${OS} == "ubuntu" ]]; then
RELEASE_YEAR=$(echo "${VERSION_ID}" | cut -d'.' -f1)
if [[ ${RELEASE_YEAR} -lt 20 ]]; then
echo "Your version of Ubuntu (${VERSION_ID}) is not supported. Please use Ubuntu 20.04 or later"
exit 1
fi
elif [[ ${OS} == "fedora" ]]; then
if [[ ${VERSION_ID} -lt 39 ]]; then
echo "Your version of Fedora (${VERSION_ID}) is not supported. Please use Fedora 39 or later"
exit 1
fi
elif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then
if [[ ${VERSION_ID} == 7* ]] || [[ ${VERSION_ID} == 8* ]]; then
echo "Your version of CentOS (${VERSION_ID}) is not supported. Please use CentOS 9 or later"
exit 1
fi
else
echo "Looks like you aren't running this installer on a Debian, Ubuntu, Fedora, CentOS, AlmaLinux or Rocky Linux system"
exit 1
fi
}
function getHomeDirForClient() {
local CLIENT_NAME=$1
if [ -z "${CLIENT_NAME}" ]; then
echo "Error: getHomeDirForClient() requires a client name as argument"
exit 1
fi
# Home directory of the user, where the client configuration will be written
if [ -e "/home/${CLIENT_NAME}" ]; then
# if $1 is a user name
HOME_DIR="/home/${CLIENT_NAME}"
elif [ "${SUDO_USER}" ]; then
# if not, use SUDO_USER
if [ "${SUDO_USER}" == "root" ]; then
# If running sudo as root
HOME_DIR="/root"
else
HOME_DIR="/home/${SUDO_USER}"
fi
else
# if not SUDO_USER, use /root
HOME_DIR="/root"
fi
echo "$HOME_DIR"
}
function initialCheck() {
isRoot
checkVirt
checkOS
}
function readJminAndJmax() {
SERVER_AWG_JMIN=0
SERVER_AWG_JMAX=0
until [[ ${SERVER_AWG_JMIN} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_JMIN} >= 1 )) && (( ${SERVER_AWG_JMIN} <= 1280 )); do
read -rp "Server AmneziaWG Jmin [1-1280]: " -e -i 50 SERVER_AWG_JMIN
done
until [[ ${SERVER_AWG_JMAX} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_JMAX} >= 1 )) && (( ${SERVER_AWG_JMAX} <= 1280 )); do
read -rp "Server AmneziaWG Jmax [1-1280]: " -e -i 1000 SERVER_AWG_JMAX
done
}
function generateS1AndS2() {
RANDOM_AWG_S1=$(shuf -i15-150 -n1)
RANDOM_AWG_S2=$(shuf -i15-150 -n1)
}
function readS1AndS2() {
SERVER_AWG_S1=0
SERVER_AWG_S2=0
until [[ ${SERVER_AWG_S1} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_S1} >= 15 )) && (( ${SERVER_AWG_S1} <= 150 )); do
read -rp "Server AmneziaWG S1 [15-150]: " -e -i ${RANDOM_AWG_S1} SERVER_AWG_S1
done
until [[ ${SERVER_AWG_S2} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_S2} >= 15 )) && (( ${SERVER_AWG_S2} <= 150 )); do
read -rp "Server AmneziaWG S2 [15-150]: " -e -i ${RANDOM_AWG_S2} SERVER_AWG_S2
done
}
function generateH1AndH2AndH3AndH4() {
RANDOM_AWG_H1=$(shuf -i5-2147483647 -n1)
RANDOM_AWG_H2=$(shuf -i5-2147483647 -n1)
RANDOM_AWG_H3=$(shuf -i5-2147483647 -n1)
RANDOM_AWG_H4=$(shuf -i5-2147483647 -n1)
}
function readH1AndH2AndH3AndH4() {
SERVER_AWG_H1=0
SERVER_AWG_H2=0
SERVER_AWG_H3=0
SERVER_AWG_H4=0
until [[ ${SERVER_AWG_H1} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_H1} >= 5 )) && (( ${SERVER_AWG_H1} <= 2147483647 )); do
read -rp "Server AmneziaWG H1 [5-2147483647]: " -e -i ${RANDOM_AWG_H1} SERVER_AWG_H1
done
until [[ ${SERVER_AWG_H2} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_H2} >= 5 )) && (( ${SERVER_AWG_H2} <= 2147483647 )); do
read -rp "Server AmneziaWG H2 [5-2147483647]: " -e -i ${RANDOM_AWG_H2} SERVER_AWG_H2
done
until [[ ${SERVER_AWG_H3} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_H3} >= 5 )) && (( ${SERVER_AWG_H3} <= 2147483647 )); do
read -rp "Server AmneziaWG H3 [5-2147483647]: " -e -i ${RANDOM_AWG_H3} SERVER_AWG_H3
done
until [[ ${SERVER_AWG_H4} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_H4} >= 5 )) && (( ${SERVER_AWG_H4} <= 2147483647 )); do
read -rp "Server AmneziaWG H4 [5-2147483647]: " -e -i ${RANDOM_AWG_H4} SERVER_AWG_H4
done
}
function installQuestions() {
echo "AmneziaWG server installer (https://github.com/Varckin/AmneziaWG-Install)"
echo ""
echo "I need to ask you a few questions before starting the setup."
echo "You can keep the default options and just press enter if you are ok with them."
echo ""
# Detect public IPv4 or IPv6 address and pre-fill for the user
SERVER_PUB_IP=$(ip -4 addr | sed -ne 's|^.* inet \([^/]*\)/.* scope global.*$|\1|p' | awk '{print $1}' | head -1)
if [[ -z ${SERVER_PUB_IP} ]]; then
# Detect public IPv6 address
SERVER_PUB_IP=$(ip -6 addr | sed -ne 's|^.* inet6 \([^/]*\)/.* scope global.*$|\1|p' | head -1)
fi
read -rp "Public IPv4 or IPv6 address or domain: " -e -i "${SERVER_PUB_IP}" SERVER_PUB_IP
# Detect public interface and pre-fill for the user
SERVER_NIC="$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)"
until [[ ${SERVER_PUB_NIC} =~ ^[a-zA-Z0-9_]+$ ]]; do
read -rp "Public interface: " -e -i "${SERVER_NIC}" SERVER_PUB_NIC
done
until [[ ${SERVER_AWG_NIC} =~ ^[a-zA-Z0-9_]+$ && ${#SERVER_AWG_NIC} -lt 16 ]]; do
read -rp "AmneziaWG interface name: " -e -i awg0 SERVER_AWG_NIC
done
until [[ ${SERVER_AWG_IPV4} =~ ^([0-9]{1,3}\.){3} ]]; do
read -rp "Server AmneziaWG IPv4: " -e -i 10.66.66.1 SERVER_AWG_IPV4
done
until [[ ${SERVER_AWG_IPV6} =~ ^([a-f0-9]{1,4}:){3,4}: ]]; do
read -rp "Server AmneziaWG IPv6: " -e -i fd42:42:42::1 SERVER_AWG_IPV6
done
# Generate random number within private ports range
RANDOM_PORT=$(shuf -i49152-65535 -n1)
until [[ ${SERVER_PORT} =~ ^[0-9]+$ ]] && [ "${SERVER_PORT}" -ge 1 ] && [ "${SERVER_PORT}" -le 65535 ]; do
read -rp "Server AmneziaWG port [1-65535]: " -e -i "${RANDOM_PORT}" SERVER_PORT
done
# Adguard DNS by default
until [[ ${CLIENT_DNS_1} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do
read -rp "First DNS resolver to use for the clients: " -e -i 1.1.1.1 CLIENT_DNS_1
done
until [[ ${CLIENT_DNS_2} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; do
read -rp "Second DNS resolver to use for the clients (optional): " -e -i 1.0.0.1 CLIENT_DNS_2
if [[ ${CLIENT_DNS_2} == "" ]]; then
CLIENT_DNS_2="${CLIENT_DNS_1}"
fi
done
until [[ ${ALLOWED_IPS} =~ ^.+$ ]]; do
echo -e "\nAmneziaWG uses a parameter called AllowedIPs to determine what is routed over the VPN."
read -rp "Allowed IPs list for generated clients (leave default to route everything): " -e -i '0.0.0.0/0,::/0' ALLOWED_IPS
if [[ ${ALLOWED_IPS} == "" ]]; then
ALLOWED_IPS="0.0.0.0/0,::/0"
fi
done
# Jc
RANDOM_AWG_JC=$(shuf -i3-10 -n1)
until [[ ${SERVER_AWG_JC} =~ ^[0-9]+$ ]] && (( ${SERVER_AWG_JC} >= 1 )) && (( ${SERVER_AWG_JC} <= 128 )); do
read -rp "Server AmneziaWG Jc [1-128]: " -e -i ${RANDOM_AWG_JC} SERVER_AWG_JC
done
# Jmin && Jmax
readJminAndJmax
until [ "${SERVER_AWG_JMIN}" -le "${SERVER_AWG_JMAX}" ]; do
echo "AmneziaWG require Jmin < Jmax"
readJminAndJmax
done
# S1 && S2
generateS1AndS2
while (( ${RANDOM_AWG_S1} + 56 == ${RANDOM_AWG_S2} )); do
generateS1AndS2
done
readS1AndS2
while (( ${SERVER_AWG_S1} + 56 == ${SERVER_AWG_S2} )); do
echo "AmneziaWG require S1 + 56 <> S2"
readS1AndS2
done
# H1 && H2 && H3 && H4
generateH1AndH2AndH3AndH4
while (( ${RANDOM_AWG_H1} == ${RANDOM_AWG_H2} )) || (( ${RANDOM_AWG_H1} == ${RANDOM_AWG_H3} )) || (( ${RANDOM_AWG_H1} == ${RANDOM_AWG_H4} )) || (( ${RANDOM_AWG_H2} == ${RANDOM_AWG_H3} )) || (( ${RANDOM_AWG_H2} == ${RANDOM_AWG_H4} )) || (( ${RANDOM_AWG_H3} == ${RANDOM_AWG_H4} )); do
generateH1AndH2AndH3AndH4
done
readH1AndH2AndH3AndH4
while (( ${SERVER_AWG_H1} == ${SERVER_AWG_H2} )) || (( ${SERVER_AWG_H1} == ${SERVER_AWG_H3} )) || (( ${SERVER_AWG_H1} == ${SERVER_AWG_H4} )) || (( ${SERVER_AWG_H2} == ${SERVER_AWG_H3} )) || (( ${SERVER_AWG_H2} == ${SERVER_AWG_H4} )) || (( ${SERVER_AWG_H3} == ${SERVER_AWG_H4} )); do
echo "AmneziaWG require H1 and H2 and H3 and H4 be different"
readH1AndH2AndH3AndH4
done
echo ""
echo "Okay, that was all I needed. We are ready to setup your AmneziaWG server now."
echo "You will be able to generate a client at the end of the installation."
read -n1 -r -p "Press any key to continue..."
}
function installAmneziaWG() {
# Run setup questions first
installQuestions
# Install AmneziaWG tools and module
if [[ ${OS} == 'ubuntu' ]]; then
if [[ -e /etc/apt/sources.list.d/ubuntu.sources ]]; then
if ! grep -q "deb-src" /etc/apt/sources.list.d/ubuntu.sources; then
cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/amneziawg.sources
sed -i 's/deb/deb-src/' /etc/apt/sources.list.d/amneziawg.sources
fi
else
if ! grep -q "^deb-src" /etc/apt/sources.list; then
cp /etc/apt/sources.list /etc/apt/sources.list.d/amneziawg.sources.list
sed -i 's/^deb/deb-src/' /etc/apt/sources.list.d/amneziawg.sources.list
fi
fi
apt install -y software-properties-common
add-apt-repository -y ppa:amnezia/ppa
apt install -y amneziawg amneziawg-tools qrencode
elif [[ ${OS} == 'debian' ]]; then
if ! grep -q "^deb-src" /etc/apt/sources.list; then
cp /etc/apt/sources.list /etc/apt/sources.list.d/amneziawg.sources.list
sed -i 's/^deb/deb-src/' /etc/apt/sources.list.d/amneziawg.sources.list
fi
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 57290828
echo "deb https://ppa.launchpadcontent.net/amnezia/ppa/ubuntu focal main" >>/etc/apt/sources.list.d/amneziawg.sources.list
echo "deb-src https://ppa.launchpadcontent.net/amnezia/ppa/ubuntu focal main" >>/etc/apt/sources.list.d/amneziawg.sources.list
apt update
apt install -y amneziawg amneziawg-tools qrencode iptables
elif [[ ${OS} == 'fedora' ]]; then
dnf config-manager --set-enabled crb
dnf install -y epel-release
dnf copr enable -y amneziavpn/amneziawg
dnf install -y amneziawg-dkms amneziawg-tools qrencode iptables
elif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then
dnf config-manager --set-enabled crb
dnf install -y epel-release
dnf copr enable -y amneziavpn/amneziawg
dnf install -y amneziawg-dkms amneziawg-tools qrencode iptables
fi
SERVER_AWG_CONF="${AMNEZIAWG_DIR}/${SERVER_AWG_NIC}.conf"
SERVER_PRIV_KEY=$(awg genkey)
SERVER_PUB_KEY=$(echo "${SERVER_PRIV_KEY}" | awg pubkey)
# Save WireGuard settings
echo "SERVER_PUB_IP=${SERVER_PUB_IP}
SERVER_PUB_NIC=${SERVER_PUB_NIC}
SERVER_AWG_NIC=${SERVER_AWG_NIC}
SERVER_AWG_IPV4=${SERVER_AWG_IPV4}
SERVER_AWG_IPV6=${SERVER_AWG_IPV6}
SERVER_PORT=${SERVER_PORT}
SERVER_PRIV_KEY=${SERVER_PRIV_KEY}
SERVER_PUB_KEY=${SERVER_PUB_KEY}
CLIENT_DNS_1=${CLIENT_DNS_1}
CLIENT_DNS_2=${CLIENT_DNS_2}
ALLOWED_IPS=${ALLOWED_IPS}
SERVER_AWG_JC=${SERVER_AWG_JC}
SERVER_AWG_JMIN=${SERVER_AWG_JMIN}
SERVER_AWG_JMAX=${SERVER_AWG_JMAX}
SERVER_AWG_S1=${SERVER_AWG_S1}
SERVER_AWG_S2=${SERVER_AWG_S2}
SERVER_AWG_H1=${SERVER_AWG_H1}
SERVER_AWG_H2=${SERVER_AWG_H2}
SERVER_AWG_H3=${SERVER_AWG_H3}
SERVER_AWG_H4=${SERVER_AWG_H4}" >"${AMNEZIAWG_DIR}/params"
# Add server interface
echo "[Interface]
Address = ${SERVER_AWG_IPV4}/24,${SERVER_AWG_IPV6}/64
ListenPort = ${SERVER_PORT}
PrivateKey = ${SERVER_PRIV_KEY}
Jc = ${SERVER_AWG_JC}
Jmin = ${SERVER_AWG_JMIN}
Jmax = ${SERVER_AWG_JMAX}
S1 = ${SERVER_AWG_S1}
S2 = ${SERVER_AWG_S2}
H1 = ${SERVER_AWG_H1}
H2 = ${SERVER_AWG_H2}
H3 = ${SERVER_AWG_H3}
H4 = ${SERVER_AWG_H4}" >"${SERVER_AWG_CONF}"
if pgrep firewalld; then
FIREWALLD_IPV4_ADDRESS=$(echo "${SERVER_AWG_IPV4}" | cut -d"." -f1-3)".0"
FIREWALLD_IPV6_ADDRESS=$(echo "${SERVER_AWG_IPV6}" | sed 's/:[^:]*$/:0/')
echo "PostUp = firewall-cmd --add-port ${SERVER_PORT}/udp && firewall-cmd --add-rich-rule='rule family=ipv4 source address=${FIREWALLD_IPV4_ADDRESS}/24 masquerade' && firewall-cmd --add-rich-rule='rule family=ipv6 source address=${FIREWALLD_IPV6_ADDRESS}/24 masquerade'
PostDown = firewall-cmd --remove-port ${SERVER_PORT}/udp && firewall-cmd --remove-rich-rule='rule family=ipv4 source address=${FIREWALLD_IPV4_ADDRESS}/24 masquerade' && firewall-cmd --remove-rich-rule='rule family=ipv6 source address=${FIREWALLD_IPV6_ADDRESS}/24 masquerade'" >>"${SERVER_AWG_CONF}"
else
echo "PostUp = iptables -I INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT
PostUp = iptables -I FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_AWG_NIC} -j ACCEPT
PostUp = iptables -I FORWARD -i ${SERVER_AWG_NIC} -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE
PostUp = ip6tables -I INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT
PostUp = ip6tables -I FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_AWG_NIC} -j ACCEPT
PostUp = ip6tables -I FORWARD -i ${SERVER_AWG_NIC} -j ACCEPT
PostUp = ip6tables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE
PostDown = iptables -D INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT
PostDown = iptables -D FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_AWG_NIC} -j ACCEPT
PostDown = iptables -D FORWARD -i ${SERVER_AWG_NIC} -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE
PostDown = ip6tables -D INPUT -p udp --dport ${SERVER_PORT} -j ACCEPT
PostDown = ip6tables -D FORWARD -i ${SERVER_PUB_NIC} -o ${SERVER_AWG_NIC} -j ACCEPT
PostDown = ip6tables -D FORWARD -i ${SERVER_AWG_NIC} -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE" >>"${SERVER_AWG_CONF}"
fi
# Enable routing on the server
echo "net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1" >/etc/sysctl.d/awg.conf
sysctl --system
systemctl start "awg-quick@${SERVER_AWG_NIC}"
systemctl enable "awg-quick@${SERVER_AWG_NIC}"
newClient
echo -e "${GREEN}If you want to add more clients, you simply need to run this script another time!${NC}"
# Check if AmneziaWG is running
systemctl is-active --quiet "awg-quick@${SERVER_AWG_NIC}"
AWG_RUNNING=$?
# AmneziaWG might not work if we updated the kernel. Tell the user to reboot
if [[ ${AWG_RUNNING} -ne 0 ]]; then
echo -e "\n${RED}WARNING: AmneziaWG does not seem to be running.${NC}"
echo -e "${ORANGE}You can check if AmneziaWG is running with: systemctl status awg-quick@${SERVER_AWG_NIC}${NC}"
echo -e "${ORANGE}If you get something like \"Cannot find device ${SERVER_AWG_NIC}\", please reboot!${NC}"
else # AmneziaWG is running
echo -e "\n${GREEN}AmneziaWG is running.${NC}"
echo -e "${GREEN}You can check the status of AmneziaWG with: systemctl status awg-quick@${SERVER_AWG_NIC}\n\n${NC}"
echo -e "${ORANGE}If you don't have internet connectivity from your client, try to reboot the server.${NC}"
fi
}
function newClient() {
# If SERVER_PUB_IP is IPv6, add brackets if missing
if [[ ${SERVER_PUB_IP} =~ .*:.* ]]; then
if [[ ${SERVER_PUB_IP} != *"["* ]] || [[ ${SERVER_PUB_IP} != *"]"* ]]; then
SERVER_PUB_IP="[${SERVER_PUB_IP}]"
fi
fi
ENDPOINT="${SERVER_PUB_IP}:${SERVER_PORT}"
echo ""
echo "Client configuration"
echo ""
echo "The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars."
until [[ ${CLIENT_NAME} =~ ^[a-zA-Z0-9_-]+$ && ${CLIENT_EXISTS} == '0' && ${#CLIENT_NAME} -lt 16 ]]; do
read -rp "Client name: " -e CLIENT_NAME
CLIENT_EXISTS=$(grep -c -E "^### Client ${CLIENT_NAME}\$" "${SERVER_AWG_CONF}")
if [[ ${CLIENT_EXISTS} != 0 ]]; then
echo ""
echo -e "${ORANGE}A client with the specified name was already created, please choose another name.${NC}"
echo ""
fi
done
for DOT_IP in {2..254}; do
DOT_EXISTS=$(grep -c "${SERVER_AWG_IPV4::-1}${DOT_IP}" "${SERVER_AWG_CONF}")
if [[ ${DOT_EXISTS} == '0' ]]; then
break
fi
done
if [[ ${DOT_EXISTS} == '1' ]]; then
echo ""
echo "The subnet configured supports only 253 clients."
exit 1
fi
BASE_IP=$(echo "$SERVER_AWG_IPV4" | awk -F '.' '{ print $1"."$2"."$3 }')
until [[ ${IPV4_EXISTS} == '0' ]]; do
read -rp "Client AmneziaWG IPv4: ${BASE_IP}." -e -i "${DOT_IP}" DOT_IP
CLIENT_AWG_IPV4="${BASE_IP}.${DOT_IP}"
IPV4_EXISTS=$(grep -c "$CLIENT_AWG_IPV4/32" "${SERVER_AWG_CONF}")
if [[ ${IPV4_EXISTS} != 0 ]]; then
echo ""
echo -e "${ORANGE}A client with the specified IPv4 was already created, please choose another IPv4.${NC}"
echo ""
fi
done
BASE_IP=$(echo "$SERVER_AWG_IPV6" | awk -F '::' '{ print $1 }')
until [[ ${IPV6_EXISTS} == '0' ]]; do
read -rp "Client AmneziaWG IPv6: ${BASE_IP}::" -e -i "${DOT_IP}" DOT_IP
CLIENT_AWG_IPV6="${BASE_IP}::${DOT_IP}"
IPV6_EXISTS=$(grep -c "${CLIENT_AWG_IPV6}/128" "${SERVER_AWG_CONF}")
if [[ ${IPV6_EXISTS} != 0 ]]; then
echo ""
echo -e "${ORANGE}A client with the specified IPv6 was already created, please choose another IPv6.${NC}"
echo ""
fi
done
# Generate key pair for the client
CLIENT_PRIV_KEY=$(awg genkey)
CLIENT_PUB_KEY=$(echo "${CLIENT_PRIV_KEY}" | awg pubkey)
CLIENT_PRE_SHARED_KEY=$(awg genpsk)
HOME_DIR=$(getHomeDirForClient "${CLIENT_NAME}")
# Create client file and add the server as a peer
echo "[Interface]
PrivateKey = ${CLIENT_PRIV_KEY}
Address = ${CLIENT_AWG_IPV4}/32,${CLIENT_AWG_IPV6}/128
DNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}
Jc = ${SERVER_AWG_JC}
Jmin = ${SERVER_AWG_JMIN}
Jmax = ${SERVER_AWG_JMAX}
S1 = ${SERVER_AWG_S1}
S2 = ${SERVER_AWG_S2}
H1 = ${SERVER_AWG_H1}
H2 = ${SERVER_AWG_H2}
H3 = ${SERVER_AWG_H3}
H4 = ${SERVER_AWG_H4}
[Peer]
PublicKey = ${SERVER_PUB_KEY}
PresharedKey = ${CLIENT_PRE_SHARED_KEY}
Endpoint = ${ENDPOINT}
AllowedIPs = ${ALLOWED_IPS}" >"${HOME_DIR}/${SERVER_AWG_NIC}-client-${CLIENT_NAME}.conf"
# Add the client as a peer to the server
echo -e "\n### Client ${CLIENT_NAME}
[Peer]
PublicKey = ${CLIENT_PUB_KEY}
PresharedKey = ${CLIENT_PRE_SHARED_KEY}
AllowedIPs = ${CLIENT_AWG_IPV4}/32,${CLIENT_AWG_IPV6}/128" >>"${SERVER_AWG_CONF}"
awg syncconf "${SERVER_AWG_NIC}" <(awg-quick strip "${SERVER_AWG_NIC}")
# Generate QR code if qrencode is installed
if command -v qrencode &>/dev/null; then
echo -e "${GREEN}\nHere is your client config file as a QR Code:\n${NC}"
qrencode -t ansiutf8 -l L <"${HOME_DIR}/${SERVER_AWG_NIC}-client-${CLIENT_NAME}.conf"
echo ""
fi
echo -e "${GREEN}Your client config file is in ${HOME_DIR}/${SERVER_AWG_NIC}-client-${CLIENT_NAME}.conf${NC}"
}
function listClients() {
NUMBER_OF_CLIENTS=$(grep -c -E "^### Client" "${SERVER_AWG_CONF}")
if [[ ${NUMBER_OF_CLIENTS} -eq 0 ]]; then
echo ""
echo "You have no existing clients!"
exit 1
fi
grep -E "^### Client" "${SERVER_AWG_CONF}" | cut -d ' ' -f 3 | nl -s ') '
}
function revokeClient() {
NUMBER_OF_CLIENTS=$(grep -c -E "^### Client" "${SERVER_AWG_CONF}")
if [[ ${NUMBER_OF_CLIENTS} == '0' ]]; then
echo ""
echo "You have no existing clients!"
exit 1
fi
echo ""
echo "Select the existing client you want to revoke"
grep -E "^### Client" "${SERVER_AWG_CONF}" | cut -d ' ' -f 3 | nl -s ') '
until [[ ${CLIENT_NUMBER} -ge 1 && ${CLIENT_NUMBER} -le ${NUMBER_OF_CLIENTS} ]]; do
if [[ ${CLIENT_NUMBER} == '1' ]]; then
read -rp "Select one client [1]: " CLIENT_NUMBER
else
read -rp "Select one client [1-${NUMBER_OF_CLIENTS}]: " CLIENT_NUMBER
fi
done
# match the selected number to a client name
CLIENT_NAME=$(grep -E "^### Client" "${SERVER_AWG_CONF}" | cut -d ' ' -f 3 | sed -n "${CLIENT_NUMBER}"p)
# remove [Peer] block matching $CLIENT_NAME
sed -i "/^### Client ${CLIENT_NAME}\$/,/^$/d" "${SERVER_AWG_CONF}"
# remove generated client file
HOME_DIR=$(getHomeDirForClient "${CLIENT_NAME}")
rm -f "${HOME_DIR}/${SERVER_AWG_NIC}-client-${CLIENT_NAME}.conf"
# restart AmneziaWG to apply changes
awg syncconf "${SERVER_AWG_NIC}" <(awg-quick strip "${SERVER_AWG_NIC}")
}
function uninstallAmneziaWG() {
echo ""
echo -e "\n${RED}WARNING: This will uninstall AmneziaWG and remove all the configuration files!${NC}"
echo -e "${ORANGE}Please backup the /etc/amnezia/amneziawg directory if you want to keep your configuration files.\n${NC}"
read -rp "Do you really want to remove AmneziaWG? [y/n]: " -e REMOVE
REMOVE=${REMOVE:-n}
if [[ $REMOVE == 'y' ]]; then
checkOS
systemctl stop "awg-quick@${SERVER_AWG_NIC}"
systemctl disable "awg-quick@${SERVER_AWG_NIC}"
# Disable routing
rm -f /etc/sysctl.d/awg.conf
sysctl --system
# Remove config files
rm -rf ${AMNEZIAWG_DIR}/*
if [[ ${OS} == 'ubuntu' ]]; then
apt remove -y amneziawg amneziawg-tools
add-apt-repository -ry ppa:amnezia/ppa
if [[ -e /etc/apt/sources.list.d/ubuntu.sources ]]; then
rm -f /etc/apt/sources.list.d/amneziawg.sources
else
rm -f /etc/apt/sources.list.d/amneziawg.sources.list
fi
elif [[ ${OS} == 'debian' ]]; then
apt-get remove -y amneziawg amneziawg-tools
rm -f /etc/apt/sources.list.d/amneziawg.sources.list
apt-key del 57290828
apt update
elif [[ ${OS} == 'fedora' ]]; then
dnf remove -y amneziawg-dkms amneziawg-tools
dnf copr disable -y amneziavpn/amneziawg
elif [[ ${OS} == 'centos' ]] || [[ ${OS} == 'almalinux' ]] || [[ ${OS} == 'rocky' ]]; then
dnf remove -y amneziawg-dkms amneziawg-tools
dnf copr disable -y amneziavpn/amneziawg
fi
# Check if AmneziaWG is running
systemctl is-active --quiet "awg-quick@${SERVER_AWG_NIC}"
AWG_RUNNING=$?
if [[ ${AWG_RUNNING} -eq 0 ]]; then
echo "AmneziaWG failed to uninstall properly."
exit 1
else
echo "AmneziaWG uninstalled successfully."
exit 0
fi
else
echo ""
echo "Removal aborted!"
fi
}
function loadParams() {
source "${AMNEZIAWG_DIR}/params"
SERVER_AWG_CONF="${AMNEZIAWG_DIR}/${SERVER_AWG_NIC}.conf"
}
function manageMenu() {
echo "AmneziaWG server installer (https://github.com/Varckin/AmneziaWG-Install)"
echo ""
echo "It looks like AmneziaWG is already installed."
echo ""
echo "What do you want to do?"
echo " 1) Add a new user"
echo " 2) List all users"
echo " 3) Revoke existing user"
echo " 4) Uninstall AmneziaWG"
echo " 5) Exit"
until [[ ${MENU_OPTION} =~ ^[1-5]$ ]]; do
read -rp "Select an option [1-5]: " MENU_OPTION
done
case "${MENU_OPTION}" in
1)
newClient
;;
2)
listClients
;;
3)
revokeClient
;;
4)
uninstallAmneziaWG
;;
5)
exit 0
;;
esac
}
# Check for root, virt, OS...
initialCheck
# Check if AmneziaWG is already installed and load params
if [[ -e "${AMNEZIAWG_DIR}/params" ]]; then
loadParams
manageMenu
else
installAmneziaWG
fi