From 6a9d454d2a8ab4fb7f170c1a4ce4049ec89396d0 Mon Sep 17 00:00:00 2001 From: Dokril Date: Wed, 24 Dec 2025 11:42:23 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=B2=D0=B5=D0=B1-=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=20=D1=83=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D1=81=D0=BA?= =?UTF-8?q?=D1=80=D0=B8=D0=BF=D1=82=20=D0=B4=D0=BB=D1=8F=20=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BA=D0=BB=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D1=81=D0=BA=D0=B8=D1=85=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B9=20VLESS?= =?UTF-8?q?=20=D0=B8=D0=B7=20URL.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 28 +++++------------ scripts/gen-client-from-url.sh | 56 +++------------------------------- web/index.html | 48 +++++++++++++++++------------ web/server.py | 4 +-- 4 files changed, 42 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 7c415ec..d588417 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - Пользователи, которым нужен VPN для работы или доступа к заблокированным ресурсам - Разработчики, которые хотят направить трафик VS Code или других программ через VPN -- Люди, которые получили "ссылку подписки" от VPN-провайдера +- Люди, которые получили VLESS ссылку от VPN-провайдера --- @@ -57,9 +57,7 @@ ### Что вам понадобится -1. **VPN-ссылка** — получите её от вашего VPN-провайдера. Бывает двух видов: - - **Прямая ссылка**: начинается с `vless://...` - - **Ссылка подписки**: обычный URL (начинается с `https://...`), который содержит список серверов +1. **VLESS-ссылка** — получите её от вашего VPN-провайдера. Она начинается с `vless://...` 2. **Docker** — программа для запуска изолированных приложений - [Скачать Docker Desktop](https://www.docker.com/products/docker-desktop/) (бесплатно) @@ -90,7 +88,7 @@ docker compose up -d ### После запуска 1. **Откройте веб-интерфейс**: http://localhost:3456 -2. **Вставьте вашу VPN-ссылку** (vless:// или https://) +2. **Вставьте вашу VLESS-ссылку** (vless://) 3. **Нажмите "Применить"** 4. Готово! Прокси работает на порту **8082** @@ -174,24 +172,14 @@ http.proxy: http://127.0.0.1:8082 --- -## 🔄 Смена сервера -### Через веб-интерфейс (рекомендуется) + +### Через веб-интерфейс 1. Откройте http://localhost:3456 -2. Вставьте новую ссылку +2. Вставьте новую VLESS ссылку 3. Нажмите "Применить" -### Через консоль (если нужен выбор из списка) - -Если у вас ссылка подписки с несколькими серверами: - -```bash -docker exec -it sing-proxy ./menu.sh "https://ваша-ссылка-подписки..." -``` - -Появится список серверов для выбора. - --- ## 📋 Управление контейнером @@ -250,7 +238,7 @@ docker compose up -d **Решение**: - Попробуйте другой сервер — вставьте другую ссылку в веб-интерфейсе -- Проверьте, что ссылка подписки актуальна +- Проверьте, что VLESS ссылка актуальна ### Как узнать, работает ли VPN? @@ -311,7 +299,7 @@ environment: | **Контейнер** | Изолированное приложение со всеми необходимыми компонентами | | **VLESS** | Современный протокол VPN-соединения | | **Reality** | Технология маскировки VPN-трафика под обычный интернет-трафик | -| **Ссылка подписки** | URL, который содержит список VPN-серверов и их настройки | + | **Порт** | "Номер двери" для сетевых соединений. Прокси: 8082, Веб-интерфейс: 3456 | --- diff --git a/scripts/gen-client-from-url.sh b/scripts/gen-client-from-url.sh index b5ed30d..d89a297 100755 --- a/scripts/gen-client-from-url.sh +++ b/scripts/gen-client-from-url.sh @@ -19,58 +19,10 @@ if [[ ! -f "$TEMPLATE_FILE" ]]; then exit 1 fi -# Detect if input is a subscription link (HTTP/HTTPS) -if [[ "$URL_INPUT" =~ ^http ]]; then - echo "Detecting subscription link..." - - # Build URL with client parameter for APIs that require it - SUB_URL="$URL_INPUT" - - # Try fetching as-is first - SUB_CONTENT=$(curl -sSL "$SUB_URL") - - # If empty, try adding client parameter (some APIs require this) - if [[ -z "$SUB_CONTENT" ]]; then - echo "Empty response, trying with client=v2rayng parameter..." - if [[ "$SUB_URL" == *"?"* ]]; then - SUB_URL="${URL_INPUT}&client=v2rayng" - else - SUB_URL="${URL_INPUT}?client=v2rayng" - fi - SUB_CONTENT=$(curl -sSL "$SUB_URL") - fi - - if [[ -z "$SUB_CONTENT" ]]; then - echo "Error: Failed to download subscription from $SUB_URL" >&2 - exit 1 - fi - - # Check if base64 encoded (simple check: no spaces, looks like b64) - # Trying to decode. If fails, assume it's plain text lists - if DECODED=$(echo "$SUB_CONTENT" | base64 -d 2>/dev/null); then - echo "Decoded base64 subscription." - RAW_CONFIGS="$DECODED" - else - echo "Using plain text subscription." - RAW_CONFIGS="$SUB_CONTENT" - fi - - # Find first vless reality link (vless://... + security=reality or just vless://) - # We try to find one that explicitly has reality, if not, pick ANY vless - TARGET_URL=$(echo "$RAW_CONFIGS" | grep -o 'vless://[^[:space:]]*' | grep 'security=reality' | head -n 1) - - if [[ -z "$TARGET_URL" ]]; then - echo "No VLESS Reality link found, trying any VLESS..." - TARGET_URL=$(echo "$RAW_CONFIGS" | grep -o 'vless://[^[:space:]]*' | head -n 1) - fi - - if [[ -z "$TARGET_URL" ]]; then - echo "Error: No VLESS URL found in subscription." >&2 - exit 1 - fi - - echo "Selected URL from subscription: ${TARGET_URL:0:30}..." - URL_INPUT="$TARGET_URL" +# Check if input starts with vless:// +if [[ "$URL_INPUT" != vless://* ]]; then + echo "Error: Only vless:// URLs are supported." >&2 + exit 1 fi # Strip scheme diff --git a/web/index.html b/web/index.html index 3db378a..bc2aafd 100644 --- a/web/index.html +++ b/web/index.html @@ -1,5 +1,6 @@ + @@ -35,7 +36,7 @@ align-items: center; justify-content: center; padding: 2rem; - background-image: + background-image: radial-gradient(ellipse at top, rgba(99, 102, 241, 0.1) 0%, transparent 50%), radial-gradient(ellipse at bottom right, rgba(168, 85, 247, 0.08) 0%, transparent 50%); } @@ -51,7 +52,7 @@ border: 1px solid var(--border-color); border-radius: 24px; padding: 2.5rem; - box-shadow: + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05); @@ -113,8 +114,15 @@ } @keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.6; } + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0.6; + } } .status-text { @@ -223,7 +231,9 @@ } @keyframes spin { - to { transform: rotate(360deg); } + to { + transform: rotate(360deg); + } } .message { @@ -242,6 +252,7 @@ opacity: 0; transform: translateY(-8px); } + to { opacity: 1; transform: translateY(0); @@ -346,6 +357,7 @@ } +
@@ -365,17 +377,12 @@
- +
- +
-

