Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $script:InstallRoot = $env:VPN_PROXY_WINDOWS_ROOT if ([string]::IsNullOrWhiteSpace($script:InstallRoot)) { $script:InstallRoot = "C:\Tools\vpn-proxy-windows" } $script:ProxiFyreRoot = $env:PROXIFYRE_ROOT if ([string]::IsNullOrWhiteSpace($script:ProxiFyreRoot)) { $script:ProxiFyreRoot = "C:\Tools\ProxiFyre" } function New-VpnProxyResult { param( [string]$Action, [bool]$Success, [object]$Result = $null, [string]$Message = "", [string]$ErrorMessage = "" ) $value = [ordered]@{ success = $Success action = $Action } if ($null -ne $Result) { $value.result = $Result } if ($Message) { $value.message = $Message } if ($ErrorMessage) { $value.error = $ErrorMessage } return $value } function Get-VpnProxyStatus { $task = Get-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue $singboxProcess = Get-Process -Name "sing-box" -ErrorAction SilentlyContinue $proxifyre = Get-Service -Name "ProxiFyreService" -ErrorAction SilentlyContinue return [ordered]@{ singbox = if ($singboxProcess) { "Running" } elseif ($task) { [string]$task.State } else { "NotInstalled" } proxifyre = if ($proxifyre) { [string]$proxifyre.Status } else { "NotInstalled" } installRoot = $script:InstallRoot proxifyreRoot = $script:ProxiFyreRoot } } function Write-ProxiFyreConfig { param( [Parameter(Mandatory=$true)][string]$ConfigPath, [Parameter(Mandatory=$true)][object]$Config ) $dir = Split-Path -Parent $ConfigPath New-Item -ItemType Directory -Force -Path $dir | Out-Null if (Test-Path $ConfigPath) { Copy-Item $ConfigPath "$ConfigPath.bak" -Force } $Config | ConvertTo-Json -Depth 20 | Set-Content -Path $ConfigPath -Encoding UTF8 } function Restart-ProxiFyre { $exe = Join-Path $script:ProxiFyreRoot "ProxiFyre.exe" if (-not (Test-Path $exe)) { throw "ProxiFyre.exe not found at $exe" } & $exe stop 2>$null | Out-Null & $exe install 2>$null | Out-Null & $exe start 2>$null | Out-Null } function Invoke-ProxiFyreApply { param([object]$Payload) Write-ProxiFyreConfig -ConfigPath $Payload.configPath -Config $Payload.config Restart-ProxiFyre return New-VpnProxyResult -Action "proxifyre.apply" -Success $true -Message "ProxiFyre config applied and service restarted" } function Invoke-ServiceControl { param([object]$Payload) $service = [string]$Payload.service $action = [string]$Payload.action if ($service -eq "proxifyre") { if ($action -eq "restart") { Restart-ProxiFyre } elseif ($action -eq "start") { Start-Service -Name "ProxiFyreService" } elseif ($action -eq "stop") { Stop-Service -Name "ProxiFyreService" -Force } else { throw "Unknown ProxiFyre action: $action" } } elseif ($service -eq "sing-box") { if ($action -eq "restart") { Stop-ScheduledTask -TaskName "SingBoxProxy" -ErrorAction SilentlyContinue Start-ScheduledTask -TaskName "SingBoxProxy" } elseif ($action -eq "start") { Start-ScheduledTask -TaskName "SingBoxProxy" } elseif ($action -eq "stop") { Stop-ScheduledTask -TaskName "SingBoxProxy" } else { throw "Unknown sing-box action: $action" } } elseif ($service -eq "ui") { return New-VpnProxyResult -Action "service.control" -Success $true -Message "UI is controlled by manage.ps1 -OpenUi" } else { throw "Unknown service: $service" } return New-VpnProxyResult -Action "service.control" -Success $true -Message "$service $action complete" } function Get-VpnProxyLogs { $paths = @( (Join-Path $script:InstallRoot "runtime\sing-box\singbox.log"), (Join-Path $script:ProxiFyreRoot "ProxiFyre.log") ) $logs = @() foreach ($path in $paths) { if (Test-Path $path) { $logs += [ordered]@{ path = $path lines = @(Get-Content $path -Tail 120 -ErrorAction SilentlyContinue) } } } return $logs } function Invoke-VpnProxyAction { param( [Parameter(Mandatory=$true)][string]$Action, [object]$Payload = @{} ) switch ($Action) { "status.get" { return New-VpnProxyResult -Action $Action -Success $true -Result (Get-VpnProxyStatus) } "proxifyre.apply" { return Invoke-ProxiFyreApply -Payload $Payload } "service.control" { return Invoke-ServiceControl -Payload $Payload } "logs.get" { return New-VpnProxyResult -Action $Action -Success $true -Result (Get-VpnProxyLogs) } default { throw "Unknown action: $Action" } } } Export-ModuleMember -Function Invoke-VpnProxyAction, Get-VpnProxyStatus