Add initial files
This commit is contained in:
Executable
+200
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
WG_INTERFACE="wg0"
|
||||
WG_CONF="/etc/wireguard/${WG_INTERFACE}.conf"
|
||||
WG_DIR="/etc/wireguard"
|
||||
CLIENT_DIR="${WG_DIR}/clients"
|
||||
SERVER_PORT="51820"
|
||||
DEFAULT_ENDPOINT="37.26.136.232"
|
||||
SERVER_VPN_IP="10.9.0.1"
|
||||
VPN_SUBNET_PREFIX="10.9.0"
|
||||
START_HOST="2"
|
||||
END_HOST="254"
|
||||
USE_IPV6="0"
|
||||
IPV6_PREFIX="fd05:13:53::"
|
||||
|
||||
umask 077
|
||||
|
||||
die() {
|
||||
echo "Ошибка: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || die "Не найдена команда: $1"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Использование:
|
||||
sudo $0 CLIENT_NAME [ENDPOINT]
|
||||
|
||||
Примеры:
|
||||
sudo $0 android-phone
|
||||
sudo $0 work-laptop vpn.example.com
|
||||
sudo $0 user5 37.26.136.232
|
||||
|
||||
Что делает:
|
||||
- создаёт ключи клиента
|
||||
- подбирает следующий свободный IP
|
||||
- добавляет peer в ${WG_CONF}
|
||||
- создаёт клиентский конфиг в ${CLIENT_DIR}
|
||||
- применяет конфиг WireGuard
|
||||
EOF
|
||||
}
|
||||
|
||||
[[ $# -ge 1 ]] || { usage; exit 1; }
|
||||
|
||||
CLIENT_NAME="$1"
|
||||
ENDPOINT="${2:-$DEFAULT_ENDPOINT}"
|
||||
|
||||
[[ "$EUID" -eq 0 ]] || die "Скрипт нужно запускать через sudo/root"
|
||||
[[ -f "$WG_CONF" ]] || die "Не найден конфиг ${WG_CONF}"
|
||||
|
||||
need_cmd wg
|
||||
need_cmd awk
|
||||
need_cmd grep
|
||||
need_cmd sed
|
||||
need_cmd sort
|
||||
need_cmd tee
|
||||
need_cmd mkdir
|
||||
need_cmd chmod
|
||||
|
||||
mkdir -p "$CLIENT_DIR"
|
||||
|
||||
if [[ ! "$CLIENT_NAME" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
||||
die "Имя клиента может содержать только буквы, цифры, точку, подчёркивание и дефис"
|
||||
fi
|
||||
|
||||
CLIENT_CONF="${CLIENT_DIR}/${WG_INTERFACE}-client-${CLIENT_NAME}.conf"
|
||||
CLIENT_PRIVKEY_FILE="${CLIENT_DIR}/${CLIENT_NAME}.key"
|
||||
CLIENT_PUBKEY_FILE="${CLIENT_DIR}/${CLIENT_NAME}.pub"
|
||||
CLIENT_PSK_FILE="${CLIENT_DIR}/${CLIENT_NAME}.psk"
|
||||
|
||||
if grep -qE "^### Client ${CLIENT_NAME}$" "$WG_CONF"; then
|
||||
die "Клиент с именем '${CLIENT_NAME}' уже есть в ${WG_CONF}"
|
||||
fi
|
||||
|
||||
if [[ -e "$CLIENT_CONF" || -e "$CLIENT_PRIVKEY_FILE" || -e "$CLIENT_PUBKEY_FILE" || -e "$CLIENT_PSK_FILE" ]]; then
|
||||
die "Файлы клиента '${CLIENT_NAME}' уже существуют в ${CLIENT_DIR}"
|
||||
fi
|
||||
|
||||
|
||||
find_next_ipv4() {
|
||||
local used host
|
||||
used="$(
|
||||
grep -oE "${VPN_SUBNET_PREFIX//./\\.}\.[0-9]+/32" "$WG_CONF" \
|
||||
| sed 's#/32##' \
|
||||
| awk -F. '{print $4}' \
|
||||
| sort -n \
|
||||
| uniq
|
||||
)"
|
||||
|
||||
for host in $(seq "$START_HOST" "$END_HOST"); do
|
||||
if ! grep -qx "$host" <<<"$used"; then
|
||||
echo "${VPN_SUBNET_PREFIX}.${host}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
CLIENT_IPV4="$(find_next_ipv4)" || die "Не удалось найти свободный IPv4 адрес"
|
||||
CLIENT_HOST_OCTET="${CLIENT_IPV4##*.}"
|
||||
|
||||
if [[ "$USE_IPV6" == "1" ]]; then
|
||||
CLIENT_IPV6="${IPV6_PREFIX}${CLIENT_HOST_OCTET}"
|
||||
fi
|
||||
|
||||
echo "Создаю клиента: ${CLIENT_NAME}"
|
||||
echo "IPv4 клиента: ${CLIENT_IPV4}"
|
||||
if [[ "$USE_IPV6" == "1" ]]; then
|
||||
echo "IPv6 клиента: ${CLIENT_IPV6}"
|
||||
fi
|
||||
|
||||
wg genkey | tee "$CLIENT_PRIVKEY_FILE" | wg pubkey > "$CLIENT_PUBKEY_FILE"
|
||||
wg genpsk > "$CLIENT_PSK_FILE"
|
||||
|
||||
chmod 600 "$CLIENT_PRIVKEY_FILE" "$CLIENT_PUBKEY_FILE" "$CLIENT_PSK_FILE"
|
||||
|
||||
CLIENT_PRIVATE_KEY="$(cat "$CLIENT_PRIVKEY_FILE")"
|
||||
CLIENT_PUBLIC_KEY="$(cat "$CLIENT_PUBKEY_FILE")"
|
||||
CLIENT_PRESHARED_KEY="$(cat "$CLIENT_PSK_FILE")"
|
||||
|
||||
if command -v wg >/dev/null 2>&1 && wg show "$WG_INTERFACE" >/dev/null 2>&1; then
|
||||
SERVER_PUBLIC_KEY="$(wg show "$WG_INTERFACE" public-key)"
|
||||
else
|
||||
SERVER_PUBLIC_KEY="$(wg pubkey < <(grep '^PrivateKey *= *' "$WG_CONF" | head -n1 | awk -F'=' '{gsub(/ /,"",$2); print $2}'))"
|
||||
fi
|
||||
|
||||
TMP_PEER_FILE="$(mktemp)"
|
||||
trap 'rm -f "$TMP_PEER_FILE"' EXIT
|
||||
|
||||
{
|
||||
echo
|
||||
echo "### Client ${CLIENT_NAME}"
|
||||
echo "[Peer]"
|
||||
echo "PublicKey = ${CLIENT_PUBLIC_KEY}"
|
||||
echo "PresharedKey = ${CLIENT_PRESHARED_KEY}"
|
||||
if [[ "$USE_IPV6" == "1" ]]; then
|
||||
echo "AllowedIPs = ${CLIENT_IPV4}/32,${CLIENT_IPV6}/128"
|
||||
else
|
||||
echo "AllowedIPs = ${CLIENT_IPV4}/32"
|
||||
fi
|
||||
} > "$TMP_PEER_FILE"
|
||||
|
||||
cat "$TMP_PEER_FILE" >> "$WG_CONF"
|
||||
|
||||
if [[ "$USE_IPV6" == "1" ]]; then
|
||||
CLIENT_ADDRESS="${CLIENT_IPV4}/32,${CLIENT_IPV6}/128"
|
||||
CLIENT_ALLOWED_IPS="0.0.0.0/0,::/0"
|
||||
else
|
||||
CLIENT_ADDRESS="${CLIENT_IPV4}/32"
|
||||
CLIENT_ALLOWED_IPS="0.0.0.0/0"
|
||||
fi
|
||||
|
||||
cat > "$CLIENT_CONF" <<EOF
|
||||
[Interface]
|
||||
PrivateKey = ${CLIENT_PRIVATE_KEY}
|
||||
Address = ${CLIENT_ADDRESS}
|
||||
DNS = ${SERVER_VPN_IP},192.168.0.200
|
||||
|
||||
[Peer]
|
||||
PublicKey = ${SERVER_PUBLIC_KEY}
|
||||
PresharedKey = ${CLIENT_PRESHARED_KEY}
|
||||
Endpoint = ${ENDPOINT}:${SERVER_PORT}
|
||||
AllowedIPs = ${CLIENT_ALLOWED_IPS}
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
chmod 600 "$CLIENT_CONF"
|
||||
|
||||
echo "Применяю конфиг WireGuard..."
|
||||
wg syncconf "$WG_INTERFACE" <(wg-quick strip "$WG_INTERFACE")
|
||||
|
||||
echo
|
||||
echo "Готово."
|
||||
echo "Клиент: ${CLIENT_NAME}"
|
||||
echo "IP: ${CLIENT_IPV4}"
|
||||
echo "Конфиг: ${CLIENT_CONF}"
|
||||
echo
|
||||
|
||||
if command -v qrencode >/dev/null 2>&1; then
|
||||
echo "QR-код для клиента:"
|
||||
qrencode -t ansiutf8 < "$CLIENT_CONF"
|
||||
echo
|
||||
else
|
||||
echo "Пакет qrencode не установлен, QR-код не напечатан."
|
||||
echo "Установить можно так:"
|
||||
echo " sudo apt update && sudo apt install -y qrencode"
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "Проверка:"
|
||||
echo " sudo wg show ${WG_INTERFACE}"
|
||||
echo
|
||||
echo "Передать клиенту файл:"
|
||||
echo " ${CLIENT_CONF}"
|
||||
Reference in New Issue
Block a user