mirror of
https://github.com/andrey271192/amnezia_web-PRO.git
synced 2026-09-20 14:42:00 +00:00
feat: Cloudflare WARP routing for AmneziaWG
Web toggles per IPv4 peer; wgcf install script on host (no Telegram/QR). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
252
scripts/warp-amnezia.sh
Executable file
252
scripts/warp-amnezia.sh
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env bash
|
||||
# Cloudflare WARP внутри контейнера AmneziaWG (wgcf → warp.conf → wg-quick).
|
||||
# Запускать на хосте VPS от root. Без Telegram и без QR — только установка и обслуживание туннеля WARP.
|
||||
# После install управление «кто выходит через WARP» — в веб-панели Amnezia Admin (раздел WARP).
|
||||
set -euo pipefail
|
||||
|
||||
WGCF_VERSION="${WGCF_VERSION:-2.2.30}"
|
||||
WGCF_BIN="${WGCF_BIN:-/root/wgcf}"
|
||||
WGCF_ACCOUNT="${WGCF_ACCOUNT:-/root/wgcf-account.toml}"
|
||||
WGCF_PROFILE="${WGCF_PROFILE:-/root/wgcf-profile.conf}"
|
||||
|
||||
usage() {
|
||||
echo "Использование: $0 {install|start|stop|status|rekey} [имя_контейнера]"
|
||||
echo "Переменные: AWG_CONTAINER, WARP_DIR (по умолчанию /opt/warp)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_root() {
|
||||
if [[ "${EUID:-0}" -ne 0 ]]; then
|
||||
echo "Запустите от root."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_container() {
|
||||
local c="${2:-${AWG_CONTAINER:-}}"
|
||||
if [[ -n "$c" ]] && docker exec "$c" true 2>/dev/null; then
|
||||
CONTAINER="$c"
|
||||
return 0
|
||||
fi
|
||||
local -a found=()
|
||||
while IFS= read -r n; do found+=("$n"); done < <(docker ps --format '{{.Names}}' | grep -E '^amnezia-awg2$|^amnezia-awg$' || true)
|
||||
if [[ ${#found[@]} -eq 1 ]]; then
|
||||
CONTAINER="${found[0]}"
|
||||
return 0
|
||||
fi
|
||||
if [[ ${#found[@]} -gt 1 ]]; then
|
||||
echo "Несколько контейнеров: ${found[*]}. Укажите вторым аргументом или AWG_CONTAINER="
|
||||
exit 1
|
||||
fi
|
||||
echo "Не найден контейнер amnezia-awg / amnezia-awg2."
|
||||
exit 1
|
||||
}
|
||||
|
||||
load_paths() {
|
||||
AWG_WARP_DIR="${WARP_DIR:-/opt/warp}"
|
||||
AWG_WARP_CONF="${AWG_WARP_DIR}/warp.conf"
|
||||
AWG_VPN_CONF=""
|
||||
if docker exec "$CONTAINER" test -f /opt/amnezia/awg/awg0.conf 2>/dev/null; then
|
||||
AWG_VPN_CONF="/opt/amnezia/awg/awg0.conf"
|
||||
elif docker exec "$CONTAINER" test -f /opt/amnezia/awg/wg0.conf 2>/dev/null; then
|
||||
AWG_VPN_CONF="/opt/amnezia/awg/wg0.conf"
|
||||
else
|
||||
for f in /opt/amnezia/awg/wg0.conf /opt/amnezia/awg/awg0.conf /etc/wireguard/wg0.conf; do
|
||||
if docker exec "$CONTAINER" test -f "$f" 2>/dev/null; then
|
||||
AWG_VPN_CONF="$f"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[[ -n "$AWG_VPN_CONF" ]] || {
|
||||
echo "Не найден конфиг WireGuard/AWG в контейнере."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
install_wgcf() {
|
||||
[[ -x "$WGCF_BIN" ]] && return 0
|
||||
local arch wa
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
x86_64) wa="amd64" ;;
|
||||
aarch64 | arm64) wa="arm64" ;;
|
||||
armv7l) wa="armv7" ;;
|
||||
*) echo "Архитектура не поддерживается: $arch"; exit 1 ;;
|
||||
esac
|
||||
wget -q -O "$WGCF_BIN" "https://github.com/ViRb3/wgcf/releases/download/v${WGCF_VERSION}/wgcf_${WGCF_VERSION}_linux_${wa}"
|
||||
chmod +x "$WGCF_BIN"
|
||||
}
|
||||
|
||||
ensure_account() {
|
||||
if [[ ! -f "$WGCF_ACCOUNT" ]]; then
|
||||
echo "Регистрация WARP (wgcf register)…"
|
||||
(cd /root && yes | "$WGCF_BIN" register >/dev/null 2>&1 || true)
|
||||
fi
|
||||
[[ -f "$WGCF_ACCOUNT" ]] || {
|
||||
echo "Не создан $WGCF_ACCOUNT"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
generate_profile() {
|
||||
(cd /root && yes | "$WGCF_BIN" generate >/dev/null 2>&1 || true)
|
||||
[[ -f "$WGCF_PROFILE" ]] || {
|
||||
echo "Не создан $WGCF_PROFILE"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
resolve_endpoint() {
|
||||
local ep
|
||||
ep="$(getent ahostsv4 engage.cloudflareclient.com 2>/dev/null | awk 'NR==1{print $1}')"
|
||||
[[ -n "$ep" ]] || {
|
||||
echo "Не удалось резолвить engage.cloudflareclient.com"
|
||||
exit 1
|
||||
}
|
||||
echo "$ep"
|
||||
}
|
||||
|
||||
build_warp_conf() {
|
||||
local endpoint_ip="$1"
|
||||
local pk pub addr
|
||||
pk="$(awk -F' = ' '/^PrivateKey = /{print $2}' "$WGCF_PROFILE")"
|
||||
pub="$(awk -F' = ' '/^PublicKey = /{print $2}' "$WGCF_PROFILE")"
|
||||
addr="$(awk -F' = ' '/^Address = /{print $2}' "$WGCF_PROFILE" | cut -d',' -f1)"
|
||||
docker exec "$CONTAINER" sh -c "mkdir -p '$AWG_WARP_DIR'"
|
||||
docker cp "$WGCF_PROFILE" "${CONTAINER}:${AWG_WARP_DIR}/wgcf-profile.conf" 2>/dev/null || true
|
||||
docker exec "$CONTAINER" sh -c "cat > '$AWG_WARP_CONF' <<WARPEOF
|
||||
[Interface]
|
||||
PrivateKey = ${pk}
|
||||
Address = ${addr}
|
||||
MTU = 1280
|
||||
Table = off
|
||||
|
||||
[Peer]
|
||||
PublicKey = ${pub}
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = ${endpoint_ip}:2408
|
||||
PersistentKeepalive = 25
|
||||
WARPEOF
|
||||
chmod 600 '$AWG_WARP_CONF'"
|
||||
}
|
||||
|
||||
warp_up() {
|
||||
docker exec "$CONTAINER" sh -c "wg-quick down '$AWG_WARP_CONF' >/dev/null 2>&1 || true"
|
||||
docker exec "$CONTAINER" sh -c "wg-quick up '$AWG_WARP_CONF'"
|
||||
docker exec "$CONTAINER" ip addr show warp >/dev/null 2>&1 || {
|
||||
echo "Интерфейс warp не поднялся."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
warp_down() {
|
||||
docker exec "$CONTAINER" sh -c "wg-quick down '$AWG_WARP_CONF' 2>/dev/null || true"
|
||||
}
|
||||
|
||||
is_installed() {
|
||||
docker exec "$CONTAINER" test -f "$AWG_WARP_CONF" 2>/dev/null
|
||||
}
|
||||
|
||||
is_running() {
|
||||
docker exec "$CONTAINER" ip addr show warp >/dev/null 2>&1
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
echo "Бэкап конфигов в контейнере…"
|
||||
docker exec "$CONTAINER" sh -c "
|
||||
ts=\$(date +%Y%m%d-%H%M%S)
|
||||
cp '$AWG_VPN_CONF' '${AWG_VPN_CONF}.bak-warp-'\$ts 2>/dev/null || true
|
||||
cp /opt/amnezia/start.sh /opt/amnezia/start.sh.bak-warp-\$ts 2>/dev/null || true
|
||||
true
|
||||
"
|
||||
install_wgcf
|
||||
ensure_account
|
||||
generate_profile
|
||||
local ep
|
||||
ep="$(resolve_endpoint)"
|
||||
echo "Endpoint: $ep"
|
||||
build_warp_conf "$ep"
|
||||
warp_up
|
||||
echo "Готово: WARP установлен. Управление клиентами — в веб-панели (раздел WARP)."
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
if is_installed; then
|
||||
echo "warp.conf: есть ($AWG_WARP_CONF)"
|
||||
else
|
||||
echo "warp.conf: нет — выполните: $0 install"
|
||||
exit 1
|
||||
fi
|
||||
if is_running; then
|
||||
echo "Интерфейс warp: поднят"
|
||||
docker exec "$CONTAINER" wg show warp 2>/dev/null || true
|
||||
echo -n "Внешний IP через WARP: "
|
||||
docker exec "$CONTAINER" sh -c "curl -fsS --interface warp --connect-timeout 4 https://ifconfig.me 2>/dev/null || echo '?'"
|
||||
echo
|
||||
else
|
||||
echo "Интерфейс warp: опущен ($0 start)"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_rekey() {
|
||||
is_installed || {
|
||||
echo "Сначала install."
|
||||
exit 1
|
||||
}
|
||||
warp_down || true
|
||||
rm -f "$WGCF_ACCOUNT"
|
||||
ensure_account
|
||||
generate_profile
|
||||
local ep
|
||||
ep="$(resolve_endpoint)"
|
||||
build_warp_conf "$ep"
|
||||
warp_up
|
||||
echo "Ключ WARP перевыпущен. Заново отметьте клиентов в веб-панели и примените маршрутизацию."
|
||||
}
|
||||
|
||||
[[ "${1:-}" ]] || usage
|
||||
need_root
|
||||
command -v docker >/dev/null || {
|
||||
echo "Нужен docker в PATH."
|
||||
exit 1
|
||||
}
|
||||
|
||||
CMD="$1"
|
||||
pick_container "$@"
|
||||
load_paths
|
||||
|
||||
case "$CMD" in
|
||||
install)
|
||||
if is_installed && is_running; then
|
||||
echo "Уже установлен и работает."
|
||||
exit 0
|
||||
fi
|
||||
if is_installed && ! is_running; then
|
||||
echo "Конфиг есть — поднимаю интерфейс…"
|
||||
warp_up
|
||||
exit 0
|
||||
fi
|
||||
cmd_install
|
||||
;;
|
||||
start)
|
||||
is_installed || {
|
||||
echo "Нет warp.conf — сначала install."
|
||||
exit 1
|
||||
}
|
||||
is_running && {
|
||||
echo "Уже работает."
|
||||
exit 0
|
||||
}
|
||||
warp_up
|
||||
echo "WARP поднят."
|
||||
;;
|
||||
stop)
|
||||
is_installed || exit 0
|
||||
warp_down
|
||||
echo "WARP остановлен."
|
||||
;;
|
||||
status) cmd_status ;;
|
||||
rekey) cmd_rekey ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user