Files
talkscore-asr/scripts/vpn-connect.ps1
T
Vladimir BryzgalovandClaude Opus 5 b2bad9d8e6 Скрипт подключения машины ASR к серверу Talkscore по WireGuard
Машина переехала в сеть с серым адресом, извне до неё не достучаться.
Туннель поднимается с её стороны наружу, машина получает постоянный
10.90.0.2, по которому её видит сервер. Через туннель идёт только трафик
до сервера - интернет машины не затрагивается.

Ключевая пара создаётся на самой машине, наружу уходит только открытый ключ.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 02:18:42 +05:00

176 lines
7.6 KiB
PowerShell

# Подключает машину ASR к серверу Talkscore через WireGuard.
#
# Зачем: у машины серый адрес, извне до неё не достучаться. Туннель она
# поднимает сама, наружу, и получает постоянный адрес 10.90.0.2, по которому
# сервер Talkscore к ней обращается.
#
# Через туннель ходит только трафик до 10.90.0.1 - обычный интернет машины
# не затрагивается.
#
# Запускать от имени администратора:
# powershell -ExecutionPolicy Bypass -File vpn-connect.ps1
#
# Проверить состояние:
# powershell -ExecutionPolicy Bypass -File vpn-connect.ps1 -Status
param(
[switch]$Status,
[switch]$Remove,
[string]$ServerPublicKey = "Qd9nsSZI1yAusMHSD68EWWa+1xZzO2coYY4iutJAa1Y=",
[string]$ServerEndpoint = "77.233.223.232:51820",
[string]$ClientAddress = "10.90.0.2/32",
[string]$ServerAddress = "10.90.0.1"
)
$ErrorActionPreference = "Stop"
$TunnelName = "talkscore"
$WgDir = "$env:ProgramFiles\WireGuard"
$WgExe = Join-Path $WgDir "wg.exe"
$WireGuard = Join-Path $WgDir "wireguard.exe"
function Write-Step($text) { Write-Host "`n $text" -ForegroundColor Cyan }
function Write-Good($text) { Write-Host " $text" -ForegroundColor Green }
function Write-Warn($text) { Write-Host " $text" -ForegroundColor Yellow }
function Write-Bad($text) { Write-Host " $text" -ForegroundColor Red }
function Assert-Admin {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Bad "Нужны права администратора: туннель ставится как служба Windows."
Write-Bad "Запустите PowerShell от имени администратора и повторите."
exit 1
}
}
function Install-WireGuard {
if (Test-Path $WgExe) {
Write-Good "WireGuard уже установлен"
return
}
Write-Step "Ставлю WireGuard..."
# winget есть не на всех сборках, поэтому запасной путь - прямая загрузка.
$installed = $false
if (Get-Command winget -ErrorAction SilentlyContinue) {
winget install --id WireGuard.WireGuard --silent --accept-source-agreements `
--accept-package-agreements 2>&1 | Out-Null
$installed = Test-Path $WgExe
}
if (-not $installed) {
$url = "https://download.wireguard.com/windows-client/wireguard-installer.exe"
$tmp = Join-Path $env:TEMP "wireguard-installer.exe"
Write-Warn "winget не сработал, качаю установщик напрямую"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $tmp -UseBasicParsing
Write-Warn "Может открыться окно установщика - пройдите его, скрипт подождёт."
Start-Process -FilePath $tmp -Wait
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
}
if (-not (Test-Path $WgExe)) {
Write-Bad "Установить не удалось. Поставьте вручную: https://www.wireguard.com/install/"
exit 1
}
Write-Good "WireGuard установлен"
}
function Get-TunnelService {
Get-Service -Name "WireGuardTunnel`$$TunnelName" -ErrorAction SilentlyContinue
}
function Show-Status {
$service = Get-TunnelService
if (-not $service) {
Write-Warn "Туннель не установлен. Запустите скрипт без ключей."
return
}
Write-Host " Служба: $($service.Status)"
if ($service.Status -ne "Running") {
Write-Warn "Туннель установлен, но не запущен: Start-Service '$($service.Name)'"
return
}
& $WgExe show $TunnelName
Write-Step "Проверка связи с сервером"
if (Test-Connection -ComputerName $ServerAddress -Count 2 -Quiet) {
Write-Good "$ServerAddress отвечает - туннель работает"
} else {
Write-Bad "$ServerAddress не отвечает."
Write-Bad "Обычная причина: публичный ключ этой машины ещё не добавлен на сервер."
}
}
function Remove-Tunnel {
if (-not (Get-TunnelService)) { Write-Warn "Туннеля нет"; return }
& $WireGuard /uninstalltunnelservice $TunnelName
Write-Good "Туннель удалён"
}
# --- основной сценарий ---
Assert-Admin
if ($Status) { Show-Status; exit 0 }
if ($Remove) { Remove-Tunnel; exit 0 }
Install-WireGuard
if (Get-TunnelService) {
Write-Warn "Туннель '$TunnelName' уже установлен."
Write-Warn "Чтобы пересоздать с новым ключом: запустите с -Remove, затем снова без ключей."
Show-Status
exit 0
}
Write-Step "Создаю ключи..."
# Ключевая пара делается здесь, на этой машине. Закрытый ключ её не покидает,
# наружу уходит только открытый - его и добавляют на сервер.
$privateKey = (& $WgExe genkey)
$publicKey = ($privateKey | & $WgExe pubkey)
$config = @"
[Interface]
PrivateKey = $privateKey
Address = $ClientAddress
[Peer]
PublicKey = $ServerPublicKey
Endpoint = $ServerEndpoint
# Только адрес сервера: остальной трафик машины через туннель не идёт.
AllowedIPs = $ServerAddress/32
# Серый адрес живёт за NAT, и без периодических пакетов сопоставление
# в таблице провайдера протухает через пару минут.
PersistentKeepalive = 25
"@
$configPath = Join-Path $env:TEMP "$TunnelName.conf"
# ASCII: в конфиге только ключи и адреса, кириллицы нет, а WireGuard
# разбирает файл построже большинства программ.
[IO.File]::WriteAllText($configPath, $config, [Text.Encoding]::ASCII)
Write-Step "Устанавливаю туннель как службу..."
& $WireGuard /installtunnelservice $configPath
Start-Sleep -Seconds 3
# Файл содержит закрытый ключ, а WireGuard уже скопировал конфигурацию себе.
Remove-Item $configPath -Force -ErrorAction SilentlyContinue
$service = Get-TunnelService
if (-not $service) {
Write-Bad "Служба не появилась. Посмотрите журнал в приложении WireGuard."
exit 1
}
Set-Service -Name $service.Name -StartupType Automatic
Write-Good "Туннель установлен и будет подниматься при загрузке"
Write-Host ""
Write-Host ("=" * 70)
Write-Host " ОТКРЫТЫЙ КЛЮЧ ЭТОЙ МАШИНЫ - передайте его для добавления на сервер:"
Write-Host ""
Write-Host " $publicKey" -ForegroundColor Yellow
Write-Host ""
Write-Host " Это не секрет, его можно пересылать открыто."
Write-Host " Пока ключ не добавлен на сервер, туннель работать не будет."
Write-Host ("=" * 70)
Write-Step "Текущее состояние"
Show-Status