Integrate Xray 26.9.9 with the sing-box system tunnel and verify Windows routes during health checks. Improve endpoint selection, network recovery, subscription refresh deadlines, diagnostics, packaging, and regression coverage.
73 lines
5.2 KiB
PowerShell
73 lines
5.2 KiB
PowerShell
[CmdletBinding()]
|
|
param()
|
|
$ErrorActionPreference = 'Stop'
|
|
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
|
|
$dll = Join-Path $repo 'tests/QVPN.Tests/bin/Release/net10.0-windows/QVPN.Tests.dll'
|
|
$report = Join-Path $repo 'research/xray-upgrade-verification.json'
|
|
$phase = 'preflight'; $happWasRunning = $false
|
|
function Save-Phase([string]$name) {
|
|
$script:phase = $name
|
|
[pscustomobject]@{Completed=$false;Phase=$name;At=[DateTimeOffset]::Now.ToString('o')} | ConvertTo-Json | Set-Content -LiteralPath $report -Encoding utf8
|
|
}
|
|
function Send([string]$command,[string]$value='') {
|
|
$arguments=@($dll,'--client',$command); if($value){$arguments+=@('--value',$value)}
|
|
$response=& dotnet @arguments | ConvertFrom-Json
|
|
if($LASTEXITCODE -ne 0 -or !$response.Ok){throw "Service command failed: $command"}
|
|
return $response.Status
|
|
}
|
|
try {
|
|
$identity=[Security.Principal.WindowsIdentity]::GetCurrent()
|
|
if(!([Security.Principal.WindowsPrincipal]::new($identity)).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){throw 'Administrator required'}
|
|
$version=([xml](Get-Content (Join-Path $repo 'Directory.Build.props') -Raw)).Project.PropertyGroup.Version
|
|
$setup=Join-Path $repo "dist/QVPN-Setup-$version.exe"
|
|
$expected=(Get-Content (Join-Path $repo "dist/QVPN-Setup-$version.sha256") -Raw).Split(' ')[0]
|
|
if((Get-FileHash -LiteralPath $setup).Hash -ne $expected){throw 'Installer checksum mismatch'}
|
|
$before=Send 'status'; if(!$before.Nodes.Count){throw 'Cached subscription missing'}
|
|
$zurich=$before.Nodes | Where-Object {$_.Name -like '*Цюрих*'} | Select-Object -First 1
|
|
if(!$zurich){throw 'Zurich is missing from subscription'}
|
|
Save-Phase 'refresh current provider parameters'
|
|
$data=Join-Path $env:ProgramData 'QVPN'
|
|
Copy-Item -LiteralPath (Join-Path $data 'settings.dpapi') -Destination (Join-Path $data ("settings.dpapi.before-$version-"+[DateTime]::UtcNow.ToString('yyyyMMddHHmmss')))
|
|
$refreshed=Send 'refresh'
|
|
$zurich=$refreshed.Nodes | Where-Object {$_.Name -eq $zurich.Name} | Select-Object -First 1
|
|
if(!$zurich){throw 'Zurich is missing after refreshing provider parameters'}
|
|
Save-Phase 'release competing HAPP tunnel'
|
|
$happ=Get-Service HappService -ErrorAction SilentlyContinue
|
|
$happWasRunning=$happ -and $happ.Status -eq 'Running'
|
|
Get-Process Happ -ErrorAction SilentlyContinue | Where-Object {$_.Path -eq 'C:\Program Files\FlyFrogLLC\Happ\Happ.exe'} | Stop-Process -Force
|
|
if($happWasRunning){Stop-Service HappService; (Get-Service HappService).WaitForStatus('Stopped',[TimeSpan]::FromSeconds(30))}
|
|
Start-Sleep -Seconds 2
|
|
if(Get-NetAdapter -ErrorAction SilentlyContinue | Where-Object {$_.Name -like '*happ*' -and $_.Status -eq 'Up'}){throw 'HAPP adapter is still active'}
|
|
$null=Send 'select' $zurich.Id
|
|
Save-Phase 'install Xray update preserving encrypted settings'
|
|
$timer=[Diagnostics.Stopwatch]::StartNew()
|
|
for($attempt=0;$attempt -lt 2;$attempt++) {
|
|
$installer=Start-Process -FilePath $setup -ArgumentList '--silent' -WindowStyle Hidden -PassThru -Wait
|
|
if($installer.ExitCode -eq 0){break}
|
|
if($attempt -eq 1){throw 'Installer failed twice'}
|
|
Start-Sleep -Seconds 5
|
|
}
|
|
Save-Phase 'connect installed Xray to Zurich'
|
|
$null=Send 'connect'; $timer.Restart()
|
|
do {
|
|
Start-Sleep -Milliseconds 250
|
|
$status=Send 'status'
|
|
if($status.State -eq 'connected' -and $status.VpnCore -eq 'Xray' -and $status.XrayPid){break}
|
|
}while($timer.Elapsed.TotalSeconds -lt 60)
|
|
if($status.State -ne 'connected' -or $status.VpnCore -ne 'Xray'){throw 'Installed Xray connection did not complete'}
|
|
if($status.ActiveName -ne $zurich.Name){throw 'Selected Zurich was not retained'}
|
|
$connectSeconds=[Math]::Round($timer.Elapsed.TotalSeconds,2)
|
|
Save-Phase 'verify installed Xray recovery and continuous TUN traffic'
|
|
$verification=Start-Process -FilePath (Join-Path $PSHOME 'pwsh.exe') -WindowStyle Hidden -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',(Join-Path $PSScriptRoot 'verify-stability-installed.ps1'),'-ObserveSeconds','300') -PassThru -Wait
|
|
if($verification.ExitCode -ne 0){throw 'Installed recovery/stability verification failed'}
|
|
# Return the competing client to the state observed before this diagnostic run.
|
|
# The updated QVPN service and selected location remain installed for normal use.
|
|
if($happWasRunning -and !$before.DesiredConnected){$null=Send 'disconnect'; Start-Service HappService}
|
|
[pscustomobject]@{Completed=$true;At=[DateTimeOffset]::Now.ToString('o');Version=$version;ConnectionSeconds=$connectSeconds;VpnCore='Xray';Location='Zurich';KeyRetained=$true;HappStopped=$happWasRunning;HappRestored=($happWasRunning -and !$before.DesiredConnected);RecoveryReport='installed-stability-verification.json'} | ConvertTo-Json | Set-Content -LiteralPath $report -Encoding utf8
|
|
} catch {
|
|
try{$null=Send 'disconnect'}catch{}
|
|
if($happWasRunning){Start-Service HappService -ErrorAction SilentlyContinue}
|
|
[pscustomobject]@{Completed=$false;At=[DateTimeOffset]::Now.ToString('o');Phase=$phase;Failure=$_.Exception.Message;HappRestored=$happWasRunning} | ConvertTo-Json | Set-Content -LiteralPath $report -Encoding utf8
|
|
exit 1
|
|
}
|