montana/Монтана-Протокол/Код/montana-vpn/install.sh

170 lines
7.0 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Montana VPN — установщик xray Reality endpoint на Linux VPS.
#
# Что делает:
# 1. Ставит system deps (xray, nginx, ufw, curl, jq)
# 2. Генерирует свежие Reality keys + UUID + shortId на самом хосте
# 3. Подставляет их в xray-config.json.template → /usr/local/etc/xray/config.json
# 4. Поднимает nginx :80 с decoy-страницей (камуфляж от пассивных проверяющих)
# 5. Прописывает systemd unit + drop-in для xray
# 6. Открывает 22/80/443 в ufw, остальное закрывает
# 7. Включает BBR + fq_codel через sysctl
# 8. Запускает xray, печатает VLESS URL клиенту
#
# Использование:
# sudo bash install.sh # с настройками по умолчанию
# sudo DECOY_HOST=www.googletagmanager.com bash install.sh
# sudo CLIENT_EMAIL=alice@montana bash install.sh
#
# Идемпотентен: повторный запуск не ломает настройки и не пересоздаёт ключи
# (они в /etc/montana-vpn/state.env, удалить файл = пересоздать).
set -euo pipefail
DECOY_HOST="${DECOY_HOST:-www.googletagmanager.com}"
CLIENT_EMAIL="${CLIENT_EMAIL:-montana-client}"
STATE_DIR="/etc/montana-vpn"
STATE_FILE="$STATE_DIR/state.env"
XRAY_CONF_DIR="/usr/local/etc/xray"
XRAY_CONF="$XRAY_CONF_DIR/config.json"
XRAY_LOG_DIR="/var/log/xray"
DECOY_ROOT="/var/www/decoy"
NGINX_SITE="/etc/nginx/sites-available/decoy"
SYSCTL_FILE="/etc/sysctl.d/99-montana-vpn.conf"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
TEMPLATE_DIR="$SCRIPT_DIR/config-template"
log() { printf '\033[1;32m[montana-vpn]\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[montana-vpn]\033[0m %s\n' "$*" >&2; }
die() { printf '\033[1;31m[montana-vpn] ОШИБКА:\033[0m %s\n' "$*" >&2; exit 1; }
[ "$(id -u)" = "0" ] || die "требуется sudo/root"
[ -f /etc/os-release ] || die "/etc/os-release отсутствует"
. /etc/os-release
OS_ID="${ID:-unknown}"
log "OS: ${PRETTY_NAME:-$OS_ID}"
[ -d "$TEMPLATE_DIR" ] || die "config-template/ не найден рядом со скриптом ($TEMPLATE_DIR)"
log "ставлю system deps..."
case "$OS_ID" in
ubuntu|debian)
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq nginx ufw curl jq ca-certificates >/dev/null
;;
fedora|rhel|centos|rocky|almalinux)
dnf install -y -q nginx firewalld curl jq ca-certificates >/dev/null
;;
alpine)
apk add --no-cache nginx curl jq ca-certificates >/dev/null
;;
*)
die "неподдерживаемый OS: $OS_ID"
;;
esac
if ! command -v xray >/dev/null 2>&1; then
log "ставлю xray (официальный installer)..."
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install >/dev/null
else
log "xray уже установлен: $(xray version 2>&1 | head -1)"
fi
mkdir -p "$STATE_DIR" "$XRAY_CONF_DIR" "$XRAY_LOG_DIR" "$DECOY_ROOT"
chmod 0700 "$STATE_DIR"
if [ -f "$STATE_FILE" ]; then
log "переиспользую ключи из $STATE_FILE (удалите файл чтобы перегенерить)"
# shellcheck disable=SC1090
. "$STATE_FILE"
else
log "генерирую свежие Reality keys + UUID + shortId..."
KEYS=$(xray x25519)
REALITY_PRIVATE_KEY=$(echo "$KEYS" | awk '/Private key:|PrivateKey:/ {print $NF}')
REALITY_PUBLIC_KEY=$(echo "$KEYS" | awk '/Public key:|Password:/ {print $NF}')
CLIENT_UUID=$(xray uuid)
REALITY_SHORT_ID=$(openssl rand -hex 8)
cat > "$STATE_FILE" <<STATE
DECOY_HOST="$DECOY_HOST"
CLIENT_EMAIL="$CLIENT_EMAIL"
CLIENT_UUID="$CLIENT_UUID"
REALITY_PRIVATE_KEY="$REALITY_PRIVATE_KEY"
REALITY_PUBLIC_KEY="$REALITY_PUBLIC_KEY"
REALITY_SHORT_ID="$REALITY_SHORT_ID"
STATE
chmod 0600 "$STATE_FILE"
fi
log "генерирую xray config.json из шаблона..."
sed \
-e "s|{{CLIENT_UUID}}|$CLIENT_UUID|g" \
-e "s|{{CLIENT_EMAIL}}|$CLIENT_EMAIL|g" \
-e "s|{{DECOY_HOST}}|$DECOY_HOST|g" \
-e "s|{{REALITY_PRIVATE_KEY}}|$REALITY_PRIVATE_KEY|g" \
-e "s|{{REALITY_SHORT_ID}}|$REALITY_SHORT_ID|g" \
"$TEMPLATE_DIR/xray-config.json.template" > "$XRAY_CONF"
chmod 0644 "$XRAY_CONF"
chown -R nobody:nogroup "$XRAY_LOG_DIR" 2>/dev/null || chown -R nobody:nobody "$XRAY_LOG_DIR" 2>/dev/null || true
log "ставлю xray.service + drop-in..."
install -m 0644 "$TEMPLATE_DIR/xray.service" /etc/systemd/system/xray.service
install -d -m 0755 /etc/systemd/system/xray.service.d
install -m 0644 "$TEMPLATE_DIR/xray.service.d/10-donot_touch_single_conf.conf" /etc/systemd/system/xray.service.d/10-donot_touch_single_conf.conf
log "поднимаю nginx :80 decoy..."
install -m 0644 "$TEMPLATE_DIR/decoy-index.html" "$DECOY_ROOT/index.html"
install -m 0644 "$TEMPLATE_DIR/nginx-decoy.conf" "$NGINX_SITE"
ln -sf "$NGINX_SITE" /etc/nginx/sites-enabled/decoy
rm -f /etc/nginx/sites-enabled/default
nginx -t >/dev/null 2>&1 || die "nginx config невалиден"
systemctl enable nginx >/dev/null 2>&1 || true
systemctl restart nginx
log "включаю BBR + fq_codel через sysctl..."
install -m 0644 "$TEMPLATE_DIR/sysctl-bbr.conf" "$SYSCTL_FILE"
sysctl -p "$SYSCTL_FILE" >/dev/null 2>&1 || true
if command -v ufw >/dev/null 2>&1; then
log "настраиваю ufw (22, 80, 443)..."
ufw allow 22/tcp comment 'SSH' >/dev/null 2>&1 || true
ufw allow 80/tcp comment 'decoy nginx' >/dev/null 2>&1 || true
ufw allow 443/tcp comment 'VLESS+TCP+Reality' >/dev/null 2>&1 || true
ufw --force enable >/dev/null 2>&1 || true
fi
log "запускаю xray..."
systemctl daemon-reload
systemctl enable xray.service >/dev/null 2>&1
systemctl restart xray.service
sleep 2
PUBLIC_IP=$(curl -s4 https://api.ipify.org 2>/dev/null || hostname -I | awk '{print $1}')
log ""
log "================================================================"
log " УСТАНОВКА VPN ЗАВЕРШЕНА"
log "================================================================"
log ""
log "Server: $PUBLIC_IP:443"
log "Decoy SNI: $DECOY_HOST"
log "Client UUID: $CLIENT_UUID"
log "Reality PK: $REALITY_PUBLIC_KEY"
log "Reality SID: $REALITY_SHORT_ID"
log "Flow: xtls-rprx-vision"
log ""
log "VLESS URL для клиента (импортировать в v2rayN/Hiddify/Streisand):"
log ""
echo "vless://${CLIENT_UUID}@${PUBLIC_IP}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${DECOY_HOST}&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#montana-vpn"
log ""
log "Полные ключи и состояние: $STATE_FILE (mode 0600)"
log ""
log "Управление:"
log " systemctl status xray # статус VPN"
log " systemctl restart xray # перезапуск"
log " journalctl -u xray -f # логи"
log ""
log "Узел Montana — отдельный слой; устанавливается scripts/install-vps.sh"
log "(или scripts/install-vps-full.sh — узел + VPN одной командой)."