Files
vpn-proxy/setup-singbox-native.ps1

440 lines
15 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# ==========================================
# 🎯 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 ""