diff --git a/test/autoXRAYselfRUbrEUxhttp-test.sh b/test/autoXRAYselfRUbrEUxhttp-test.sh new file mode 100644 index 0000000..7673125 --- /dev/null +++ b/test/autoXRAYselfRUbrEUxhttp-test.sh @@ -0,0 +1,982 @@ +#!/bin/bash + +# Цвета для вывода +GRN='\033[1;32m' +RED='\033[1;31m' +YEL='\033[1;33m' +NC='\033[0m' # No Color + +[[ $EUID -eq 0 ]] || { echo -e "${RED}❌ скрипту нужны root права ${NC}"; exit 1; } + +DOMAIN=$1 + +vless_url=$2 + +if [ -z "$DOMAIN" ]; then + echo -e "${RED}❌ Ошибка: домен не задан.${NC}" + exit 1 +fi + +if [ -z "$vless_url" ]; then + echo "${RED}❌ Ошибка: конфиг vless не задан.${NC}" + exit 1 +fi + +if [[ "$vless_url" != vless://* ]]; then + echo "${RED}❌ Ошибка: Неверный формат vless-ссылки.${NC}" + exit 1 +fi + + +# Функция URL-декодинга +urldecode() { + printf '%b' "${1//%/\\x}" +} +url_body="${vless_url#vless://}" + +node_name_enc="${url_body##*#}" +node_nameVL="$(urldecode "$node_name_enc")" + +url_body="${url_body%%#*}" + +uuidVL="${url_body%@*}" +host_port_query="${url_body#*@}" + +addressVL="${host_port_query%%:*}" +restVL="${host_port_query#*:}" +portVL="${restVL%%\?*}" + +query_string="${restVL#*\?}" + +# Разбор параметров в ассоциативный массив +declare -A params +IFS='&' read -ra pairs <<< "$query_string" +for pair in "${pairs[@]}"; do + key="${pair%%=*}" + value="${pair#*=}" + params["$key"]="$(urldecode "$value")" +done + + +# Вывод: +echo "${YEL}== Основное ==${NC}" +echo "UUID: $uuidVL" +echo "Address: $addressVL" +echo "Port: $portVL" +echo "Node Name: $node_nameVL" + +echo "" +echo "${YEL}== Параметры ==${NC}" +SECURITY="${params[security]}"; echo "SECURITY=$SECURITY" +TYPE="${params[type]}"; echo "TYPE=$TYPE" +headerType="${params[headerType]}"; echo "headerType=$headerType" +path_url="${params[path]}"; echo "path=$path_url" +host="${params[host]}"; echo "host=$host" +mode="${params[mode]}"; echo "mode=$mode" +extra="${params[extra]}"; echo "extra=$extra" + +SNI="${params[sni]}"; echo "SNI=$SNI" +FP="${params[fp]}"; echo "FP=$FP" +PBK="${params[pbk]}"; echo "PBK=$PBK" +SID="${params[sid]}"; echo "SID=$SID" +SPX="${params[spx]}"; echo "SPX=$SPX" + + +# FLOW="${params[flow]}"; echo "FLOW=$FLOW" + + + +echo "${YEL}Обновление и установка необходимых пакетов...${NC}" +apt-get update && apt-get install curl jq dnsutils openssl nginx certbot-y +systemctl enable --now nginx + +LOCAL_IP=$(hostname -I | awk '{print $1}') +DNS_IP=$(dig +short "$DOMAIN" | grep '^[0-9]') + +if [ "$LOCAL_IP" != "$DNS_IP" ]; then + echo -e "${RED}❌ Внимание: IP-адрес ($LOCAL_IP) не совпадает с A-записью $DOMAIN ($DNS_IP).${NC}" + echo -e "${YEL}Правильно укажите одну A-запись для вашего домена в ДНС - $LOCAL_IP ${NC}" + + read -p "Продолжить на ваш страх и риск? (y/N):" choice + + if [[ ! "$choice" =~ ^[Yy]$ ]]; then + echo -e "${RED}Выполнение скрипта прервано.${NC}" + exit 1 + fi + echo -e "${YEL}Продолжение выполнения скрипта...${NC}" +fi + + +# Включаем BBR +bbr=$(sysctl -a | grep net.ipv4.tcp_congestion_control) +if [ "$bbr" = "net.ipv4.tcp_congestion_control = bbr" ]; then + echo -e "${GRN}BBR уже запущен${NC}" +else + echo "net.core.default_qdisc=fq" > /etc/sysctl.d/999-autoXRAY.conf + echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.d/999-autoXRAY.conf + sysctl --system + echo -e "${GRN}BBR активирован${NC}" +fi + +cat < /etc/security/limits.d/99-autoXRAY.conf +* soft nofile 65535 +* hard nofile 65535 +root soft nofile 65535 +root hard nofile 65535 +EOF +ulimit -n 65535 +echo -e "${GRN}Лимиты применены. Текущий ulimit -n: $(ulimit -n) ${NC}" + + + +# Блок CERTBOT - START +certbot certonly --webroot -w /var/www/html \ + -d $DOMAIN \ + -m mail@$DOMAIN \ + --agree-tos --non-interactive \ + --deploy-hook "systemctl reload nginx" + +RET=$? + +if [ $RET -eq 0 ]; then + echo -e "\n${GRN}========================================" + echo "✅ Команда certbot успешно выполнена" + echo "✅ Сертификат https от letsencrypt ПОЛУЧЕН" + echo "========================================" + echo -e "${NC}" +else + echo -e "\n${RED}========================================" + echo "❌ CERTBOT ЗАВЕРШИЛСЯ С ОШИБКОЙ" + echo "❌ Сертификат https от letsencrypt НЕ ПОЛУЧЕН!" + echo "❌ Смотрите выше логи процесса получения сертификата" + echo "❌ Код возврата: $RET" + echo "========================================" + echo -e "${NC}" + exit 1 +fi +# Блок CERTBOT - END + +# конфиг nginx +CONFIG_PATH="/etc/nginx/sites-available/default" + +bash -c "cat > $CONFIG_PATH" < /dev/null && pwd) +SCRIPT_DIR=/usr/local/etc/xray + +# Генерируем переменные +xray_uuid_vrv=$(xray uuid) +domains=(www.theregister.com www.20minutes.fr www.dealabs.com www.manomano.fr www.caradisiac.com www.techadvisor.com www.computerworld.com teamdocs.su wikiportal.su docscenter.su www.bing.com github.com tradingview.com) +xray_dest_vrv=${domains[$RANDOM % ${#domains[@]}]} +xray_dest_vrv222=${domains[$RANDOM % ${#domains[@]}]} + +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) + +path_subpage=$(openssl rand -base64 15 | tr -dc 'A-Za-z0-9' | head -c 20) + +path_xhttp=$(openssl rand -base64 15 | tr -dc 'a-z0-9' | head -c 6) + +# 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_dest_vrv xray_dest_vrv222 xray_privateKey_vrv xray_publicKey_vrv xray_shortIds_vrv xray_sspasw_vrv DOMAIN path_subpage WEB_PATH TYPE FP SNI SPX PBK SECURITY FLOW SID mode uuidVL addressVL portVL path_xhttp path_url 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": "RUbrEU", + "port": ${portVL}, + "listen": "0.0.0.0", + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "${xray_uuid_vrv}" + } + ], + "decryption": "none" + }, + "sniffing": { + "enabled": true, + "destOverride": [ + "http", + "tls", + "quic" + ] + }, + "streamSettings": { + "network": "xhttp", + "xhttpSettings": { + "mode": "${mode}", + "path": "/${path_xhttp}" + }, + "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": "RUsocks5", + "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": [ + { + "mux": { + "concurrency": -1, + "enabled": false + }, + "tag": "proxy", + "protocol": "vless", + "settings": { + "vnext": [ + { + "port": ${portVL}, + "users": [ + { + "id": "$uuidVL", + "encryption": "none" + } + ], + "address": "$addressVL" + } + ] + }, + "streamSettings": { + "network": "$TYPE", + "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": "${mode}", + "path": "${path_url}" + }, + "security": "$SECURITY", + "realitySettings": { + "show": false, + "fingerprint": "$FP", + "serverName": "$SNI", + "password": "$PBK", + "shortId": "$SID", + "mldsa65Verify": "", + "spiderX": "$SPX" + } + } + }, + { + "tag": "direct", + "protocol": "freedom", + "settings": { + "domainStrategy": "ForceIPv4" + } + }, + { + "tag": "block", + "protocol": "blackhole" + } + ], + "routing": { + "rules": [ + { + "ip": [ + "geoip:private" + ], + "outboundTag": "block" + }, + { + "protocol": [ + "bittorrent" + ], + "outboundTag": "block" + }, + { + "domain": [ + "geosite:category-ads", + "geosite:win-spy", + "geosite:private" + ], + "outboundTag": "block" + }, + { + "domain": [ + "habr.com" + ], + "outboundTag": "proxy" + }, + { + "domain": [ + "testipv6.net", + "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" + }, + { + "inboundTag": [ + "RUbrEU" + ], + "outboundTag": "proxy" + }, + { + "inboundTag": [ + "RUsocks5" + ], + "outboundTag": "proxy" + } + ], + "domainStrategy": "IPIfNonMatch" + } +} + +EOF + +# Создаем JSON конфигурацию клиента +cat << 'EOF' | envsubst > "$WEB_PATH/$path_subpage.json" +[ +{ + "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": [ + { + "mux": { + "concurrency": -1, + "enabled": false + }, + "tag": "proxy", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "$DOMAIN", + "port": ${portVL}, + "users": [ + { + "id": "${xray_uuid_vrv}", + "encryption": "none" + } + ] + } + ] + }, + "streamSettings": { + "network": "$TYPE", + "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": "${mode}", + "path": "/${path_xhttp}" + }, + "security": "reality", + "realitySettings": { + "show": false, + "fingerprint": "chrome", + "serverName": "$DOMAIN", + "password": "${xray_publicKey_vrv}", + "shortId": "${xray_shortIds_vrv}", + "mldsa65Verify": "", + "spiderX": "/" + } + } + }, + { + "tag": "direct", + "protocol": "freedom" + }, + { + "tag": "block", + "protocol": "blackhole" + } + ], + "remarks": "🇪🇺 Bridge RU-EU vlsXHTTPrty" +}, +{ + "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" + }, + { + "type": "field", + "ip": [ + "geoip:!ru" + ], + "outboundTag": "proxy" + }, + { + "domain": [ + "geosite:discord", + "geosite:youtube", + "geosite:tiktok", + "geosite:signal" + ], + "outboundTag": "proxy" + } + ] + }, + "inbounds": [ + { + "tag": "socks-in", + "protocol": "socks", + "listen": "127.0.0.1", + "port": 10808, + "settings": { + "udp": true + } + }, + { + "tag": "socks-sb", + "protocol": "socks", + "listen": "127.0.0.1", + "port": 2080, + "settings": { + "udp": true + } + }, + { + "tag": "http-in", + "protocol": "http", + "listen": "127.0.0.1", + "port": 10809 + } + ], + "outbounds": [ + { + "mux": { + "concurrency": -1, + "enabled": false + }, + "tag": "proxy", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "$addressVL", + "port": ${portVL}, + "users": [ + { + "id": "${uuidVL}", + "encryption": "none" + } + ] + } + ] + }, + "streamSettings": { + "network": "$TYPE", + "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": "${mode}", + "path": "${path_url}" + }, + "security": "$SECURITY", + "realitySettings": { + "show": false, + "fingerprint": "$FP", + "serverName": "$SNI", + "password": "$PBK", + "shortId": "$SID", + "mldsa65Verify": "", + "spiderX": "$SPX" + } + } + }, + { + "tag": "direct", + "protocol": "freedom" + }, + { + "tag": "block", + "protocol": "blackhole" + } + ], + "remarks": "🇪🇺 Direct EU vlsXHTTPrty" +} +] +EOF + +systemctl restart xray +echo -e "Перезапуск XRAY" + +# Формирование ссылок +subPageLink="https://$DOMAIN/$path_subpage.json" + +# Формирование ссылок +link1="vless://${xray_uuid_vrv}@$DOMAIN:${portVL}?security=reality&type=xhttp&headerType=&path=%2F$path_xhttp&host=&mode=${mode}&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#vlsXHTTPrtyRUbrEU" + + +configListLink="https://$DOMAIN/$path_subpage.html" + +CONFIGS_ARRAY=( + "VLESS XHTTP Reality XTLS RUbrEU|$link1" + "Напрямую через EU|$vless_url" +) +ALL_LINKS_TEXT="" + +# --- ЗАПИСЬ HEAD (СТАТИКА, МИНИФИЦИРОВАННЫЕ СТИЛИ И JS) --- +cat > "$WEB_PATH/$path_subpage.html" <<'EOF' + + +autoXRAY configs + + + + + +EOF + +# --- ЗАПИСЬ BODY (ДИНАМИЧЕСКИЕ ДАННЫЕ) --- +cat >> "$WEB_PATH/$path_subpage.html" <📂 Ссылка на подписку (готовый конфиг клиента с роутингом) +
+
Subscription
+ + + +
+ + +

