feat: add windows helper scripts
This commit is contained in:
154
scripts/windows/VpnProxy.Windows.psm1
Normal file
154
scripts/windows/VpnProxy.Windows.psm1
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
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
|
||||||
26
scripts/windows/helper.ps1
Normal file
26
scripts/windows/helper.ps1
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
Import-Module (Join-Path $ScriptDir "VpnProxy.Windows.psm1") -Force
|
||||||
|
|
||||||
|
try {
|
||||||
|
$raw = [Console]::In.ReadToEnd()
|
||||||
|
if ([string]::IsNullOrWhiteSpace($raw)) {
|
||||||
|
throw "Missing JSON input"
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $raw | ConvertFrom-Json
|
||||||
|
$payload = if ($request.PSObject.Properties.Name -contains "payload") { $request.payload } else { @{} }
|
||||||
|
$result = Invoke-VpnProxyAction -Action ([string]$request.action) -Payload $payload
|
||||||
|
$result | ConvertTo-Json -Depth 30 -Compress
|
||||||
|
exit 0
|
||||||
|
} catch {
|
||||||
|
$errorResult = [ordered]@{
|
||||||
|
success = $false
|
||||||
|
action = "error"
|
||||||
|
error = $_.Exception.Message
|
||||||
|
}
|
||||||
|
$errorResult | ConvertTo-Json -Depth 10 -Compress
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
64
scripts/windows/manage.ps1
Normal file
64
scripts/windows/manage.ps1
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
param(
|
||||||
|
[switch]$OpenUi,
|
||||||
|
[switch]$Status,
|
||||||
|
[switch]$RestartServices
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$AppDir = Split-Path -Parent (Split-Path -Parent $ScriptDir)
|
||||||
|
if (-not (Test-Path (Join-Path $AppDir "package.json"))) {
|
||||||
|
throw "Cannot locate app root from $ScriptDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
$Root = $env:VPN_PROXY_WINDOWS_ROOT
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Root)) {
|
||||||
|
if ((Split-Path -Leaf $AppDir) -eq "app") {
|
||||||
|
$Root = Split-Path -Parent $AppDir
|
||||||
|
} else {
|
||||||
|
$Root = $AppDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$env:VPN_PROXY_WINDOWS_ROOT = $Root
|
||||||
|
$env:APP_MODE = "windows"
|
||||||
|
$env:DATA_DIR = Join-Path $Root "data"
|
||||||
|
$env:DIST_DIR = Join-Path $AppDir "dist"
|
||||||
|
$env:PROXY_PORT = "1080"
|
||||||
|
$env:PROXY_BIND_IP = "127.0.0.1"
|
||||||
|
$env:SING_BOX_CONFIG = Join-Path $Root "runtime\sing-box\config.json"
|
||||||
|
$env:SING_BOX_CACHE = Join-Path $Root "runtime\sing-box\cache.db"
|
||||||
|
$env:WINDOWS_HELPER = Join-Path $AppDir "scripts\windows\helper.ps1"
|
||||||
|
|
||||||
|
function Get-NodeCommand {
|
||||||
|
$portable = Join-Path $Root "runtime\node\node.exe"
|
||||||
|
if (Test-Path $portable) { return $portable }
|
||||||
|
return "node"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Status) {
|
||||||
|
$inputJson = @{ action = "status.get"; payload = @{} } | ConvertTo-Json -Compress
|
||||||
|
$inputJson | & $env:WINDOWS_HELPER
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($RestartServices) {
|
||||||
|
$helper = $env:WINDOWS_HELPER
|
||||||
|
(@{ action = "service.control"; payload = @{ service = "proxifyre"; action = "restart" } } | ConvertTo-Json -Compress) | & $helper
|
||||||
|
(@{ action = "service.control"; payload = @{ service = "sing-box"; action = "restart" } } | ConvertTo-Json -Compress) | & $helper
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($OpenUi) {
|
||||||
|
$node = Get-NodeCommand
|
||||||
|
Start-Process "http://127.0.0.1:3456"
|
||||||
|
& $node (Join-Path $AppDir "src\server\index.js")
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "VPN Proxy Windows"
|
||||||
|
Write-Host " -OpenUi Start local UI"
|
||||||
|
Write-Host " -Status Print JSON status"
|
||||||
|
Write-Host " -RestartServices Restart ProxiFyre and sing-box"
|
||||||
Reference in New Issue
Block a user