Вставьте VLESS ссылку или URL подписки

+

Вставьте VLESS ссылку

@@ -424,10 +431,10 @@ try { const res = await fetch('/status'); const data = await res.json(); - + if (data.active) { statusIndicator.classList.add('active'); - statusValue.textContent = data.tag + statusValue.textContent = data.tag ? `${data.tag} (${data.server})` : 'Активен'; } else { @@ -456,7 +463,7 @@ form.addEventListener('submit', async (e) => { e.preventDefault(); - + const url = urlInput.value.trim(); if (!url) { showMessage('error', 'Введите URL'); @@ -498,7 +505,7 @@ const hostname = window.location.hostname; const httpLink = document.getElementById('httpLink'); const socksLink = document.getElementById('socksLink'); - + httpLink.textContent = `http://${hostname}:8082`; socksLink.textContent = `socks5://${hostname}:8082`; @@ -513,4 +520,5 @@ }); - + + \ No newline at end of file diff --git a/web/server.py b/web/server.py index 7e5ab0c..1702829 100644 --- a/web/server.py +++ b/web/server.py @@ -115,8 +115,8 @@ class ProxyControlHandler(http.server.BaseHTTPRequestHandler): self.send_json({"success": False, "error": "URL не указан"}, 400) return - if not (url.startswith("vless://") or url.startswith("http://") or url.startswith("https://")): - self.send_json({"success": False, "error": "Неверный формат URL. Ожидается vless:// или http(s):// ссылка"}, 400) + if not url.startswith("vless://"): + self.send_json({"success": False, "error": "Неверный формат. Поддерживаются только vless:// ссылки"}, 400) return # Run gen-client-from-url.sh