diff --git a/README.md b/README.md index b58d086..7bd2de6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ ``` ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Ваш браузер │────▶│ VPN Proxy │────▶│ VPN Сервер │────▶ Интернет -│ или VS Code │ │ (порт 8082) │ │ (в другой стране)│ +│ или VS Code │ │ (порт 8080) │ │ (в другой стране)│ └─────────────────┘ └──────────────────┘ └──────────────────┘ ▲ │ @@ -44,6 +44,7 @@ | --------------------------- | ------------------------------------------------------------------ | | `install-docker-proxy.ps1` | 🚀 **Автоустановщик** — скачайте и запустите, всё сделает сам | | `discord-windows-hack.ps1` | 🎮 Установка ProxiFyre для Discord/Vesktop | +| `setup-singbox-native.ps1` | 🎯 Нативный sing-box для Discord UDP (голосовые) | | `web/server.py` | Веб-интерфейс для управления через браузер | | `web/index.html` | Страница с красивым интерфейсом | | `docker/entrypoint.sh` | Главный скрипт запуска контейнера | @@ -120,7 +121,7 @@ docker compose up -d 2. **Выберите режим**: - **📡 Подписка**: вставьте URL подписки, нажмите «Загрузить серверы», выберите сервер и нажмите «Применить» - **🔑 VLESS Ключ**: вставьте VLESS-ссылку и нажмите «Применить» -3. Готово! Прокси работает на порту **8082** +3. Готово! Прокси работает на порту **8080** > 💡 **Подписка сохраняется** между перезагрузками контейнера — URL и выбранный сервер хранятся в папке `data/` @@ -153,7 +154,7 @@ docker compose up -d | Порт | Для чего | URL | | ------ | ------------------------------------------------- | ----------------------- | | `3456` | **Веб-интерфейс** — управление через браузер | http://localhost:3456 | -| `2412` | **Прокси** — сюда подключаются браузер/приложения | `http://127.0.0.1:8082` | +| `8080` | **Прокси** — сюда подключаются браузер/приложения | `http://127.0.0.1:8080` | | `9090` | Внутренний порт управления (обычно не нужен) | — | --- @@ -168,7 +169,7 @@ docker compose up -d ```bash # Через прокси — должен показать IP VPN-сервера -curl -x http://127.0.0.1:8082 https://ipinfo.io/json +curl -x http://127.0.0.1:8080 https://ipinfo.io/json ``` Если показывает IP другой страны — VPN работает! 🎉 @@ -182,14 +183,14 @@ curl -x http://127.0.0.1:8082 https://ipinfo.io/json Откройте настройки (Cmd+, на Mac или Ctrl+, на Windows), найдите "proxy" и добавьте: ``` -http.proxy: http://127.0.0.1:8082 +http.proxy: http://127.0.0.1:8080 ``` Или добавьте в `settings.json`: ```json { - "http.proxy": "http://127.0.0.1:8082", + "http.proxy": "http://127.0.0.1:8080", "http.proxyStrictSSL": true } ``` @@ -200,7 +201,7 @@ http.proxy: http://127.0.0.1:8082 - **Тип**: HTTP или SOCKS5 - **Адрес**: `127.0.0.1` -- **Порт**: `8082` +- **Порт**: `8080` ### Для Discord / Vesktop (Windows) @@ -215,7 +216,26 @@ Discord не поддерживает системные настройки пр - Устанавливает драйвер Windows Packet Filter - Устанавливает ProxiFyre как службу Windows - Настраивает перехват трафика для Discord/Vesktop -- Направляет его через прокси `127.0.0.1:8082` +- Направляет его через прокси `127.0.0.1:8080` + +> ⚠️ **Важно:** Docker Desktop на Windows **не поддерживает UDP**. Голосовые звонки Discord могут не работать. +> Для полной поддержки голоса используйте `setup-singbox-native.ps1`. + +### 🎯 Нативный sing-box для Discord (голосовые звонки) + +Если Docker запущен локально на Windows и голосовые звонки Discord не работают: + +```powershell +# Запустите от имени Администратора +.\setup-singbox-native.ps1 +``` + +**Что делает скрипт:** +- Спрашивает режим работы (удалённый прокси или локальный Docker) +- Загружает sing-box v1.11.4 для Windows +- Работает с подписками (как веб-интерфейс) +- Создаёт задачу автозапуска в Планировщике Windows +- Настраивает ProxiFyre на локальный SOCKS5 (порт 1080) **Если ProxiFyre уже установлен:** При повторном запуске скрипт покажет: @@ -300,7 +320,7 @@ docker compose up -d curl https://ipinfo.io/json # Через прокси — должен показать IP VPN-сервера -curl -x http://127.0.0.1:8082 https://ipinfo.io/json +curl -x http://127.0.0.1:8080 https://ipinfo.io/json ``` Если IP-адреса разные — VPN работает! 🎉 @@ -333,7 +353,7 @@ curl -x http://127.0.0.1:8082 https://ipinfo.io/json | **VLESS** | Современный протокол VPN-соединения | | **Reality** | Технология маскировки VPN-трафика под обычный интернет-трафик | -| **Порт** | "Номер двери" для сетевых соединений. Прокси: 8082, Веб-интерфейс: 3456 | +| **Порт** | "Номер двери" для сетевых соединений. Прокси: 8080, Веб-интерфейс: 3456 | --- diff --git a/discord-windows-hack.ps1 b/discord-windows-hack.ps1 index c4a8934..bbc361e 100644 --- a/discord-windows-hack.ps1 +++ b/discord-windows-hack.ps1 @@ -3,7 +3,7 @@ # ========================================== param( [switch]$Force, # Принудительная переустановка - [string]$Proxy = "", # Адрес прокси (для неинтерактивного режима), например "127.0.0.1:8082" + [string]$Proxy = "", # Адрес прокси (для неинтерактивного режима), например "127.0.0.1:8080" [string[]]$Apps = @(), # Приложения (для неинтерактивного режима), например @("Discord", "Vesktop") [switch]$Silent # Тихий режим (без лишнего вывода, для вызова из других скриптов) ) @@ -44,9 +44,11 @@ if ($proxifyreExists -and -not $Force) { Write-Host "📊 Статус службы: " -NoNewline -ForegroundColor Yellow if ($proxifyreService -and $proxifyreService.Status -eq 'Running') { Write-Host "РАБОТАЕТ" -ForegroundColor Green - } elseif ($proxifyreService) { + } + elseif ($proxifyreService) { Write-Host "$($proxifyreService.Status)" -ForegroundColor Red - } else { + } + else { Write-Host "НЕ ЗАРЕГИСТРИРОВАНА" -ForegroundColor Red } @@ -68,7 +70,8 @@ if ($proxifyreExists -and -not $Force) { Write-Host " Прокси: $proxy" -ForegroundColor White Write-Host " Приложения: $apps" -ForegroundColor White Write-Host "" - } catch { + } + catch { Write-Host " ⚠️ Не удалось прочитать конфиг" -ForegroundColor Yellow } } @@ -114,14 +117,90 @@ if ($proxifyreExists -and -not $Force) { } "4" { Write-Host "`n⚙️ Изменение настроек..." -ForegroundColor Cyan - # Продолжаем выполнение скрипта для настройки + + # Выбор режима + Write-Host "" + Write-Host "📡 Где работает VPN-прокси?" -ForegroundColor Yellow + Write-Host " [1] Удалённый сервер (Docker на VPS/другом ПК)" -ForegroundColor White + Write-Host " [2] Локальный Docker Desktop (на этом ПК)" -ForegroundColor White + $modeChoice = Read-Host "👉 Выбор (1-2)" + + if ($modeChoice -eq "2") { + # Локальный Docker — нужен sing-box + $singboxTask = Get-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue + if ($singboxTask -and $singboxTask.State -eq "Running") { + Write-Host "`n✅ Нативный sing-box работает!" -ForegroundColor Green + $NewProxy = "127.0.0.1:1080" + } + else { + Write-Host "`n⚠️ Нативный sing-box не запущен!" -ForegroundColor Yellow + Write-Host " Запустите: .\setup-singbox-native.ps1" -ForegroundColor Cyan + $runSetup = Read-Host " Запустить сейчас? (y/n)" + if ($runSetup -eq "y") { + $setupScript = Join-Path $PSScriptRoot "setup-singbox-native.ps1" + if (Test-Path $setupScript) { & $setupScript } + } + $NewProxy = "127.0.0.1:1080" + } + } + else { + # Удалённый прокси + Write-Host "`n🌐 SOCKS5 Прокси (IP:PORT):" -ForegroundColor Yellow + $NewProxy = Read-Host " [Enter] для 127.0.0.1:8080" + if ([string]::IsNullOrWhiteSpace($NewProxy)) { $NewProxy = "127.0.0.1:8080" } + } + + # Запрос приложений + Write-Host "`n🎮 Что проксируем?" -ForegroundColor Yellow + Write-Host " [1] Vesktop" + Write-Host " [2] Discord" + Write-Host " [3] Vesktop + Discord" + $AppChoice = Read-Host "👉 Выбор (1-3)" + + switch ($AppChoice) { + "2" { $NewApps = @("Discord") } + "3" { $NewApps = @("Vesktop", "Discord") } + Default { $NewApps = @("Vesktop") } + } + + # Генерируем новый конфиг + Write-Host "`n📝 Обновляем конфиг..." -ForegroundColor Cyan + $ConfigData = @{ + logLevel = "Info" + proxies = @( + @{ + appNames = $NewApps + socks5ProxyEndpoint = $NewProxy + username = "" + password = "" + supportedProtocols = @("TCP", "UDP") + } + ) + excludes = @() + } | ConvertTo-Json -Depth 4 + Set-Content -Path $configPath -Value $ConfigData -Encoding UTF8 + + Write-Host " ✅ Конфиг обновлён:" -ForegroundColor Green + Write-Host " Прокси: $NewProxy" -ForegroundColor White + Write-Host " Приложения: $($NewApps -join ', ')" -ForegroundColor White + + # Перезапуск службы + Write-Host "`n🔄 Перезапуск службы для применения..." -ForegroundColor Cyan + Start-Process -FilePath "$InstallPath\ProxiFyre.exe" -ArgumentList "stop" -Wait -NoNewWindow + Start-Sleep -s 1 + Start-Process -FilePath "$InstallPath\ProxiFyre.exe" -ArgumentList "start" -Wait -NoNewWindow + Start-Sleep -s 2 + $svc = Get-Service -Name "ProxiFyreService" -ErrorAction SilentlyContinue + Write-Host " Статус: $($svc.Status)" -ForegroundColor Green + exit 0 } "5" { Write-Host "`n📋 Логи ProxiFyre:" -ForegroundColor Cyan $logFiles = Get-ChildItem "$InstallPath\logs\*.log" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($logFiles) { Get-Content $logFiles.FullName -Tail 50 - } else { + } + else { Write-Host " Лог-файлы не найдены" -ForegroundColor Yellow } exit 0 @@ -130,14 +209,16 @@ if ($proxifyreExists -and -not $Force) { Write-Host "`n📄 Конфиг ProxiFyre:" -ForegroundColor Cyan if (Test-Path $configPath) { Get-Content $configPath - } else { + } + else { Write-Host " Конфиг не найден" -ForegroundColor Yellow } exit 0 } "7" { Write-Host "`n🔧 Переустановка..." -ForegroundColor Cyan - # Продолжаем выполнение скрипта + $Force = $true + # Продолжаем выполнение скрипта для полной переустановки } default { Write-Host "`n ℹ️ Выход" -ForegroundColor Gray @@ -157,11 +238,77 @@ if ($Proxy -and $Apps.Count -gt 0) { Write-Host " Прокси: $UserProxy" -ForegroundColor White Write-Host " Приложения: $($TargetApps -join ', ')" -ForegroundColor White } -} else { - # Интерактивный режим - Write-Host "`n🌐 SOCKS5 Прокси (IP:PORT):" -ForegroundColor Yellow - $UserProxy = Read-Host " [Enter] для 127.0.0.1:8082" - if ([string]::IsNullOrWhiteSpace($UserProxy)) { $UserProxy = "127.0.0.1:8082" } +} +else { + # Интерактивный режим — сначала выбор режима + Write-Host "" + Write-Host "==========================================" -ForegroundColor Cyan + Write-Host " 📡 ГДЕ РАБОТАЕТ ВАШ VPN-ПРОКСИ? " -ForegroundColor Cyan + Write-Host "==========================================" -ForegroundColor Cyan + Write-Host "" + Write-Host " [1] 🌐 УДАЛЁННЫЙ СЕРВЕР" -ForegroundColor White + Write-Host " Docker на VPS или другом ПК в сети" -ForegroundColor Gray + Write-Host " (UDP работает, просто укажите адрес)" -ForegroundColor Gray + Write-Host "" + Write-Host " [2] 💻 ЛОКАЛЬНЫЙ DOCKER НА WINDOWS" -ForegroundColor White + Write-Host " Docker Desktop на этом компьютере" -ForegroundColor Gray + Write-Host " (UDP НЕ работает, нужен нативный sing-box)" -ForegroundColor Gray + Write-Host "" + + $modeChoice = Read-Host "👉 Выбор (1-2)" + + if ($modeChoice -eq "2") { + # Локальный Docker — нужен нативный sing-box + Write-Host "" + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host " ⚠️ ЛОКАЛЬНЫЙ DOCKER DESKTOP " -ForegroundColor Yellow + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host "" + Write-Host "Docker Desktop на Windows НЕ поддерживает UDP!" -ForegroundColor Red + Write-Host "Для голосовых звонков Discord нужен нативный sing-box." -ForegroundColor Red + Write-Host "" + + # Проверяем, установлен ли уже нативный sing-box + $singboxInstalled = Test-Path "C:\Tools\sing-box\sing-box.exe" + $singboxTask = Get-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue + + if ($singboxInstalled -and $singboxTask -and $singboxTask.State -eq "Running") { + Write-Host "✅ Нативный sing-box уже установлен и работает!" -ForegroundColor Green + Write-Host " Прокси: 127.0.0.1:1080" -ForegroundColor White + $UserProxy = "127.0.0.1:1080" + } + else { + Write-Host "Для установки нативного sing-box запустите:" -ForegroundColor Yellow + Write-Host " .\setup-singbox-native.ps1" -ForegroundColor Cyan + Write-Host "" + + $runSetup = Read-Host "Запустить setup-singbox-native.ps1 сейчас? (y/n)" + if ($runSetup -eq "y") { + $setupScript = Join-Path $PSScriptRoot "setup-singbox-native.ps1" + if (Test-Path $setupScript) { + & $setupScript + # После установки используем порт 1080 + $UserProxy = "127.0.0.1:1080" + } + else { + Write-Host "❌ Скрипт setup-singbox-native.ps1 не найден!" -ForegroundColor Red + exit 1 + } + } + else { + Write-Host "" + Write-Host "Установите sing-box вручную и повторите." -ForegroundColor Yellow + exit 0 + } + } + } + else { + # Удалённый прокси — просто спрашиваем адрес + Write-Host "`n🌐 SOCKS5 Прокси (IP:PORT):" -ForegroundColor Yellow + Write-Host " Примеры: 192.168.1.100:8080, myserver.com:8080" -ForegroundColor Gray + $UserProxy = Read-Host " [Enter] для 127.0.0.1:8080" + if ([string]::IsNullOrWhiteSpace($UserProxy)) { $UserProxy = "127.0.0.1:8080" } + } Write-Host "`n🎮 Что проксируем?" -ForegroundColor Yellow Write-Host " [1] Vesktop" @@ -193,7 +340,8 @@ try { $Proc = Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$MsiFile`" /qn /norestart" -Wait -PassThru if ($Proc.ExitCode -eq 0) { Write-Host " ✅ Успешно." -ForegroundColor Green } elseif ($Proc.ExitCode -eq 1603) { Write-Host " ⚠️ Уже установлен." -ForegroundColor Yellow } -} catch { +} +catch { Write-Error "❌ Ошибка скачивания драйвера: $_"; Exit } @@ -209,7 +357,8 @@ try { Invoke-WebRequest -Uri $AppUrl -OutFile $ZipFile -ErrorAction Stop Expand-Archive -Path $ZipFile -DestinationPath $InstallPath -Force Write-Host " ✅ Распаковано." -ForegroundColor Green -} catch { +} +catch { Write-Error "❌ Ошибка скачивания ProxiFyre: $_"; Exit } @@ -224,13 +373,13 @@ Write-Host "`n📝 [3/3] Генерируем конфиг..." -ForegroundColor $ConfigPath = Join-Path -Path $InstallPath -ChildPath "app-config.json" $ConfigData = @{ logLevel = "Info" - proxies = @( + proxies = @( @{ - appNames = $TargetApps + appNames = $TargetApps socks5ProxyEndpoint = $UserProxy - username = "" - password = "" - supportedProtocols = @("TCP", "UDP") + username = "" + password = "" + supportedProtocols = @("TCP", "UDP") } ) excludes = @() @@ -263,7 +412,8 @@ if ($Service -and $Service.Status -eq 'Running') { Write-Host "🎉 УСПЕХ! Служба работает в фоне." -ForegroundColor Green Write-Host "📁 Логи тут: $InstallPath\logs" Write-Host "==========================================" -} else { +} +else { Write-Host "`n⚠️ Служба установлена, но статус: $($Service.Status). Проверь логи." -ForegroundColor Red Write-Host "Попробуй вручную: net start ProxiFyreService" } \ No newline at end of file diff --git a/install-docker-proxy.ps1 b/install-docker-proxy.ps1 index 55cda54..36dba8f 100644 --- a/install-docker-proxy.ps1 +++ b/install-docker-proxy.ps1 @@ -50,7 +50,8 @@ if ($existingContainer -and -not $Force) { Write-Host "РАБОТАЕТ" -ForegroundColor Green Write-Host " Контейнер: sing-proxy" -ForegroundColor Gray Write-Host " Uptime: $containerRunning" -ForegroundColor Gray - } else { + } + else { Write-Host "📊 Статус: " -NoNewline -ForegroundColor Yellow Write-Host "ОСТАНОВЛЕН" -ForegroundColor Red $containerStatus = docker ps -a --filter "name=sing-proxy" --format "{{.Status}}" 2>$null @@ -60,7 +61,7 @@ if ($existingContainer -and -not $Force) { Write-Host "" Write-Host "📡 Адреса подключения:" -ForegroundColor Yellow Write-Host " Веб-интерфейс: http://localhost:3456" -ForegroundColor White - Write-Host " HTTP/SOCKS Прокси: 127.0.0.1:8082" -ForegroundColor White + Write-Host " HTTP/SOCKS Прокси: 127.0.0.1:8080" -ForegroundColor White Write-Host "" Write-Host "📁 Расположение:" -ForegroundColor Yellow Write-Host " Проект: $ScriptDir" -ForegroundColor White @@ -84,7 +85,8 @@ if ($existingContainer -and -not $Force) { $proxy = $config.proxies[0].socks5ProxyEndpoint Write-Host " Прокси: $proxy" -ForegroundColor White Write-Host " Приложения: $apps" -ForegroundColor White - } catch {} + } + catch {} } Write-Host "" } @@ -155,7 +157,8 @@ try { Write-Success "Docker установлен: $dockerVersion" $DockerInstalled = $true } -} catch { +} +catch { $DockerInstalled = $false } @@ -186,7 +189,8 @@ if ($DockerInstalled) { Write-Success "Docker daemon запущен" $DockerRunning = $true } - } catch { + } + catch { $DockerRunning = $false } @@ -214,17 +218,20 @@ if ($DockerInstalled) { if ($LASTEXITCODE -eq 0) { $DockerRunning = $true } - } catch {} + } + catch {} } Write-Host "" if ($DockerRunning) { Write-Success "Docker запустился!" - } else { + } + else { Write-Error "Таймаут ожидания Docker. Запустите Docker Desktop вручную." exit 1 } - } else { + } + else { exit 1 } } @@ -238,7 +245,8 @@ if ($DockerRunning) { Write-Success "Docker Compose доступен: $composeVersion" $DockerComposeAvailable = $true } - } catch {} + } + catch {} if (-not $DockerComposeAvailable) { # Пробуем старый формат docker-compose @@ -248,7 +256,8 @@ if ($DockerRunning) { Write-Success "Docker Compose (legacy) доступен: $composeVersion" $DockerComposeAvailable = $true } - } catch {} + } + catch {} } if (-not $DockerComposeAvailable -and -not $SkipDockerCheck) { @@ -316,7 +325,8 @@ try { } Write-Success "Контейнер запущен" -} finally { +} +finally { Pop-Location } @@ -328,7 +338,8 @@ Write-Step "Проверка статуса..." $containerStatus = docker ps --filter "name=sing-proxy" --format "{{.Status}}" 2>&1 if ($containerStatus -match "Up") { Write-Success "Контейнер sing-proxy работает: $containerStatus" -} else { +} +else { Write-Warning "Контейнер может ещё запускаться. Проверьте через: docker ps" } @@ -342,7 +353,7 @@ Write-Host "==========================================" -ForegroundColor Green Write-Host "" Write-Host "📡 Адреса подключения:" -ForegroundColor Yellow Write-Host " Веб-интерфейс: http://localhost:3456" -ForegroundColor White -Write-Host " HTTP/SOCKS Прокси: 127.0.0.1:8082" -ForegroundColor White +Write-Host " HTTP/SOCKS Прокси: 127.0.0.1:8080" -ForegroundColor White Write-Host "" Write-Host "📋 Следующие шаги:" -ForegroundColor Yellow Write-Host " 1. Откройте http://localhost:3456 в браузере" -ForegroundColor White @@ -381,7 +392,8 @@ if (-not $SkipDiscord) { Write-Host " cd `"$ScriptDir`"" -ForegroundColor Cyan Write-Host " .\discord-windows-hack.ps1" -ForegroundColor Cyan Write-Host "" - } else { + } + else { # Запускаем скрипт с параметрами для неинтерактивного режима $discordScript = Join-Path $ScriptDir "discord-windows-hack.ps1" @@ -396,14 +408,31 @@ if (-not $SkipDiscord) { } # Вызываем discord-windows-hack.ps1 с параметрами (без дублирования кода) - & $discordScript -Proxy "127.0.0.1:8082" -Apps $targetApps -Force + & $discordScript -Proxy "127.0.0.1:8080" -Apps $targetApps -Force - } else { + # Предупреждение о UDP + Write-Host "" + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host " ⚠️ ВАЖНО: ГОЛОСОВЫЕ ЗВОНКИ DISCORD " -ForegroundColor Yellow + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host "" + Write-Host "Docker Desktop на Windows НЕ ПОДДЕРЖИВАЕТ UDP!" -ForegroundColor Red + Write-Host "Голосовые звонки Discord могут не работать." -ForegroundColor Red + Write-Host "" + Write-Host "Для полной поддержки голоса запустите:" -ForegroundColor Cyan + Write-Host " .\setup-singbox-native.ps1" -ForegroundColor White + Write-Host "" + Write-Host "Этот скрипт установит нативный sing-box," -ForegroundColor Gray + Write-Host "который поддерживает UDP трафик." -ForegroundColor Gray + + } + else { Write-Warning "Скрипт discord-windows-hack.ps1 не найден" Write-Info "Скачайте его или создайте вручную" } } - } else { + } + else { Write-Info "Установка Discord прокси пропущена" } } diff --git a/setup-singbox-native.ps1 b/setup-singbox-native.ps1 new file mode 100644 index 0000000..17eef4e --- /dev/null +++ b/setup-singbox-native.ps1 @@ -0,0 +1,439 @@ +# ========================================== +# 🎯 SING-BOX NATIVE INSTALLER FOR WINDOWS +# ========================================== +# Устанавливает нативный sing-box для поддержки UDP (Discord голосовые) +# Используется когда Docker запущен ЛОКАЛЬНО на Windows +# (Docker Desktop не поддерживает UDP) +# ========================================== + +param( + [switch]$Force, # Принудительная переустановка + [string]$SubscriptionUrl = "" # URL подписки (для неинтерактивного режима) +) + +# ========================================== +# КОНФИГУРАЦИЯ +# ========================================== +$SingboxVersion = "1.11.4" +$InstallDir = "C:\Tools\sing-box" +$LocalProxyPort = 1080 + +# Ссылки для скачивания +$SingboxUrl = "https://github.com/SagerNet/sing-box/releases/download/v$SingboxVersion/sing-box-$SingboxVersion-windows-amd64.zip" + +# App Info (для заголовков подписки) +$AppName = "VPN-Proxy-Control by Dokril" + +# ========================================== +# ЦВЕТА И ВЫВОД +# ========================================== +function Write-Step { param($msg) Write-Host "`n📦 $msg" -ForegroundColor Cyan } +function Write-Success { param($msg) Write-Host " ✅ $msg" -ForegroundColor Green } +function Write-Warning { param($msg) Write-Host " ⚠️ $msg" -ForegroundColor Yellow } +function Write-Error { param($msg) Write-Host " ❌ $msg" -ForegroundColor Red } +function Write-Info { param($msg) Write-Host " ℹ️ $msg" -ForegroundColor Gray } + +# ========================================== +# ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ +# ========================================== + +function Get-HWID { + $hwidFile = "$InstallDir\hwid" + if (Test-Path $hwidFile) { + return (Get-Content $hwidFile -Raw).Trim() + } + + $hwid = [System.Guid]::NewGuid().ToString("N").Substring(0, 16) + + if (!(Test-Path $InstallDir)) { + New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null + } + + Set-Content -Path $hwidFile -Value $hwid + return $hwid +} + +function Get-SystemInfo { + return @{ + os = "windows" + version = [System.Environment]::OSVersion.Version.Major.ToString() + } +} + +function Get-SubscriptionData { + param([string]$Url) + + Write-Info "Загружаю подписку..." + + $hwid = Get-HWID + $sysInfo = Get-SystemInfo + + $headers = @{ + "User-Agent" = "singbox" + "x-hwid" = $hwid + "x-device-os" = $sysInfo.os + "x-ver-os" = $sysInfo.version + "x-device-model" = $AppName + } + + try { + $response = Invoke-WebRequest -Uri $Url -Headers $headers -TimeoutSec 15 -UseBasicParsing + $config = $response.Content | ConvertFrom-Json + + $userInfo = @{} + $userInfoHeader = $response.Headers["subscription-userinfo"] + if ($userInfoHeader) { + $parts = $userInfoHeader -split ";" + foreach ($part in $parts) { + if ($part -match "(\w+)=(\d+)") { + $userInfo[$matches[1]] = [int64]$matches[2] + } + } + } + + return @{ + success = $true + config = $config + userInfo = $userInfo + } + } + catch { + return @{ + success = $false + error = $_.Exception.Message + } + } +} + +function Select-Server { + param($Config) + + $outbounds = $Config.outbounds + $servers = @() + + foreach ($outbound in $outbounds) { + if ($outbound.type -in @("vless", "vmess", "trojan", "shadowsocks", "hysteria2")) { + $servers += @{ + tag = $outbound.tag + type = $outbound.type + server = $outbound.server + server_port = $outbound.server_port + outbound = $outbound + } + } + } + + if ($servers.Count -eq 0) { + Write-Error "Серверы не найдены в подписке!" + return $null + } + + Write-Host "`n🌐 Доступные серверы:" -ForegroundColor Yellow + for ($i = 0; $i -lt $servers.Count; $i++) { + $s = $servers[$i] + Write-Host " [$($i+1)] $($s.tag) ($($s.type)) - $($s.server):$($s.server_port)" + } + + $choice = Read-Host "`n👉 Выберите сервер (1-$($servers.Count))" + $index = [int]$choice - 1 + + if ($index -lt 0 -or $index -ge $servers.Count) { + Write-Error "Неверный выбор!" + return $null + } + + return $servers[$index] +} + +function New-SingboxConfig { + param($Outbound, $Port) + + $config = @{ + log = @{ + level = "info" + timestamp = $true + } + dns = @{ + independent_cache = $true + } + inbounds = @( + @{ + type = "socks" + tag = "socks-in" + listen = "127.0.0.1" + listen_port = $Port + } + ) + outbounds = @( + $Outbound, + @{ + type = "direct" + tag = "direct" + } + ) + route = @{ + final = $Outbound.tag + auto_detect_interface = $true + } + } + + return $config +} + +function Install-SingboxTask { + Write-Step "Установка sing-box через Task Scheduler..." + + $exePath = "$InstallDir\sing-box.exe" + $configPath = "$InstallDir\config.json" + $taskName = "SingBoxProxy" + + # Удаляем старую задачу + Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue + + # Создаём новую + $action = New-ScheduledTaskAction -Execute "$exePath" -Argument "run -c `"$configPath`"" -WorkingDirectory $InstallDir + $trigger = New-ScheduledTaskTrigger -AtStartup + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) + + Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null + + # Запускаем сразу + Start-ScheduledTask -TaskName $taskName + + Write-Success "Задача создана и запущена!" + return $true +} + +function Stop-SingboxTask { + Stop-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue + Stop-Process -Name "sing-box" -Force -ErrorAction SilentlyContinue +} + +# ========================================== +# ПРОВЕРКА ПРАВ АДМИНИСТРАТОРА +# ========================================== +if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { + Write-Host "⛔ Запустите скрипт от имени АДМИНИСТРАТОРА!" -ForegroundColor Red + Start-Sleep -Seconds 3 + Exit 1 +} + +Clear-Host +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " 🎯 SING-BOX NATIVE INSTALLER " -ForegroundColor Cyan +Write-Host " для Discord UDP поддержки " -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host "" +Write-Host "Этот скрипт нужен когда Docker запущен" -ForegroundColor Gray +Write-Host "ЛОКАЛЬНО на Windows (Docker Desktop)." -ForegroundColor Gray +Write-Host "Docker Desktop не поддерживает UDP." -ForegroundColor Gray + +# ========================================== +# ПРОВЕРКА СУЩЕСТВУЮЩЕЙ УСТАНОВКИ +# ========================================== +$singboxExists = Test-Path "$InstallDir\sing-box.exe" +$taskExists = Get-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue + +if ($singboxExists -and $taskExists -and -not $Force) { + Write-Host "" + Write-Host "==========================================" -ForegroundColor Green + Write-Host " ✅ SING-BOX УЖЕ УСТАНОВЛЕН! " -ForegroundColor Green + Write-Host "==========================================" -ForegroundColor Green + Write-Host "" + + $taskInfo = Get-ScheduledTask -TaskName "SingBoxProxy" + $taskState = $taskInfo.State + + Write-Host "📊 Статус: " -NoNewline -ForegroundColor Yellow + if ($taskState -eq "Running") { + Write-Host "РАБОТАЕТ" -ForegroundColor Green + } + else { + Write-Host "$taskState" -ForegroundColor Red + } + + Write-Host "" + Write-Host "📁 Расположение: $InstallDir" -ForegroundColor Yellow + Write-Host "🔌 Локальный SOCKS5: 127.0.0.1:$LocalProxyPort" -ForegroundColor Yellow + Write-Host "" + + Write-Host "Что вы хотите сделать?" -ForegroundColor Yellow + Write-Host " [1] Запустить" -ForegroundColor White + Write-Host " [2] Остановить" -ForegroundColor White + Write-Host " [3] Показать конфиг" -ForegroundColor White + Write-Host " [4] Переустановить" -ForegroundColor White + Write-Host " [q] Выход" -ForegroundColor White + Write-Host "" + + $choice = Read-Host "👉 Выбор (1-4/q)" + + switch ($choice) { + "1" { + Start-ScheduledTask -TaskName "SingBoxProxy" + Start-Sleep -Seconds 2 + Write-Success "Запущено!" + exit 0 + } + "2" { + Stop-SingboxTask + Write-Success "Остановлено!" + exit 0 + } + "3" { + Write-Host "`n📄 Конфигурация:" -ForegroundColor Cyan + Get-Content "$InstallDir\config.json" | ConvertFrom-Json | ConvertTo-Json -Depth 10 + exit 0 + } + "4" { + Write-Info "Переустановка..." + } + default { + exit 0 + } + } +} + +# ========================================== +# УСТАНОВКА +# ========================================== + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +# ШАГ 1: Скачиваем sing-box +Write-Step "Скачиваю sing-box v$SingboxVersion..." + +if (!(Test-Path $InstallDir)) { + New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null +} + +$zipFile = "$env:TEMP\sing-box.zip" + +try { + Invoke-WebRequest -Uri $SingboxUrl -OutFile $zipFile -UseBasicParsing + Write-Success "Скачано!" +} +catch { + Write-Error "Ошибка скачивания: $_" + exit 1 +} + +Write-Info "Распаковываю..." +Expand-Archive -Path $zipFile -DestinationPath $env:TEMP -Force + +$extractedDir = Get-ChildItem "$env:TEMP\sing-box-*" -Directory | Select-Object -First 1 +Copy-Item "$($extractedDir.FullName)\sing-box.exe" "$InstallDir\sing-box.exe" -Force + +Remove-Item $zipFile -Force -ErrorAction SilentlyContinue +Remove-Item $extractedDir.FullName -Recurse -Force -ErrorAction SilentlyContinue + +Write-Success "sing-box установлен в $InstallDir" + +# ШАГ 2: Получаем подписку +Write-Step "Настройка подписки..." + +$savedSubFile = Join-Path $PSScriptRoot "data\subscription.json" +$subUrl = $SubscriptionUrl + +if ([string]::IsNullOrWhiteSpace($subUrl) -and (Test-Path $savedSubFile)) { + try { + $savedSub = Get-Content $savedSubFile -Raw | ConvertFrom-Json + if ($savedSub.url) { + Write-Info "Найдена сохранённая подписка" + Write-Host " URL: $($savedSub.url)" -ForegroundColor Gray + $useSaved = Read-Host " Использовать? (y/n)" + if ($useSaved -eq "y") { + $subUrl = $savedSub.url + } + } + } + catch {} +} + +if ([string]::IsNullOrWhiteSpace($subUrl)) { + Write-Host "`n🔗 Введите URL подписки:" -ForegroundColor Yellow + $subUrl = Read-Host "👉" +} + +if ([string]::IsNullOrWhiteSpace($subUrl)) { + Write-Error "URL подписки не указан!" + exit 1 +} + +$subResult = Get-SubscriptionData -Url $subUrl + +if (-not $subResult.success) { + Write-Error "Ошибка загрузки подписки: $($subResult.error)" + exit 1 +} + +Write-Success "Подписка загружена!" + +if ($subResult.userInfo.Count -gt 0) { + $ui = $subResult.userInfo + if ($ui.upload -and $ui.download -and $ui.total) { + $usedGB = [math]::Round(($ui.upload + $ui.download) / 1GB, 2) + $totalGB = [math]::Round($ui.total / 1GB, 2) + Write-Info "Трафик: $usedGB / $totalGB GB" + } +} + +# ШАГ 3: Выбираем сервер +$selectedServer = Select-Server -Config $subResult.config + +if (-not $selectedServer) { + exit 1 +} + +Write-Success "Выбран сервер: $($selectedServer.tag)" + +# ШАГ 4: Генерируем конфиг +Write-Step "Генерирую конфигурацию..." + +$config = New-SingboxConfig -Outbound $selectedServer.outbound -Port $LocalProxyPort +$configJson = $config | ConvertTo-Json -Depth 10 + +Set-Content -Path "$InstallDir\config.json" -Value $configJson -Encoding UTF8 +Write-Success "Конфиг сохранён: $InstallDir\config.json" + +# ШАГ 5: Запускаем +Stop-SingboxTask +Start-Sleep -Seconds 1 + +$installed = Install-SingboxTask + +if (-not $installed) { + Write-Error "Не удалось установить задачу!" + exit 1 +} + +Start-Sleep -Seconds 3 + +# Проверяем порт +Write-Info "Проверяю доступность порта..." +$portCheck = Test-NetConnection -ComputerName 127.0.0.1 -Port $LocalProxyPort -WarningAction SilentlyContinue + +if ($portCheck.TcpTestSucceeded) { + Write-Success "Порт $LocalProxyPort доступен!" +} +else { + Write-Warning "Порт $LocalProxyPort пока недоступен. Подождите несколько секунд." +} + +# Финал +Write-Host "" +Write-Host "==========================================" -ForegroundColor Green +Write-Host " 🎉 SING-BOX УСТАНОВЛЕН! " -ForegroundColor Green +Write-Host "==========================================" -ForegroundColor Green +Write-Host "" +Write-Host "📡 Локальный SOCKS5: 127.0.0.1:$LocalProxyPort" -ForegroundColor Yellow +Write-Host " Сервер: $($selectedServer.tag)" -ForegroundColor White +Write-Host "" +Write-Host "Теперь запустите discord-windows-hack.ps1" -ForegroundColor Cyan +Write-Host "и укажите прокси: 127.0.0.1:$LocalProxyPort" -ForegroundColor Cyan +Write-Host "" +Write-Host "📋 Полезные команды:" -ForegroundColor Gray +Write-Host " Статус: Get-ScheduledTask -TaskName SingBoxProxy" -ForegroundColor Gray +Write-Host " Запустить: Start-ScheduledTask -TaskName SingBoxProxy" -ForegroundColor Gray +Write-Host " Остановить: Stop-ScheduledTask -TaskName SingBoxProxy" -ForegroundColor Gray +Write-Host ""