重构网关切换逻辑(待测试)
This commit is contained in:
parent
fe3279468d
commit
a18914bd4e
@ -1,188 +1,263 @@
|
|||||||
# $Global:TestDomain = "www.google.com" #测试代理是否可用
|
. (Join-Path $PSScriptRoot 'config.ps1')
|
||||||
# $Global:TestIP = "223.5.5.5" #测试是否连接网络
|
. (Join-Path $PSScriptRoot 'logger.ps1')
|
||||||
# $Global:originalDns = "223.5.5.5" #默认DNS
|
. (Join-Path $PSScriptRoot 'proxy-test.ps1')
|
||||||
# $Global:originalGateway = "192.168.6.1" #默认网关
|
|
||||||
# $Global:CustomGateway = "192.168.6.2" #代理网关
|
|
||||||
# $Global:CustomIP = "192.168.6.4" #默认ip
|
|
||||||
# $Global:TargetNetworkAdapter = {} #网络适配器实例
|
|
||||||
# $Global:TargetNetworkAdapterKeyword = "Ethernet" #网络适配器名字通配符
|
|
||||||
# $Global:isCustomGateway = $false #是否为自定义网关
|
|
||||||
|
|
||||||
. $(-Join($(Get-Location).Path, '\config.ps1'))
|
$Script:ProxySuccessCount = 0
|
||||||
. $(-Join($(Get-Location).Path, '\proxy-test.ps1'))
|
$Script:ProxyFailureCount = 0
|
||||||
. $(-Join($(Get-Location).Path, '\logger.ps1'))
|
$Script:LastSwitchTime = (Get-Date).AddSeconds(-1 * $Global:SwitchCooldownSeconds)
|
||||||
|
|
||||||
|
function Test-IsAdministrator {
|
||||||
function isDhcpEnable(){
|
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||||
return Get-NetIPConfiguration | select-object InterfaceAlias, IPv4Address, @{n="dhcp";e={$_.NetIPv4Interface.DHCP}} | Select-Object -ExpandProperty dhcp
|
$principal = [Security.Principal.WindowsPrincipal]$identity
|
||||||
|
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isForeignConnected {
|
function Request-Administrator {
|
||||||
# check foreign network availability
|
|
||||||
$result = Test-NetConnection -ComputerName $Global:TestDomain -Port 443
|
|
||||||
|
|
||||||
if ($result.TcpTestSucceeded) {
|
|
||||||
Write-Log -Message "Successfully connected to $($Global:TestDomain) via HTTPS. isCustomGateway:$($Global:isCustomGateway)"
|
|
||||||
return $true
|
|
||||||
} else {
|
|
||||||
Write-Log -Message "Failed to connect to $($Global:TestDomain) via HTTPS. isCustomGateway:$($Global:isCustomGateway)"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNetworkConnected {
|
|
||||||
# check network availability
|
|
||||||
$result = $(Test-Connection -ComputerName $Global:TestIP -Count 1).Status -eq 'Success'
|
|
||||||
if ($result) {
|
|
||||||
Write-Log -Message "Successfully connected to $($Global:TestIP) via ICMP. isCustomGateway:$($Global:isCustomGateway)"
|
|
||||||
return $true
|
|
||||||
} else {
|
|
||||||
Write-Log -Message "Failed to connect to $($Global:TestIP) via ICMP. isCustomGateway:$($Global:isCustomGateway)"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDhcp($enable){
|
|
||||||
if($enable){
|
|
||||||
Set-NetIPInterface -InterfaceAlias $Global:TargetNetworkAdapter.name -Dhcp Enabled
|
|
||||||
Write-Log -Message "enable dhcp"
|
|
||||||
} else {
|
|
||||||
Set-NetIPInterface -InterfaceAlias $Global:TargetNetworkAdapter.name -Dhcp Disabled
|
|
||||||
Write-Log -Message "disable dhcp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeGateway{
|
|
||||||
param(
|
|
||||||
$adapter,$isCustomGateway
|
|
||||||
)
|
|
||||||
Write-Log -Message "Changing gateway for adapter: $($adapter.Name) isCustomGateway $($isCustomGateway)"
|
|
||||||
|
|
||||||
|
|
||||||
# check gateway availability
|
|
||||||
if($isCustomGateway){
|
|
||||||
$currentGateway = $(Get-NetIPConfiguration).IPv4DefaultGateway.NextHop
|
|
||||||
if($currentGateway -eq $Global:CustomGateway){
|
|
||||||
Write-Log -Message "current gateway is $currentGateway same as targetGateway $Global:TargetGateway, change gateway canceled"
|
|
||||||
$Global:isCustomGateway = $true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
$result = $(Test-Connection $Global:CustomGateway -Count 1).Status
|
|
||||||
if (! ($result -eq 'Success')){
|
|
||||||
Write-Log -Message "custom gateway $Global:CustomGateway is $result, refuse to change"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# check current ip configuration
|
|
||||||
$existingIP = Get-NetIPAddress -InterfaceAlias $adapter.Name -AddressFamily IPv4
|
|
||||||
|
|
||||||
# if have ip configuration, delete it
|
|
||||||
if ($existingIP) {
|
|
||||||
Write-Log -Message "Removing existing IP address: $($existingIP.IPAddress)"
|
|
||||||
Remove-NetIPAddress -InterfaceAlias $adapter.Name -Confirm:$false
|
|
||||||
}
|
|
||||||
|
|
||||||
# delete current route(gateway)
|
|
||||||
$existingRoute = Get-NetRoute -InterfaceAlias $adapter.Name -DestinationPrefix "0.0.0.0/0"
|
|
||||||
if ($existingRoute) {
|
|
||||||
Write-Log -Message "Removing existing default route..."
|
|
||||||
Remove-NetRoute -InterfaceAlias $adapter.Name -Confirm:$false
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isCustomGateway){ #setting gateway
|
|
||||||
|
|
||||||
# config customGateway
|
|
||||||
$Global:isCustomGateway = $true
|
|
||||||
|
|
||||||
# setting dns server
|
|
||||||
Set-DnsClientServerAddress -InterfaceAlias $adapter.name -ServerAddresses ($Global:CustomGateway, $Global:CustomGateway)
|
|
||||||
# disable dhcp
|
|
||||||
setDhcp($false)
|
|
||||||
# setting gateway to customGateway
|
|
||||||
New-NetIPAddress -InterfaceAlias $adapter.Name -AddressFamily IPv4 -IPAddress $Global:CustomIP -PrefixLength 24 -DefaultGateway $Global:CustomGateway
|
|
||||||
} else {
|
|
||||||
# config originalGateway
|
|
||||||
$Global:isCustomGateway = $false
|
|
||||||
|
|
||||||
# setting dns server
|
|
||||||
Set-DnsClientServerAddress -InterfaceAlias $adapter.name -ServerAddresses ($Global:originalDns, $Global:originalDns)
|
|
||||||
# disable dhcp
|
|
||||||
setDhcp($false)
|
|
||||||
# setting gateway to originalGateway
|
|
||||||
New-NetIPAddress -InterfaceAlias $adapter.Name -AddressFamily IPv4 -IPAddress $Global:CustomIP -PrefixLength 24 -DefaultGateway $Global:originalGateway
|
|
||||||
}
|
|
||||||
Start-Sleep 3
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getIPAddress(){
|
|
||||||
$IP = Get-NetIPConfiguration | Select-Object -ExpandProperty IPV4Address | Select-Object -ExpandProperty IPAddress
|
|
||||||
return $IP
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNetworkAdapter(){
|
|
||||||
$networkAdapters = Get-NetAdapter | ForEach-Object {
|
|
||||||
[PSCustomObject]@{
|
|
||||||
Name = $_.Name
|
|
||||||
Interface = $_.InterfaceDescription
|
|
||||||
Status = $_.Status
|
|
||||||
LinkSpeed = $_.LinkSpeed
|
|
||||||
MacAddress = $_.MacAddress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($networkAdapter in $networkAdapters){
|
|
||||||
if($networkAdapter.name.Contains($TargetNetworkAdapterKeyword)){
|
|
||||||
$Global:TargetNetworkAdapter = $networkAdapter
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Log -Message "getNetworkAdapter: $Global:TargetNetworkAdapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
function init {
|
|
||||||
Write-Log -Message "GateWay-KeepAliveForPowershell is start" -ToEventLog
|
|
||||||
# check permission
|
|
||||||
$IsAdmin = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
|
|
||||||
if (-not $IsAdmin.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
||||||
# if not admin permission, restart it with admin permission
|
|
||||||
Write-Log -Message "Requesting Administrator privileges..."
|
Write-Log -Message "Requesting Administrator privileges..."
|
||||||
Start-Process pwsh -ArgumentList "-NoExit", "-File", $PSCommandPath -Verb RunAs
|
Start-Process pwsh -ArgumentList "-NoExit", "-File", $PSCommandPath -Verb RunAs
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log -Message "Running with Administrator privileges!"
|
function Get-TargetAdapter {
|
||||||
|
$adapter = Get-NetAdapter |
|
||||||
|
Where-Object { $_.Name.Contains($Global:TargetNetworkAdapterKeyword) -and $_.Status -eq "Up" } |
|
||||||
|
Select-Object -First 1
|
||||||
|
|
||||||
# get netAdapter instance
|
if (-not $adapter) {
|
||||||
getNetworkAdapter
|
throw "No active network adapter found by keyword '$($Global:TargetNetworkAdapterKeyword)'."
|
||||||
|
|
||||||
Write-Log -Message "current adapter: $($Global:TargetNetworkAdapter.name)"
|
|
||||||
|
|
||||||
# try to change to customGateway at start
|
|
||||||
changeGateway $Global:TargetNetworkAdapter $true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loop(){
|
$Global:TargetNetworkAdapter = $adapter
|
||||||
|
Write-Log -Message "Target adapter: $($adapter.Name), InterfaceIndex: $($adapter.ifIndex)"
|
||||||
|
return $adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CurrentDefaultGateway {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
$route = Get-NetRoute -InterfaceIndex $InterfaceIndex -DestinationPrefix "0.0.0.0/0" -ErrorAction SilentlyContinue |
|
||||||
|
Sort-Object RouteMetric, ifMetric |
|
||||||
|
Select-Object -First 1
|
||||||
|
|
||||||
|
if ($route) {
|
||||||
|
return $route.NextHop
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CurrentMode {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
$gateway = Get-CurrentDefaultGateway -InterfaceIndex $InterfaceIndex
|
||||||
|
if ($gateway -eq $Global:CustomGateway) {
|
||||||
|
return "PROXY"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "DIRECT"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-CooldownExpired {
|
||||||
|
$elapsed = ((Get-Date) - $Script:LastSwitchTime).TotalSeconds
|
||||||
|
return $elapsed -ge $Global:SwitchCooldownSeconds
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-HostReachable {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$Host
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
return [bool](Test-Connection -ComputerName $Host -Count 1 -Quiet -ErrorAction Stop)
|
||||||
|
} catch {
|
||||||
|
Write-Log -Message "Host check failed for ${Host}: $_"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-ProxyDns {
|
||||||
|
try {
|
||||||
|
$result = Resolve-DnsName -Name $Global:TestDomain -Server $Global:CustomGateway -ErrorAction Stop
|
||||||
|
return [bool]$result
|
||||||
|
} catch {
|
||||||
|
Write-Log -Message "Proxy DNS check failed via $($Global:CustomGateway): $_"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-InternetTcp {
|
||||||
|
try {
|
||||||
|
return [bool](Test-NetConnection -ComputerName $Global:TestDomain -Port 443 -InformationLevel Quiet)
|
||||||
|
} catch {
|
||||||
|
Write-Log -Message "Internet TCP check failed for $($Global:TestDomain):443: $_"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-ProxyHealthy {
|
||||||
|
$gatewayReachable = Test-HostReachable -Host $Global:CustomGateway
|
||||||
|
if (-not $gatewayReachable) {
|
||||||
|
Write-Log -Message "Proxy gateway $($Global:CustomGateway) is not reachable."
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$dnsOk = Test-ProxyDns
|
||||||
|
if (-not $dnsOk) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Global:UseSocksProxyHealthCheck) {
|
||||||
|
return Test-SocksProxy -ProxyHost $Global:CustomGateway -ProxyPort $Global:ProxyPort -TestHost $Global:TestDomain -TestPort 443
|
||||||
|
}
|
||||||
|
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-DefaultGateway {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex,
|
||||||
|
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$Gateway
|
||||||
|
)
|
||||||
|
|
||||||
|
$currentGateway = Get-CurrentDefaultGateway -InterfaceIndex $InterfaceIndex
|
||||||
|
if ($currentGateway -eq $Gateway) {
|
||||||
|
Write-Log -Message "Default gateway is already $Gateway."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$existingRoutes = Get-NetRoute -InterfaceIndex $InterfaceIndex -DestinationPrefix "0.0.0.0/0" -ErrorAction SilentlyContinue
|
||||||
|
foreach ($route in $existingRoutes) {
|
||||||
|
Write-Log -Message "Removing default route $($route.NextHop) from interface $InterfaceIndex."
|
||||||
|
Remove-NetRoute -InterfaceIndex $InterfaceIndex -DestinationPrefix "0.0.0.0/0" -NextHop $route.NextHop -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log -Message "Adding default route $Gateway to interface $InterfaceIndex."
|
||||||
|
New-NetRoute -InterfaceIndex $InterfaceIndex -DestinationPrefix "0.0.0.0/0" -NextHop $Gateway -RouteMetric 1 | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-ProxyDns {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Log -Message "Setting DNS to proxy gateway $($Global:CustomGateway)."
|
||||||
|
Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $Global:CustomGateway
|
||||||
|
Clear-DnsClientCache
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-DirectDns {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Global:DirectDnsServers -and $Global:DirectDnsServers.Count -gt 0) {
|
||||||
|
Write-Log -Message "Setting DNS to $($Global:DirectDnsServers -join ', ')."
|
||||||
|
Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $Global:DirectDnsServers
|
||||||
|
} else {
|
||||||
|
Write-Log -Message "Resetting DNS to DHCP provided servers."
|
||||||
|
Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ResetServerAddresses
|
||||||
|
}
|
||||||
|
|
||||||
|
Clear-DnsClientCache
|
||||||
|
}
|
||||||
|
|
||||||
|
function Switch-ToProxy {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Log -Message "Switching to proxy gateway $($Global:CustomGateway)." -ToEventLog
|
||||||
|
Set-ProxyDns -InterfaceIndex $InterfaceIndex
|
||||||
|
Set-DefaultGateway -InterfaceIndex $InterfaceIndex -Gateway $Global:CustomGateway
|
||||||
|
$Global:isCustomGateway = $true
|
||||||
|
$Script:LastSwitchTime = Get-Date
|
||||||
|
}
|
||||||
|
|
||||||
|
function Switch-ToDirect {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[int]$InterfaceIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Log -Message "Switching to direct gateway $($Global:originalGateway)." -ToEventLog
|
||||||
|
Set-DefaultGateway -InterfaceIndex $InterfaceIndex -Gateway $Global:originalGateway
|
||||||
|
Set-DirectDns -InterfaceIndex $InterfaceIndex
|
||||||
|
$Global:isCustomGateway = $false
|
||||||
|
$Script:LastSwitchTime = Get-Date
|
||||||
|
}
|
||||||
|
|
||||||
|
function Initialize-GatewayKeepAlive {
|
||||||
|
if (-not (Test-IsAdministrator)) {
|
||||||
|
Request-Administrator
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log -Message "GateWay-KeepAliveForPowershell is start" -ToEventLog
|
||||||
|
Write-Log -Message "Running with Administrator privileges."
|
||||||
|
|
||||||
|
$adapter = Get-TargetAdapter
|
||||||
|
$mode = Get-CurrentMode -InterfaceIndex $adapter.ifIndex
|
||||||
|
$Global:isCustomGateway = $mode -eq "PROXY"
|
||||||
|
Write-Log -Message "Initial mode: $mode"
|
||||||
|
|
||||||
|
return $adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-GatewayKeepAliveLoop {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
$Adapter
|
||||||
|
)
|
||||||
|
|
||||||
while ($true) {
|
while ($true) {
|
||||||
# if network offline and using customGateway, try to restore to originalGateway
|
$mode = Get-CurrentMode -InterfaceIndex $Adapter.ifIndex
|
||||||
if((!$(isNetworkConnected)) -and $Global:isCustomGateway){
|
$Global:isCustomGateway = $mode -eq "PROXY"
|
||||||
Write-Log -Message "Network is down, change to original gateway" -ToEventLog
|
$proxyHealthy = Test-ProxyHealthy
|
||||||
changeGateway $Global:TargetNetworkAdapter $false
|
|
||||||
|
if ($mode -eq "PROXY") {
|
||||||
|
$internetOk = Test-InternetTcp
|
||||||
|
if ($proxyHealthy -and $internetOk) {
|
||||||
|
$Script:ProxyFailureCount = 0
|
||||||
|
} else {
|
||||||
|
$Script:ProxyFailureCount++
|
||||||
|
Write-Log -Message "Proxy mode health failed $($Script:ProxyFailureCount)/$($Global:ProxyFailureThreshold)."
|
||||||
}
|
}
|
||||||
|
|
||||||
# if customGateway proxy is working and using original gateway, try to change to customGateway
|
if ($Script:ProxyFailureCount -ge $Global:ProxyFailureThreshold -and (Test-CooldownExpired)) {
|
||||||
if($(Test-SocksProxy -ProxyHost $Global:CustomGateway -ProxyPort 1070) -and (!$Global:isCustomGateway)){
|
Switch-ToDirect -InterfaceIndex $Adapter.ifIndex
|
||||||
Write-Log -Message "isCustomGateway $Global:isCustomGateway"
|
$Script:ProxyFailureCount = 0
|
||||||
Write-Log -Message "proxy host is up, change to custom gateway" -ToEventLog
|
$Script:ProxySuccessCount = 0
|
||||||
changeGateway $Global:TargetNetworkAdapter $true
|
}
|
||||||
|
} else {
|
||||||
|
if ($proxyHealthy) {
|
||||||
|
$Script:ProxySuccessCount++
|
||||||
|
Write-Log -Message "Proxy mode candidate succeeded $($Script:ProxySuccessCount)/$($Global:ProxySuccessThreshold)."
|
||||||
|
} else {
|
||||||
|
$Script:ProxySuccessCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# if customGateway proxy is not working but network still online, do nothing
|
if ($Script:ProxySuccessCount -ge $Global:ProxySuccessThreshold -and (Test-CooldownExpired)) {
|
||||||
|
Switch-ToProxy -InterfaceIndex $Adapter.ifIndex
|
||||||
Start-Sleep 1
|
$Script:ProxySuccessCount = 0
|
||||||
|
$Script:ProxyFailureCount = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init
|
Start-Sleep -Seconds $Global:HealthCheckIntervalSeconds
|
||||||
loop
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$adapter = Initialize-GatewayKeepAlive
|
||||||
|
Start-GatewayKeepAliveLoop -Adapter $adapter
|
||||||
|
|||||||
@ -3,8 +3,15 @@ $Global:TestIP = "223.5.5.5" #测试是否连接网络
|
|||||||
$Global:originalDns = "223.5.5.5" #默认DNS
|
$Global:originalDns = "223.5.5.5" #默认DNS
|
||||||
$Global:originalGateway = "192.168.6.1" #默认网关
|
$Global:originalGateway = "192.168.6.1" #默认网关
|
||||||
$Global:CustomGateway = "192.168.6.2" #代理网关
|
$Global:CustomGateway = "192.168.6.2" #代理网关
|
||||||
$Global:CustomIP = "192.168.6.4" #默认ip
|
|
||||||
$Global:TargetNetworkAdapter = {} #网络适配器实例
|
$Global:TargetNetworkAdapter = {} #网络适配器实例
|
||||||
$Global:TargetNetworkAdapterKeyword = "Ethernet" #网络适配器名字通配符
|
$Global:TargetNetworkAdapterKeyword = "Ethernet" #网络适配器名字通配符
|
||||||
$Global:isCustomGateway = $false #是否为自定义网关
|
$Global:isCustomGateway = $false #是否为自定义网关
|
||||||
$Global:isDebugging = $false #是否为调试模式(日志输出到控制台)
|
$Global:isDebugging = $false #是否为调试模式(日志输出到控制台)
|
||||||
|
|
||||||
|
$Global:ProxyPort = 1070 #代理网关SOCKS5检测端口
|
||||||
|
$Global:UseSocksProxyHealthCheck = $true #是否检测SOCKS5代理端口
|
||||||
|
$Global:DirectDnsServers = @() #直连模式DNS,留空表示恢复DHCP下发的DNS
|
||||||
|
$Global:ProxySuccessThreshold = 3 #连续成功多少次后切换到代理网关
|
||||||
|
$Global:ProxyFailureThreshold = 3 #连续失败多少次后切回默认网关
|
||||||
|
$Global:HealthCheckIntervalSeconds = 5 #检测间隔
|
||||||
|
$Global:SwitchCooldownSeconds = 30 #切换后的冷却时间
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
. $(-Join($(Get-Location).Path, '\config.ps1'))
|
. (Join-Path $PSScriptRoot 'config.ps1')
|
||||||
|
|
||||||
function Write-Log {
|
function Write-Log {
|
||||||
param (
|
param (
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
. $(-Join($(Get-Location).Path, '\logger.ps1'))
|
. (Join-Path $PSScriptRoot 'config.ps1')
|
||||||
. $(-Join($(Get-Location).Path, '\config.ps1'))
|
. (Join-Path $PSScriptRoot 'logger.ps1')
|
||||||
|
|
||||||
function Test-SocksProxy {
|
function Test-SocksProxy {
|
||||||
param (
|
param (
|
||||||
[string]$ProxyHost,
|
[string]$ProxyHost,
|
||||||
[int]$ProxyPort,
|
[int]$ProxyPort,
|
||||||
[string]$TestHost = "google.com",
|
[string]$TestHost = "google.com",
|
||||||
[int]$TestPort = 443
|
[int]$TestPort = 443,
|
||||||
|
[int]$TimeoutMilliseconds = 1500
|
||||||
)
|
)
|
||||||
|
|
||||||
$result = $false
|
$result = $false
|
||||||
@ -22,7 +23,10 @@ function Test-SocksProxy {
|
|||||||
$tcpClient = New-Object System.Net.Sockets.TcpClient
|
$tcpClient = New-Object System.Net.Sockets.TcpClient
|
||||||
$tcpClient.SendTimeout = 1000
|
$tcpClient.SendTimeout = 1000
|
||||||
$tcpClient.ReceiveTimeout = 1000
|
$tcpClient.ReceiveTimeout = 1000
|
||||||
$tcpClient.Connect($ProxyHost, $ProxyPort)
|
$connectTask = $tcpClient.ConnectAsync($ProxyHost, $ProxyPort)
|
||||||
|
if (-not $connectTask.Wait($TimeoutMilliseconds)) {
|
||||||
|
throw "Timed out connecting to ${ProxyHost}:$ProxyPort."
|
||||||
|
}
|
||||||
|
|
||||||
# 代理成功连接,开始验证目标地址是否可达
|
# 代理成功连接,开始验证目标地址是否可达
|
||||||
$stream = $tcpClient.GetStream()
|
$stream = $tcpClient.GetStream()
|
||||||
@ -33,7 +37,10 @@ function Test-SocksProxy {
|
|||||||
|
|
||||||
# 接收服务器响应
|
# 接收服务器响应
|
||||||
$response = New-Object byte[] 2
|
$response = New-Object byte[] 2
|
||||||
$stream.Read($response, 0, $response.Length)
|
$bytesRead = $stream.Read($response, 0, $response.Length)
|
||||||
|
if ($bytesRead -lt $response.Length) {
|
||||||
|
throw "SOCKS handshake response is incomplete."
|
||||||
|
}
|
||||||
|
|
||||||
if ($response[1] -ne 0x00) {
|
if ($response[1] -ne 0x00) {
|
||||||
throw "SOCKS handshake failed. Proxy does not support no-authentication."
|
throw "SOCKS handshake failed. Proxy does not support no-authentication."
|
||||||
@ -55,7 +62,10 @@ function Test-SocksProxy {
|
|||||||
|
|
||||||
# 接收连接响应
|
# 接收连接响应
|
||||||
$connectResponse = New-Object byte[] 10
|
$connectResponse = New-Object byte[] 10
|
||||||
$stream.Read($connectResponse, 0, $connectResponse.Length)
|
$bytesRead = $stream.Read($connectResponse, 0, $connectResponse.Length)
|
||||||
|
if ($bytesRead -lt 2) {
|
||||||
|
throw "SOCKS connect response is incomplete."
|
||||||
|
}
|
||||||
|
|
||||||
if ($connectResponse[1] -eq 0x00) {
|
if ($connectResponse[1] -eq 0x00) {
|
||||||
Write-Log -Message "Proxy is valid and can connect to ${TestHost}:$TestPort."
|
Write-Log -Message "Proxy is valid and can connect to ${TestHost}:$TestPort."
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user