Files
autoXRAY/autoXRAY1.sh
2026-02-03 23:18:38 +03:00

996 lines
31 KiB
Bash
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.
#!/bin/bash
DOMAIN=$1
if [ -z "$DOMAIN" ]; then
echo "❌ Ошибка: домен не задан."
exit 1
fi
echo "Обновление и установка необходимых пакетов..."
apt update && apt install curl jq dnsutils -y
LOCAL_IP=$(hostname -I | awk '{print $1}')
DNS_IP=$(dig +short "$DOMAIN" | grep '^[0-9]')
if [ "$LOCAL_IP" != "$DNS_IP" ]; then
echo "❌ Внимание: IP-адрес ($LOCAL_IP) не совпадает с A-записью $DOMAIN ($DNS_IP)."
echo "Правильно укажите одну A-запись для вашего домена в ДНС - $LOCAL_IP"
read -p $'\033[1;31mПродолжить на ваш страх и риск? (y/N): \033[0m' choice
if [[ ! "$choice" =~ ^[Yy]$ ]]; then
echo -e "\033[31mВыполнение скрипта прервано.\033[0m"
exit 1
fi
echo "Продолжение выполнения скрипта..."
fi
# Включаем BBR
bbr=$(sysctl -a | grep net.ipv4.tcp_congestion_control)
if [ "$bbr" = "net.ipv4.tcp_congestion_control = bbr" ]; then
echo "BBR уже запущен"
else
echo "net.core.default_qdisc=fq" >> /etc/sysctl.d/99-Xauto.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.d/99-Xauto.conf
sysctl --system
echo "BBR активирован"
fi
apt install nginx -y
systemctl enable --now nginx
# Создание директории сайта
WEB_PATH="/var/www/$DOMAIN"
mkdir -p "$WEB_PATH"
# Генерируем сайт маскировку
bash -c "$(curl -L https://github.com/xVRVx/autoXRAY/raw/refs/heads/main/test/gen_page2.sh)" -- $WEB_PATH
# Установка Xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
# Блок CERTBOT - START
apt install certbot -y
mkdir -p /var/lib/xray/cert/
### Проверить
cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem /var/lib/xray/cert/fullchain.pem
cp /etc/letsencrypt/live/$DOMAIN/privkey.pem /var/lib/xray/cert/privkey.pem
chmod 744 /var/lib/xray/cert/privkey.pem
chmod 744 /var/lib/xray/cert/fullchain.pem
certbot certonly --webroot -w /var/www/html \
-d $DOMAIN \
-m mail@$DOMAIN \
--agree-tos --non-interactive \
--deploy-hook "systemctl reload nginx; cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem /var/lib/xray/cert/fullchain.pem; cp /etc/letsencrypt/live/$DOMAIN/privkey.pem /var/lib/xray/cert/privkey.pem; chmod 744 /var/lib/xray/cert/privkey.pem; chmod 744 /var/lib/xray/cert/fullchain.pem; systemctl restart xray"
RET=$?
if [ $RET -eq 0 ]; then
echo -e "\n\033[1;32m========================================"
echo "✅ Команда certbot успешно выполнена"
echo "✅ Сертификат https от letsencrypt ПОЛУЧЕН"
echo "========================================"
echo -e "\033[0m"
else
echo -e "\n\033[1;31m========================================"
echo "❌ CERTBOT ЗАВЕРШИЛСЯ С ОШИБКОЙ"
echo "❌ Сертификат https от letsencrypt НЕ ПОЛУЧЕН!"
echo "❌ Смотрите выше логи процесса получения сертификата"
echo "❌ Код возврата: $RET"
echo "========================================"
echo -e "\033[0m"
exit 1
fi
# Блок CERTBOT - END
CONFIG_PATH="/etc/nginx/sites-available/default"
path_xhttp=$(openssl rand -base64 15 | tr -dc 'a-z0-9' | head -c 6)
echo "✅ Записываем конфигурацию в $CONFIG_PATH для домена $DOMAIN"
bash -c "cat > $CONFIG_PATH" <<EOF
server {
server_name $DOMAIN;
listen unix:/dev/shm/nginx.sock ssl http2 proxy_protocol;
listen unix:/dev/shm/nginxTLS.sock proxy_protocol;
listen unix:/dev/shm/nginx_h2.sock http2 proxy_protocol;
set_real_ip_from unix:;
real_ip_header proxy_protocol;
root /var/www/$DOMAIN;
index index.php index.html;
# grpc settings
grpc_read_timeout 1h;
grpc_send_timeout 1h;
grpc_set_header X-Real-IP \$remote_addr;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_certificate "/etc/letsencrypt/live/$DOMAIN/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/$DOMAIN/privkey.pem";
add_header profile-title "base64:YXV0b1hSQVk=";
add_header routing "happ://routing/onadd/ewogICAgIk5hbWUiOiAiYXV0b1hSQVkiLAogICAgIkdsb2JhbFByb3h5IjogInRydWUiLAogICAgIlVzZUNodW5rRmlsZXMiOiAidHJ1ZSIsCiAgICAiUmVtb3RlRE5TVHlwZSI6ICJEb0giLAogICAgIlJlbW90ZUROU0RvbWFpbiI6ICIiLAogICAgIlJlbW90ZUROU0lQIjogIiIsCiAgICAiRG9tZXN0aWNETlNUeXBlIjogIkRvSCIsCiAgICAiRG9tZXN0aWNETlNEb21haW4iOiAiIiwKICAgICJEb21lc3RpY0ROU0lQIjogIiIsCiAgICAiR2VvaXB1cmwiOiAiIiwKICAgICJHZW9zaXRldXJsIjogIiIsCiAgICAiTGFzdFVwZGF0ZWQiOiAiIiwKICAgICJEbnNIb3N0cyI6IHt9LAogICAgIk9yZGVyUm91dGluZyI6ICJibG9jay1kaXJlY3QtcHJveHkiLAogICAgIkRpcmVjdFNpdGVzIjogWwogICAgICAgICJjYXRlZ29yeS1ydSIsCiAgICAgICAgImdlb3NpdGU6cHJpdmF0ZSIKICAgIF0sCiAgICAiRGlyZWN0SXAiOiBbCiAgICAgICAgImdlb2lwOnByaXZhdGUiCiAgICBdLAogICAgIlByb3h5U2l0ZXMiOiBbXSwKICAgICJQcm94eUlwIjogW10sCiAgICAiQmxvY2tTaXRlcyI6IFsKICAgICAgICAiZ2Vvc2l0ZTpjYXRlZ29yeS1hZHMiLAogICAgICAgICJnZW9zaXRlOndpbi1zcHkiCiAgICBdLAogICAgIkJsb2NrSXAiOiBbXSwKICAgICJEb21haW5TdHJhdGVneSI6ICJJUElmTm9uTWF0Y2giLAogICAgIkZha2VETlMiOiAiZmFsc2UiCn0=";
add_header routing-enable 0;
location /${path_xhttp} {
proxy_pass http://127.0.0.1:8400;
proxy_http_version 1.1;
proxy_set_header Host \$host;
}
location /${path_xhttp}11 {
if (\$request_method != "POST") {
return 404;
}
client_body_buffer_size 1m;
client_body_timeout 1h;
client_max_body_size 0;
grpc_pass grpc://127.0.0.1:8411;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 80;
server_name $DOMAIN;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://\$host\$request_uri;
}
}
EOF
echo "✅ Конфигурация nginx обновлена."
systemctl restart nginx
SCRIPT_DIR=/usr/local/etc/xray
# Генерируем переменные
xray_uuid_vrv=$(xray uuid)
key_output=$(xray x25519)
xray_privateKey_vrv=$(echo "$key_output" | awk -F': ' '/PrivateKey/ {print $2}')
xray_publicKey_vrv=$(echo "$key_output" | awk -F': ' '/Password/ {print $2}')
key_mldsa65=$(xray mldsa65)
seed_mldsa65=$(echo "$key_mldsa65" | awk -F': ' '/Seed/ {print $2}')
verify_mldsa65=$(echo "$key_mldsa65" | awk -F': ' '/Verify/ {print $2}')
xray_shortIds_vrv=$(openssl rand -hex 8)
# xray_sspasw_vrv=$(openssl rand -base64 15 | tr -dc 'A-Za-z0-9' | head -c 20)
xray_sspasw_vrv=$(openssl rand -base64 32)
path_subpage=$(openssl rand -base64 15 | tr -dc 'A-Za-z0-9' | head -c 20)
# ipserv=$(hostname -I | awk '{print $1}')
socksUser=$(openssl rand -base64 16 | tr -dc 'A-Za-z0-9' | head -c 6)
socksPasw=$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 16)
# Экспортируем переменные для envsubst
export xray_uuid_vrv xray_privateKey_vrv xray_publicKey_vrv xray_shortIds_vrv xray_sspasw_vrv DOMAIN path_subpage path_xhttp WEB_PATH socksUser socksPasw
# Создаем JSON конфигурацию сервера
cat << 'EOF' | envsubst > "$SCRIPT_DIR/config.json"
{
"log": {
"dnsLog": false,
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log",
"loglevel": "none"
},
"dns": {
"servers": [
"https+local://8.8.4.4/dns-query",
"https+local://8.8.8.8/dns-query",
"https+local://1.1.1.1/dns-query",
"localhost"
],
"queryStrategy": "UseIPv4"
},
"inbounds": [
{
"tag": "vsRAWrtyVISION",
"port": 443,
"listen": "0.0.0.0",
"protocol": "vless",
"settings": {
"clients": [
{
"flow": "xtls-rprx-vision",
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none",
"fallbacks": [
{
"dest": "3333",
"xver": 2
}
]
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"show": false,
"xver": 2,
"target": "/dev/shm/nginx.sock",
"spiderX": "/",
"shortIds": [
"${xray_shortIds_vrv}"
],
"privateKey": "${xray_privateKey_vrv}",
"serverNames": [
"$DOMAIN"
],
"limitFallbackUpload": {
"afterBytes": 0,
"bytesPerSec": 65536,
"burstBytesPerSec": 0
},
"limitFallbackDownload": {
"afterBytes": 5242880,
"bytesPerSec": 262144,
"burstBytesPerSec": 2097152
}
}
}
},
{
"tag": "vsXHTTPrty",
"port": 3333,
"listen": "127.0.0.1",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"mode": "stream-one",
"path": "/${path_xhttp}"
},
"security": "none",
"sockopt": {
"acceptProxyProtocol": true
}
}
},
{
"tag": "vsRAWtlsVISION",
"port": 8443,
"listen": "0.0.0.0",
"protocol": "vless",
"settings": {
"clients": [
{
"flow": "xtls-rprx-vision",
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none",
"fallbacks": [
{
"path": "/${path_xhttp}22",
"dest": "@vless-ws",
"xver": 2
},
{
"path": "/ssws",
"dest": "4001"
},
{
"alpn": "h2",
"dest": "/dev/shm/nginx_h2.sock",
"xver": 2
},
{
"dest": "/dev/shm/nginxTLS.sock",
"xver": 2
}
]
},
"streamSettings": {
"network": "raw",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "/var/lib/xray/cert/fullchain.pem",
"keyFile": "/var/lib/xray/cert/privkey.pem"
}
],
"minVersion": "1.2",
"cipherSuites": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"alpn": [
"h2", "http/1.1"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "vsXHTTPtls",
"port": 8400,
"listen": "127.0.0.1",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"mode": "auto",
"path": "/${path_xhttp}"
},
"security": "none",
"sockopt": {
"acceptProxyProtocol": false
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "vsGRPCtls",
"port": 8411,
"listen": "127.0.0.1",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "grpc",
"grpcSettings": {
"serviceName": "${path_xhttp}11"
},
"security": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"listen": "@vless-ws",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"acceptProxyProtocol": true,
"path": "/${path_xhttp}22"
},
"security": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "socks5",
"port": 10443,
"listen": "0.0.0.0",
"protocol": "mixed",
"settings": {
"ip": "0.0.0.0",
"udp": true,
"auth": "password",
"accounts": [
{
"user": "${socksUser}",
"pass": "${socksPasw}"
}
]
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "ForceIPv4"
}
},
{
"tag": "block",
"protocol": "blackhole"
},
{
"tag": "warp",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 40000
}
]
}
}
],
"routing": {
"rules": [
{
"ip": [
"geoip:private"
],
"outboundTag": "block"
},
{
"protocol": [
"bittorrent"
],
"outboundTag": "block"
},
{
"domain": [
"geosite:category-ads",
"geosite:win-spy",
"geosite:private"
],
"outboundTag": "block"
},
{
"outboundTag": "direct",
"domain": ["geosite:google-gemini","geosite:category-ru","habr.com"]
}
],
"domainStrategy": "IPIfNonMatch"
}
}
EOF
# Создаем JSON конфигурацию клиента
print_config() {
local PROXY_OUTBOUND="$1"
local REMARK="$2"
cat << TPL
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"https://8.8.4.4/dns-query",
"https://8.8.8.8/dns-query",
"https://1.1.1.1/dns-query"
],
"queryStrategy": "UseIPv4"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"domain": [
"geosite:category-ads",
"geosite:win-spy"
],
"outboundTag": "block"
},
{
"protocol": [
"bittorrent"
],
"outboundTag": "direct"
},
{
"domain": [
"habr.com"
],
"outboundTag": "proxy"
},
{
"domain": [
"geosite:private",
"geosite:apple",
"geosite:apple-pki",
"geosite:huawei",
"geosite:xiaomi",
"geosite:category-android-app-download",
"geosite:f-droid",
"geosite:yandex",
"geosite:vk",
"geosite:microsoft",
"geosite:win-update",
"geosite:win-extra",
"geosite:google-play",
"geosite:steam",
"geosite:category-ru"
],
"outboundTag": "direct"
},
{
"ip": [
"geoip:private"
],
"outboundTag": "direct"
}
]
},
"inbounds": [
{
"tag": "socks-in",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 10808,
"settings": {
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "socks-sb",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 2080,
"settings": {
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "http-in",
"protocol": "http",
"listen": "127.0.0.1",
"port": 10809,
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
}
],
"outbounds": [
$PROXY_OUTBOUND,
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"remarks": "$REMARK"
}
TPL
}
# --- Config 1
OUT_REALITY_VISION='{
"mux": { "concurrency": -1, "enabled": false },
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 443,
"users": [{ "id": "${xray_uuid_vrv}", "flow": "xtls-rprx-vision", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"show": false, "fingerprint": "chrome", "serverName": "$DOMAIN",
"password": "${xray_publicKey_vrv}", "shortId": "${xray_shortIds_vrv}", "spiderX": "/"
}
}
}'
# --- Config 2
OUT_REALITY_XHTTP='{
"mux": { "concurrency": -1, "enabled": false },
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 443,
"users": [{ "id": "${xray_uuid_vrv}", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "xhttp",
"security": "reality",
"xhttpSettings": {
"mode": "auto",
"path": "/${path_xhttp}",
"extra": {
"noGRPCHeader": false,
"scMaxEachPostBytes": 1500000,
"scMinPostsIntervalMs": 20,
"scStreamUpServerSecs": "60-240",
"xPaddingBytes": "400-800",
"xmux": {
"cMaxReuseTimes": "1000-3000",
"hKeepAlivePeriod": 0,
"hMaxRequestTimes": "400-700",
"hMaxReusableSecs": "1200-1800",
"maxConcurrency": "3-5",
"maxConnections": 0
}
}
},
"realitySettings": {
"show": false, "fingerprint": "chrome", "serverName": "$DOMAIN",
"password": "${xray_publicKey_vrv}", "shortId": "${xray_shortIds_vrv}", "spiderX": "/"
}
}
}'
# --- Config 3
OUT_VISION='{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 8443,
"users": [{ "id": "${xray_uuid_vrv}", "flow": "xtls-rprx-vision", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "raw",
"security": "tls",
"tlsSettings": {
"serverName": "$DOMAIN",
"fingerprint": "chrome"
}
}
}'
# --- Config 4
OUT_XHTTP='{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 8443,
"users": [{ "id": "${xray_uuid_vrv}", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"extra": {
"headers": {
},
"noGRPCHeader": false,
"scMaxEachPostBytes": 1500000,
"scMinPostsIntervalMs": 20,
"scStreamUpServerSecs": "60-240",
"xPaddingBytes": "400-800",
"xmux": {
"cMaxReuseTimes": "1000-3000",
"hKeepAlivePeriod": 0,
"hMaxRequestTimes": "400-700",
"hMaxReusableSecs": "1200-1800",
"maxConcurrency": "3-5",
"maxConnections": 0
}
},
"mode": "auto", "path": "/${path_xhttp}" },
"security": "tls",
"tlsSettings": { "serverName": "$DOMAIN", "fingerprint": "chrome" }
}
}'
# --- Config 5
# Важно: alpn h2 обязателен для корректной работы через Nginx
OUT_GRPC='{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 8443,
"users": [{ "id": "${xray_uuid_vrv}", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "grpc",
"grpcSettings": { "serviceName": "${path_xhttp}11", "multiMode": false },
"security": "tls",
"tlsSettings": { "serverName": "$DOMAIN", "alpn": ["h2"], "fingerprint": "chrome" }
}
}'
# --- Config 6
OUT_WS='{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "$DOMAIN",
"port": 8443,
"users": [{ "id": "${xray_uuid_vrv}", "encryption": "none" }]
}]
},
"streamSettings": {
"network": "ws",
"wsSettings": { "path": "/${path_xhttp}22" },
"security": "tls",
"tlsSettings": { "serverName": "$DOMAIN", "fingerprint": "chrome" }
}
}'
(
echo "["
print_config "$OUT_REALITY_XHTTP" "🇪🇺 VLESS XHTTP REALITY EXTRA"
echo ","
print_config "$OUT_REALITY_VISION" "🇪🇺 VLESS RAW REALITY VISION"
echo ","
print_config "$OUT_VISION" "🇪🇺 VLESS RAW TLS VISION"
echo ","
print_config "$OUT_XHTTP" "🇪🇺 VLESS XHTTP TLS EXTRA"
echo ","
print_config "$OUT_GRPC" "🇪🇺 VLESS gRPC TLS"
echo ","
print_config "$OUT_WS" "🇪🇺 VLESS WS TLS"
echo "]"
) | envsubst > "$WEB_PATH/$path_subpage.json"
# Перезапуск Xray
echo "Перезапуск Xray..."
systemctl restart xray
echo -e "Готово!\n"
# Формирование ссылок
subPageLink="https://$DOMAIN/$path_subpage.json"
# Формирование ссылок
linkRTY1="vless://${xray_uuid_vrv}@$DOMAIN:443?security=reality&type=tcp&headerType=&path=&host=&flow=xtls-rprx-vision&sni=$DOMAIN&fp=chrome&pbk=${xray_publicKey_vrv}&sid=${xray_shortIds_vrv}&spx=%2F#vlessRAWrealityVISION-autoXRAY"
linkRTY2="vless://${xray_uuid_vrv}@$DOMAIN:443?security=reality&type=xhttp&headerType=&path=%2F$path_xhttp&host=&mode=stream-one&extra=%7B%22xmux%22%3A%7B%22cMaxReuseTimes%22%3A%221000-3000%22%2C%22maxConcurrency%22%3A%223-5%22%2C%22maxConnections%22%3A0%2C%22hKeepAlivePeriod%22%3A0%2C%22hMaxRequestTimes%22%3A%22400-700%22%2C%22hMaxReusableSecs%22%3A%221200-1800%22%7D%2C%22headers%22%3A%7B%7D%2C%22noGRPCHeader%22%3Afalse%2C%22xPaddingBytes%22%3A%22400-800%22%2C%22scMaxEachPostBytes%22%3A1500000%2C%22scMinPostsIntervalMs%22%3A20%2C%22scStreamUpServerSecs%22%3A%2260-240%22%7D&sni=$DOMAIN&fp=chrome&pbk=${xray_publicKey_vrv}&sid=${xray_shortIds_vrv}&spx=%2F#vlessXHTTPrealityEXTRA-autoXRAY"
linkTLS1="vless://${xray_uuid_vrv}@$DOMAIN:8443?security=tls&type=tcp&headerType=&path=&host=&flow=xtls-rprx-vision&sni=$DOMAIN&fp=chrome&spx=%2F#vlessRAWtlsVision-autoXRAY"
linkTLS2="vless://${xray_uuid_vrv}@$DOMAIN:8443?security=tls&type=xhttp&headerType=&path=%2F${path_xhttp}&host=&mode=auto&extra=%7B%22xmux%22%3A%7B%22cMaxReuseTimes%22%3A%221000-3000%22%2C%22maxConcurrency%22%3A%223-5%22%2C%22maxConnections%22%3A0%2C%22hKeepAlivePeriod%22%3A0%2C%22hMaxRequestTimes%22%3A%22400-700%22%2C%22hMaxReusableSecs%22%3A%221200-1800%22%7D%2C%22headers%22%3A%7B%7D%2C%22noGRPCHeader%22%3Afalse%2C%22xPaddingBytes%22%3A%22400-800%22%2C%22scMaxEachPostBytes%22%3A1500000%2C%22scMinPostsIntervalMs%22%3A20%2C%22scStreamUpServerSecs%22%3A%2260-240%22%7D&sni=$DOMAIN&fp=chrome&spx=%2F#vlessXHTTPtls-autoXRAY"
linkTLS3="vless://${xray_uuid_vrv}@$DOMAIN:8443?security=tls&type=ws&headerType=&path=%2F${path_xhttp}22&host=&sni=$DOMAIN&fp=chrome&spx=%2F#vlessWStls-autoXRAY"
linkTLS4="vless://${xray_uuid_vrv}@$DOMAIN:8443?security=tls&type=grpc&headerType=&serviceName=${path_xhttp}11&host=&sni=$DOMAIN&fp=chrome&spx=%2F#vlessGRPCtls-autoXRAY"
configListLink="https://$DOMAIN/$path_subpage.html"
CONFIGS_ARRAY=(
"VLESS XHTTP REALITY EXTRA (для моста)|$linkRTY2"
"VLESS RAW REALITY VISION|$linkRTY1"
"VLESS RAW TLS VISION|$linkTLS1"
"VLESS XHTTP TLS EXTRA|$linkTLS2"
"VLESS WS TLS|$linkTLS3"
"VLESS GRPC TLS|$linkTLS4"
)
ALL_LINKS_TEXT=""
# --- ЗАПИСЬ HEAD (СТАТИКА, МИНИФИЦИРОВАННЫЕ СТИЛИ И JS) ---
cat > "$WEB_PATH/$path_subpage.html" <<'EOF'
<!DOCTYPE html><html lang="ru"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="robots" content="noindex,nofollow">
<title>autoXRAY configs</title>
<link rel="icon" type="image/svg+xml" href='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDBCRkZGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTIxIDJsLTIgMm0tNy42MSA3LjYxYTUuNSA1LjUgMCAxIDEtNy43NzggNy43NzggNS41IDUuNSAwIDAgMSA3Ljc3Ny03Ljc3N3ptMCAwTDE1LjUgNy41bTAgMGwzIDNMMjIgN2wtMy0zbS0zLjUgMy41TDE5IDQiLz48L3N2Zz4='>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<style>
body{font-family:monospace;background:#121212;color:#e0e0e0;padding:10px;max-width:900px;margin:0 auto}h2{color:#c3e88d;border-top:2px solid #333;padding-top:20px;margin:15px 0 10px;font-size:18px}.config-row{background:#1e1e1e;border:1px solid #333;border-radius:6px;padding:5px;display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px}.config-label{background:#2c2c2c;color:#82aaff;padding:6px 10px;border-radius:4px;font-weight:700;font-size:13px;white-space:nowrap;min-width:140px;text-align:center}.config-code{flex:1;white-space:nowrap;overflow-x:auto;padding:8px;background:#121212;border-radius:4px;color:#c3e88d;font-size:12px;scrollbar-width:none}.config-code::-webkit-scrollbar{display:none}.btn-action{border:1px solid #555;padding:6px 12px;border-radius:4px;cursor:pointer;font-weight:700;font-size:12px;transition:all .2s;height:32px;display:flex;align-items:center;justify-content:center}.copy-btn{background:#333;color:#e0e0e0;min-width:60px}.copy-btn:hover{background:#c3e88d;color:#121212;border-color:#c3e88d}.qr-btn{background:#333;color:#82aaff;border-color:#82aaff;min-width:40px}.qr-btn:hover{background:#82aaff;color:#121212}.btn-group{display:flex;gap:10px;margin:10px 0 20px}.btn{flex:1;background:#2c2c2c;color:#c3e88d;border:1px solid #c3e88d;padding:10px;text-align:center;border-radius:6px;text-decoration:none;font-weight:700;font-size:14px}.btn:hover{background:#c3e88d;color:#121212}.btn.download{border-color:#82aaff;color:#82aaff}.btn.download:hover{background:#82aaff;color:#121212}.btn.tg{border-color:#2AABEE;color:#2AABEE}.btn.tg:hover{background:#2AABEE;color:#fff}.modal-overlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.85);z-index:999;justify-content:center;align-items:center;backdrop-filter:blur(3px)}.modal-content{background:#1e1e1e;padding:20px;border-radius:10px;border:1px solid #82aaff;text-align:center}#qrcode{background:#fff;padding:10px;border-radius:6px;margin-bottom:10px}.close-modal-btn{background:#c31e1e;color:#fff;border:none;padding:8px 20px;border-radius:4px;cursor:pointer}@media(max-width:600px){.config-label{width:100%;margin-bottom:2px}.config-code{min-width:100%;order:3}.btn-action{flex:1;order:2}}
</style>
<script>
function copyText(e,t){navigator.clipboard.writeText(document.getElementById(e).innerText).then(()=>{let o=t.innerText;t.innerText="OK",t.style.cssText="background:#c3e88d;color:#121212",setTimeout(()=>{t.innerText=o,t.style.cssText=""},1500)}).catch(e=>console.error(e))}function showQR(e){let t=document.getElementById(e).innerText,o=document.getElementById("qrModal"),n=document.getElementById("qrcode");n.innerHTML="",new QRCode(n,{text:t,width:256,height:256,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.L}),o.style.display="flex"}function closeModal(){document.getElementById("qrModal").style.display="none"}window.onclick=function(e){e.target==document.getElementById("qrModal")&&closeModal()};
</script>
</head><body>
EOF
# --- ЗАПИСЬ BODY (ДИНАМИЧЕСКИЕ ДАННЫЕ) ---
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<h2>📂 Ссылка на подписку (готовый конфиг клиента с роутингом)</h2>
<div class="config-row">
<div class="config-label">Subscription</div>
<div class="config-code" id="subLink">$subPageLink</div>
<button class="btn-action copy-btn" onclick="copyText('subLink', this)">Copy</button>
<button class="btn-action qr-btn" onclick="showQR('subLink')">QR</button>
</div>
<h2>📱 Приложение HAPP (Windows/Android/iOS/MAC/Linux)</h2>
<div class="btn-group">
<a href="happ://add/$subPageLink" class="btn">⚡ Add to HAPP</a>
<a href="https://www.happ.su/main/ru" target="_blank" class="btn download">⬇️ Download App</a>
</div>
<p>Маршрутизацию нужно выключить, она тут встроенная. По умолчанию она выключена - включается, если вы пользовались сторонними сервисами.</p>
<h2>➡️ Конфиги</h2>
EOF
# Цикл генерации строк конфигов
idx=1
for item in "${CONFIGS_ARRAY[@]}"; do
title="${item%%|*}"
link="${item#*|}"
if [ -z "$ALL_LINKS_TEXT" ]; then ALL_LINKS_TEXT="$link"; else ALL_LINKS_TEXT="$ALL_LINKS_TEXT<br>$link"; fi
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<div class="config-row">
<div class="config-label">$title</div>
<div class="config-code" id="c$idx">$link</div>
<button class="btn-action copy-btn" onclick="copyText('c$idx', this)">Copy</button>
<button class="btn-action qr-btn" onclick="showQR('c$idx')">QR</button>
</div>
EOF
((idx++))
done
# Дописываем Socks5, All links и подвал
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<div class="config-row">
<div class="config-label">Socks5 (TG)</div>
<div class="config-code" id="sock">server=$DOMAIN port=10443 user=${socksUser} pass=${socksPasw}</div>
<button class="btn-action copy-btn" onclick="copyText('sock', this)">Copy</button>
<a href="https://t.me/socks?server=$DOMAIN&port=10443&user=${socksUser}&pass=${socksPasw}" target="_blank" class="btn-action qr-btn" title="автодобавление в тг" style="text-decoration:none">✈️ Add to TG</a>
</div>
<h2>💠 Все конфиги вместе</h2>
<div class="config-row">
<div class="config-code" id="cAll" style="max-height:60px;white-space:pre-wrap;word-break:break-all">$ALL_LINKS_TEXT</div>
<button class="btn-action copy-btn" onclick="copyText('cAll', this)">Copy ALL</button>
<button class="btn-action qr-btn" onclick="showQR('cAll')">QR</button>
</div>
<div><a style="color:white;margin:40px auto 20px;display:block;text-align:center;" href="https://github.com/xVRVx/autoXRAY">https://github.com/xVRVx/autoXRAY</a></div>
<div id="qrModal" class="modal-overlay"><div class="modal-content"><div id="qrcode"></div><button class="close-modal-btn" onclick="closeModal()">Close</button></div></div>
</body></html>
EOF
echo -e "
VLESS XHTTP REALITY EXTRA (для моста)
$linkRTY2
VLESS RAW REALITY VISION
$linkRTY1
VLESS XHTTP TLS EXTRA
$linkRTY2
Ваша страничка подписки
\033[1;32m$subPageLink\033[0m
Ссылка на сохраненные конфиги
\033[1;32m$configListLink\033[0m
Скопируйте подписку в специализированное приложение:
- iOS: Happ или v2RayTun или v2rayN
- Android: Happ или v2RayTun или v2rayNG
- Windows: конфиги Happ или winLoadXRAY или v2rayN
для vless v2RayTun или Throne
Открыт локальный socks5 на порту 10808, 2080 и http на 10809.
Поддержать автора: https://github.com/xVRVx/autoXRAY
"