awg-manager/wg-manager.sh
2022-12-13 21:44:19 +03:00

233 lines
5.3 KiB
Bash
Executable File

#!/bin/bash -e
APP=$(basename $0)
LOCKFILE="/tmp/$APP.lock"
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
if ! ln -s $APP $LOCKFILE 2>/dev/null; then
echo "ERROR: script LOCKED" >&2
exit 15
fi
function usage {
echo "Usage: $0 [<options>] [command [arg]]"
echo "Options:"
echo " -i : Init (Create server keys and configs)"
echo " -c : Create new user"
echo " -d : Delete user"
echo " -L : Lock user"
echo " -U : Unlock user"
echo " -p : Print user config"
echo " -q : Print user QR code"
echo " -u <user> : User identifier (uniq field for vpn account)"
echo " -s <server> : Server host for user connection"
echo " -I : Interface (default auto)"
echo " -h : Usage"
exit 1
}
unset USER
umask 0077
HOME_DIR="/etc/wireguard"
SERVER_NAME="wg-server"
SERVER_IP_PREFIX="10.10.10"
SERVER_PORT=39547
SERVER_INTERFACE=$(ip route | grep default | sed 's/.* dev //;s/ .*//')
while getopts ":icdpqhLUu:I:s:" opt; do
case $opt in
i) INIT=1 ;;
c) CREATE=1 ;;
d) DELETE=1 ;;
L) LOCK=1 ;;
U) UNLOCK=1 ;;
p) PRINT_USER_CONFIG=1 ;;
q) PRINT_QR_CODE=1 ;;
u) USER="$OPTARG" ;;
I) SERVER_INTERFACE="$OPTARG" ;;
h) usage ;;
s) SERVER_ENDPOINT="$OPTARG" ;;
\?) echo "Invalid option: -$OPTARG" ; exit 1 ;;
:) echo "Option -$OPTARG requires an argument" ; exit 1 ;;
esac
done
[ $# -lt 1 ] && usage
function reload_server {
wg syncconf ${SERVER_NAME} <(wg-quick strip ${SERVER_NAME})
}
function get_new_ip {
LAST_IP=$[$(cat "keys/.last_ip") + 1]
if [ $LAST_IP -gt 255 ]; then
echo "ERROR: can't determine new address" >&2
exit 3
fi
echo -n "${LAST_IP}" > "keys/.last_ip"
echo "${SERVER_IP_PREFIX}.${LAST_IP}/32"
}
function add_user_to_server {
if [ ! -f "keys/${USER}/public.key" ]; then
echo "ERROR: User not exists" >&2
exit 1
fi
local USER_PUB_KEY=$(cat "keys/${USER}/public.key")
local USER_IP=$(grep -i Address "keys/${USER}/${USER}.conf" | sed 's/Address\s*=\s*//i; s/\/.*//')
if grep "# BEGIN ${USER}$" "$SERVER_NAME.conf" >/dev/null ; then
echo "User already exists"
exit 0
fi
cat <<EOF >> "$SERVER_NAME.conf"
# BEGIN ${USER}
[Peer]
PublicKey = ${USER_PUB_KEY}
AllowedIPs = ${USER_IP}
# END ${USER}
EOF
ip -4 route add ${USER_IP}/32 dev ${SERVER_NAME} || true
}
function remove_user_from_server {
sed -i "/# BEGIN ${USER}$/,/# END ${USER}$/d" "$SERVER_NAME.conf"
if [ -f "keys/${USER}/${USER}.conf" ]; then
local USER_IP=$(grep -i Address "keys/${USER}/${USER}.conf" | sed 's/Address\s*=\s*//i; s/\/.*//')
ip -4 route del ${USER_IP}/32 dev ${SERVER_NAME} || true
fi
}
function init {
if [ -z "$SERVER_ENDPOINT" ]; then
echo "ERROR: Server required" >&2
exit 1
fi
if [ -z "$SERVER_INTERFACE" ]; then
echo "ERROR: Can't determine server interface" >&2
echo "DEBUG: 'ip route':"
ip route
exit 1
fi
echo "Interface: $SERVER_INTERFACE"
mkdir -p "keys/${SERVER_NAME}"
echo -n "$SERVER_ENDPOINT" > "keys/.server"
if [ ! -f "keys/${SERVER_NAME}/private.key" ]; then
echo -n "1" > "keys/.last_ip"
wg genkey | tee "keys/${SERVER_NAME}/private.key" | wg pubkey > "keys/${SERVER_NAME}/public.key"
fi
SERVER_PVT_KEY=$(cat "keys/$SERVER_NAME/private.key")
cat <<EOF > "$SERVER_NAME.conf"
[Interface]
Address = ${SERVER_IP_PREFIX}.1/32
ListenPort = ${SERVER_PORT}
PrivateKey = ${SERVER_PVT_KEY}
PostUp = iptables -P FORWARD ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o ${SERVER_INTERFACE} -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o ${SERVER_INTERFACE} -j MASQUERADE
EOF
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
sysctl -p
systemctl enable wg-quick@${SERVER_NAME}
wg-quick up ${SERVER_NAME} || true
echo "Server initialized successfully"
exit 0
}
function create {
if [ -f "keys/${USER}/${USER}.conf" ]; then
echo "ERROR: user already exists" >&2
exit 1
fi
SERVER_ENDPOINT=$(cat "keys/.server")
USER_IP=$( get_new_ip )
mkdir "keys/${USER}"
wg genkey | tee "keys/${USER}/private.key" | wg pubkey > "keys/${USER}/public.key"
USER_PVT_KEY=$(cat "keys/${USER}/private.key")
USER_PUB_KEY=$(cat "keys/${USER}/public.key")
SERVER_PUB_KEY=$(cat "keys/$SERVER_NAME/public.key")
cat <<EOF > "keys/${USER}/${USER}.conf"
[Interface]
Address = ${USER_IP}
PrivateKey = ${USER_PVT_KEY}
DNS = 8.8.8.8
[Peer]
PublicKey = ${SERVER_PUB_KEY}
Endpoint = ${SERVER_ENDPOINT}:${SERVER_PORT}
PersistentKeepalive = 20
AllowedIPs = 0.0.0.0/0
EOF
add_user_to_server
reload_server
}
cd $HOME_DIR
if [ $INIT ]; then
init
exit 0;
fi
if [ ! -f "keys/$SERVER_NAME/public.key" ]; then
echo "ERROR: Run init script before" >&2
exit 2
fi
if [ -z "${USER}" ]; then
echo "ERROR: User required" >&2
exit 1
fi
if [ $CREATE ]; then
create
fi
if [ $DELETE ]; then
remove_user_from_server
reload_server
rm -rf "keys/${USER}"
exit 0
fi
if [ $LOCK ]; then
remove_user_from_server
reload_server
exit 0
fi
if [ $UNLOCK ]; then
add_user_to_server
reload_server
exit 0
fi
if [ $PRINT_USER_CONFIG ]; then
cat "keys/${USER}/${USER}.conf"
elif [ $PRINT_QR_CODE ]; then
qrencode -t ansiutf8 < "keys/${USER}/${USER}.conf"
fi
exit 0