📱 Приложение HAPP (Windows/Android/iOS/MAC/Linux)

+ + +

Маршрутизацию нужно выключить, она тут встроенная. По умолчанию она выключена - включается, если вы пользовались сторонними сервисами.

+ + +

➡️ Конфиги

+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
$link"; fi + + cat >> "$WEB_PATH/$path_subpage.html" < +
$title
+
$link
+ + + +EOF + ((idx++)) +done + +# Дописываем Socks5, All links и подвал +cat >> "$WEB_PATH/$path_subpage.html" < +
Мост Socks5 (TG)
+
server=$DOMAIN port=10443 user=${socksUser} pass=${socksPasw}
+ + ✈️ Add to TG + + +

💠 Все конфиги вместе

+
+
$ALL_LINKS_TEXT
+ + +
+ + + + + +EOF + +# --- ФИНАЛЬНАЯ ПРОВЕРКА --- +echo -e "\n${YEL}=== Финальная проверка статусов ===${NC}" + +# Проверка Nginx +if systemctl is-active --quiet nginx; then + echo -e "Nginx: ${GRN}RUNNING${NC}" +else + echo -e "Nginx: ${RED}STOPPED/ERROR${NC}" +fi + +# Проверка XRAY +if systemctl is-active --quiet xray; then + echo -e "XRAY: ${GRN}RUNNING${NC}" +else + echo -e "XRAY: ${RED}STOPPED/ERROR${NC}" +fi + + +echo -e " +${YEL}VLESS XHTTP REALITY EXTRA (мост RU->EU) ${NC} +$link1 + +${YEL}Ваша json страничка подписки ${NC} +$subPageLink + +${YEL}Ссылка на сохраненные конфиги ${NC} +${GRN}$configListLink ${NC} +Скопируйте подписку в специализированное приложение: +- iOS: Happ или v2RayTun или v2rayN +- Android: Happ или v2RayTun или v2rayNG +- Windows: конфиги Happ или winLoadXRAY или v2rayN + для vless v2RayTun или Throne + +Открыт локальный socks5 на порту 10808, 2080 и http на 10809. + +${GRN}Поддержать автора: https://github.com/xVRVx/autoXRAY ${NC} + +"