Files
sdm-xray/install.sh
T

268 lines
9.5 KiB
Bash
Executable File
Raw 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.
#!/usr/bin/env bash
# sdm-xray — установка сервера stealth-туннеля на свежую Ubuntu VPS.
# Использование:
# bash <(curl -fsSL https://git.my-handbook.ru/ded_ikar/sdm-xray/raw/main/install.sh) <domain>
# — с доменом: Let's Encrypt-сертификат (A-запись домена должна указывать на IP VPS)
# bash <(curl -fsSL https://git.my-handbook.ru/ded_ikar/sdm-xray/raw/main/install.sh) --selfsigned
# — БЕЗ домена: self-signed сертификат, клиент доверяет по pinnedPeerCertSha256
# (pin печатается в клиентском конфиге; панель сама подставляет его в ссылки/конфиги)
set -euo pipefail
SELFSIGNED=0
if [ -z "${1:-}" ] || [ "$1" = "--selfsigned" ]; then
SELFSIGNED=1
DOMAIN=""
else
DOMAIN="$1"
fi
GITEA="https://git.my-handbook.ru/ded_ikar/sdm-xray"
VERSION="v0.2.2"
BIN="xray-stealth-server-linux-amd64"
PANEL_BIN="sdm-panel-linux-amd64"
INSTALL_DIR="/usr/local/xray"
DATA_DIR="/etc/xray"
WEBROOT="/var/www/html"
VPS_IP="$(curl -fsSL --max-time 10 https://api.ipify.org 2>/dev/null || echo UNKNOWN)"
if [ "$SELFSIGNED" -eq 1 ]; then
echo "=== sdm-xray installer ${VERSION} (SELF-SIGNED, без домена) ==="
echo "vps-ip: $VPS_IP (используй его как serverName/адрес в клиенте)"
else
echo "=== sdm-xray installer ${VERSION} ==="
echo "domain: $DOMAIN vps-ip: $VPS_IP"
fi
export DEBIAN_FRONTEND=noninteractive
echo "=== apt: deps ==="
apt-get update -qq
apt-get install -y -qq curl openssl jq nginx certbot >/dev/null 2>&1
echo "=== download server binary + geo files ==="
mkdir -p "$INSTALL_DIR" "$DATA_DIR" "$WEBROOT"
curl -fsSL -o "$INSTALL_DIR/xray" "$GITEA/releases/download/$VERSION/$BIN"
curl -fsSL -o "$INSTALL_DIR/geoip.dat" "$GITEA/releases/download/$VERSION/geoip.dat"
curl -fsSL -o "$INSTALL_DIR/geosite.dat" "$GITEA/releases/download/$VERSION/geosite.dat"
chmod 755 "$INSTALL_DIR/xray"
"$INSTALL_DIR/xray" version | sed -n '1p'
echo "=== generate secrets ==="
UUID="$(cat /proc/sys/kernel/random/uuid)"
KEY="$(openssl rand -hex 8)"
echo "$UUID" > "$DATA_DIR/uuid"
echo "$KEY" > "$DATA_DIR/key"
# --- TLS: либо LE-серт (домен), либо self-signed (без домена) ---
if [ "$SELFSIGNED" -eq 1 ]; then
echo "=== self-signed certificate (CN=$VPS_IP, 10 лет) ==="
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-subj "/CN=$VPS_IP" \
-keyout "$DATA_DIR/server.key" -out "$DATA_DIR/server.crt" >/dev/null 2>&1
CERT_FILE="$DATA_DIR/server.crt"
KEY_FILE="$DATA_DIR/server.key"
PIN="$(openssl x509 -in "$CERT_FILE" -outform der | openssl dgst -sha256 -hex | awk '{print $NF}')"
echo "pinnedPeerCertSha256: $PIN"
echo " (панель подставит его в клиентские конфиги/ссылки автоматически)"
else
echo "=== nginx on 80 (acme) ==="
mkdir -p "$WEBROOT/.well-known/acme-challenge"
cat > /etc/nginx/sites-available/sdm <<'NGX'
server {
listen 80;
listen [::]:80;
server_name DOMAIN;
root /var/www/html;
index index.html;
location /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
}
location / {
return 301 https://$host$request_uri;
}
}
NGX
sed -i "s/DOMAIN/$DOMAIN/" /etc/nginx/sites-available/sdm
ln -sf /etc/nginx/sites-available/sdm /etc/nginx/sites-enabled/sdm
rm -f /etc/nginx/sites-enabled/default
nginx -t >/dev/null 2>&1 && systemctl reload nginx
echo "=== Let's Encrypt cert ==="
certbot certonly --webroot -w "$WEBROOT" -d "$DOMAIN" \
--register-unsafely-without-email --agree-tos --no-eff-email -n \
--cert-name "$DOMAIN" >/dev/null 2>&1 || true
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
if [ ! -f "$CERT_DIR/fullchain.pem" ]; then
echo "ERROR: сертификат не получен. Проверьте, что $DOMAIN -> $VPS_IP и порт 80 открыт."
exit 1
fi
CERT_FILE="$CERT_DIR/fullchain.pem"
KEY_FILE="$CERT_DIR/privkey.pem"
fi
echo "=== xray config ==="
cat > "$DATA_DIR/config.json" <<EOF
{
"log": {"loglevel": "warning"},
"routing": {
"rules": [
{"port": "443", "network": "udp", "outboundTag": "block"},
{"ip": ["geoip:private"], "outboundTag": "block"}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {"clients": [{"id": "$UUID", "level": 0}], "decryption": "none"},
"streamSettings": {
"network": "stealth",
"stealthSettings": {
"key": "$KEY", "padMax": 2048, "padProb": 50, "paceMs": 0, "paceJitterMs": 0,
"paths": ["/api/t04d12b46/", "/api/v2/telemetry/", "/collect/", "/ingest/"],
"ports": [443], "bps": 0, "target": "https://www.iana.org",
"padProfile": "browser", "retries": 3
},
"security": "tls",
"tlsSettings": {
"certificates": [
{"certificateFile": "$CERT_FILE", "keyFile": "$KEY_FILE"}
]
}
},
"sniffing": {"enabled": true, "destOverride": ["http","tls","quic"]}
}
],
"outbounds": [
{"protocol": "freedom", "tag": "direct"},
{"protocol": "blackhole", "tag": "block"}
]
}
EOF
echo "=== systemd ==="
cat > /etc/systemd/system/xray.service <<'UNIT'
[Unit]
Description=sdm-xray stealth tunnel
After=network.target nss-lookup.target
[Service]
ExecStart=/usr/local/xray/xray run -c /etc/xray/config.json
Restart=on-failure
RestartPreventExitStatus=23
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable xray >/dev/null 2>&1 || true
systemctl restart xray
sleep 1
if ! systemctl is-active xray >/dev/null 2>&1; then
echo "ERROR: xray не запустился:"; journalctl -u xray -n 20 --no-pager || true; exit 1
fi
echo
echo "=== INSTALLED OK ==="
echo "uuid: $UUID"
echo "key: $KEY"
# --- panel ---
echo
echo "=== control panel (sdm-panel) ==="
curl -fsSL -o "$INSTALL_DIR/sdm-panel" "$GITEA/releases/download/$VERSION/$PANEL_BIN"
chmod 755 "$INSTALL_DIR/sdm-panel"
PANEL_PASS="$(openssl rand -hex 8)"
PANEL_LOGIN="admin"
if [ "$SELFSIGNED" -eq 1 ]; then
PANEL_SERVER="$VPS_IP"
else
PANEL_SERVER="$DOMAIN"
fi
cat > "$DATA_DIR/panel.json" <<EOF
{
"bind": "127.0.0.1:8080",
"login": "$PANEL_LOGIN",
"password": "$PANEL_PASS",
"serverName": "$PANEL_SERVER"
}
EOF
chmod 600 "$DATA_DIR/panel.json"
cat > /etc/systemd/system/sdm-panel.service <<'PANEL'
[Unit]
Description=sdm-xray control panel
After=network.target xray.service
[Service]
ExecStart=/usr/local/xray/sdm-panel
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
PANEL
systemctl daemon-reload
systemctl enable sdm-panel >/dev/null 2>&1 || true
systemctl restart sdm-panel
sleep 1
echo "panel login: $PANEL_LOGIN panel password: $PANEL_PASS (запомни — больше не покажем)"
echo "Доступ к панели (SSH-туннель, шифрованный):"
echo " ssh -L 8080:127.0.0.1:8080 root@<vps-ip>"
echo " затем открой в браузере http://localhost:8080 (login: $PANEL_LOGIN / пароль выше)"
echo
echo "=== client config (client-stealth.json) ==="
if [ "$SELFSIGNED" -eq 1 ]; then
cat <<CFG
{
"log": {"loglevel": "warning"},
"inbounds": [
{"listen": "127.0.0.1", "port": 10808, "protocol": "socks"},
{"listen": "127.0.0.1", "port": 10809, "protocol": "http"}
],
"outbounds": [
{
"protocol": "vless",
"settings": {"vnext": [{"address": "$VPS_IP", "port": 443, "users": [{"id": "$UUID", "encryption": "none"}]}]},
"streamSettings": {
"network": "stealth",
"stealthSettings": {"key": "$KEY", "padMax": 2048, "padProb": 50, "paceMs": 0, "paceJitterMs": 0, "paths": ["/api/t04d12b46/", "/api/v2/telemetry/", "/collect/", "/ingest/"], "ports": [443], "bps": 0},
"security": "tls",
"tlsSettings": {"serverName": "$VPS_IP", "fingerprint": "chrome", "pinnedPeerCertSha256": "$PIN"}
}
},
{"protocol": "freedom", "tag": "direct"}
]
}
CFG
else
cat <<CFG
{
"log": {"loglevel": "warning"},
"inbounds": [
{"listen": "127.0.0.1", "port": 10808, "protocol": "socks"},
{"listen": "127.0.0.1", "port": 10809, "protocol": "http"}
],
"outbounds": [
{
"protocol": "vless",
"settings": {"vnext": [{"address": "$DOMAIN", "port": 443, "users": [{"id": "$UUID", "encryption": "none"}]}]},
"streamSettings": {
"network": "stealth",
"stealthSettings": {"key": "$KEY", "padMax": 2048, "padProb": 50, "paceMs": 0, "paceJitterMs": 0, "paths": ["/api/t04d12b46/", "/api/v2/telemetry/", "/collect/", "/ingest/"], "ports": [443], "bps": 0},
"security": "tls",
"tlsSettings": {"serverName": "$DOMAIN", "fingerprint": "chrome"}
}
},
{"protocol": "freedom", "tag": "direct"}
]
}
CFG
fi
echo
echo "=== client binaries ==="
echo " Windows: $GITEA/releases/download/$VERSION/xray-stealth-client-windows-amd64.exe"
echo " Router: $GITEA/releases/download/$VERSION/xray-stealth-client-linux-arm64"
echo " Panel: $GITEA/releases/download/$VERSION/sdm-panel-linux-amd64"