commit c70f53bed32af4060d3bd193aef619703b688c93 Author: chuzhongzai Date: Thu Dec 19 00:14:14 2024 +0800 first commit diff --git a/GateWay-KeepAlive.ps1 b/GateWay-KeepAlive.ps1 new file mode 100644 index 0000000..d29df9b --- /dev/null +++ b/GateWay-KeepAlive.ps1 @@ -0,0 +1,172 @@ +. $(-Join($(pwd).Path, '\config.ps1')) +. $(-Join($(pwd).Path, '\proxy-test.ps1')) + +function isDhcpEnable(){ + return Get-NetIPConfiguration | select-object InterfaceAlias, IPv4Address, @{n="dhcp";e={$_.NetIPv4Interface.DHCP}} | Select-Object -ExpandProperty dhcp +} + +function isForeignConnected { + # check foreign network availability + $result = Test-NetConnection -ComputerName $Global:TestDomain -Port 443 + + if ($result.TcpTestSucceeded) { + Write-Host "Successfully connected to $($Global:TestDomain) via HTTPS. isCustomGateway:$($Global:isCustomGateway)" + return $true + } else { + Write-Host "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-Host "Successfully connected to $($Global:TestIP) via ICMP. isCustomGateway:$($Global:isCustomGateway)" + return $true + } else { + Write-Host "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-Host enable dhcp + } else { + Set-NetIPInterface -InterfaceAlias $Global:TargetNetworkAdapter.name -Dhcp Disabled + Write-Host disable dhcp + } +} + +function changeGateway{ + param( + $adapter,$isCustomGateway + ) + Write-Host "Changing gateway for adapter: $($adapter.Name) isCustomGateway $($isCustomGateway)" + + + # check gateway availability + if($isCustomGateway){ + $currentGateway = $(Get-NetIPConfiguration).IPv4DefaultGateway.NextHop + if($currentGateway -eq $Global:TargetGateway){ + Write-Host "current gateway is $currentGateway same as targetGateway $Global:TargetGateway, change gateway canceled" + $Global:isCustomGateway = $true + return + } + $result = $(Test-Connection $Global:TargetGateway -Count 1).Status + if (! ($result -eq 'Success')){ + Write-Host custom gateway $Global:TargetGateway 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-Host "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-Host "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:TargetGateway, $Global:TargetGateway) + # disable dhcp + setDhcp($false) + # setting gateway to customGateway + New-NetIPAddress -InterfaceAlias $adapter.Name -AddressFamily IPv4 -IPAddress $Global:TargetIP -PrefixLength 24 -DefaultGateway $Global:TargetGateway + } else { + # config originalGateway + $Global:isCustomGateway = $false + + # setting dns server + Set-DnsClientServerAddress -InterfaceAlias $adapter.name -ServerAddresses ($Global:originalDns, $Global:originalDns) + + # setting gateway to originalGateway + New-NetIPAddress -InterfaceAlias $adapter.Name -AddressFamily IPv4 -IPAddress $Global:TargetIP -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-Host "getNetworkAdapter: " $Global:TargetNetworkAdapter +} + +function init { + # 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-Host "Requesting Administrator privileges..." + Start-Process pwsh -ArgumentList "-NoExit", "-File", $PSCommandPath -Verb RunAs + exit + } + + Write-Host "Running with Administrator privileges!" + + # get netAdapter instance + getNetworkAdapter + + Write-Host "current adapter: $($Global:TargetNetworkAdapter.name)" + + # try to change to customGateway at start + changeGateway $Global:TargetNetworkAdapter $true +} + +function loop(){ + while($true){ + # if network offline and using customGateway, try to restore to originalGateway + if((!$(isNetworkConnected)) -and $Global:isCustomGateway){ + changeGateway $Global:TargetNetworkAdapter $false + } + + # if customGateway proxy is working and using original gateway, try to change to customGateway + if($(Test-SocksProxy -ProxyHost $Global:TargetGateway -ProxyPort 1070) -and (!$Global:isCustomGateway)){ + Write-Host isCustomGateway $Global:isCustomGateway + changeGateway $Global:TargetNetworkAdapter $true + } + + # if customGateway proxy is not working but network still online, do nothing + + Start-Sleep 1 + } +} + +init +loop diff --git a/config.ps1 b/config.ps1 new file mode 100644 index 0000000..e6eb86a --- /dev/null +++ b/config.ps1 @@ -0,0 +1,9 @@ +$Global:TestDomain = "www.google.com" #测试代理是否可用 +$Global:TestIP = "223.5.5.5" #测试是否连接网络 +$Global:originalDns = "223.5.5.5" #默认DNS +$Global:TargetGateway = "192.168.6.2" #代理网关 +$Global:TargetIP = "192.168.6.4" #默认ip +$Global:originalGateway = "192.168.6.1" #默认网关 +$Global:TargetNetworkAdapter = {} #网络适配器实例 +$Global:TargetNetworkAdapterKeyword = "Ethernet" #网络适配器名字通配符 +$Global:isCustomGateway = $false #是否为自定义网关 \ No newline at end of file diff --git a/proxy-test.ps1 b/proxy-test.ps1 new file mode 100644 index 0000000..b55e8d9 --- /dev/null +++ b/proxy-test.ps1 @@ -0,0 +1,76 @@ +function Test-SocksProxy { + param ( + [string]$ProxyHost, + [int]$ProxyPort, + [string]$TestHost = "google.com", + [int]$TestPort = 443 + ) + + $result = $false + try { + # check if proxy is working + $result = $(Test-Connection $ProxyHost -Count 1).Status + if(!($result -eq "Success")){ + Write-Host proxy host $ProxyHost is $result + return $false + } + + # create TCP client + $tcpClient = New-Object System.Net.Sockets.TcpClient + $tcpClient.SendTimeout = 1000 + $tcpClient.ReceiveTimeout = 1000 + $tcpClient.Connect($ProxyHost, $ProxyPort) + + # 代理成功连接,开始验证目标地址是否可达 + $stream = $tcpClient.GetStream() + + # 构建 SOCKS5 握手包 (Initial request) + $handshake = [byte[]](0x05, 0x01, 0x00) # Version 5, 1 method, No auth + $stream.Write($handshake, 0, $handshake.Length) + + # 接收服务器响应 + $response = New-Object byte[] 2 + $stream.Read($response, 0, $response.Length) + + if ($response[1] -ne 0x00) { + throw "SOCKS handshake failed. Proxy does not support no-authentication." + } + + # 将 TestHost 转换为字节数组 + $hostBytes = [System.Text.Encoding]::ASCII.GetBytes($TestHost) + + # 构建 SOCKS5 连接请求 + $connectRequest = @( + 0x05, 0x01, 0x00, 0x03, # Version 5, Connect, Reserved, Domain + [byte]$hostBytes.Length # Domain length + ) + $hostBytes + @( + [byte]($TestPort -shr 8), # Port (high byte) + [byte]($TestPort -band 0xFF) # Port (low byte) + ) + + $stream.Write($connectRequest, 0, $connectRequest.Length) + + # 接收连接响应 + $connectResponse = New-Object byte[] 10 + $stream.Read($connectResponse, 0, $connectResponse.Length) + + if ($connectResponse[1] -eq 0x00) { + Write-Host "Proxy is valid and can connect to ${TestHost}:$TestPort." + $result = $true + } else { + throw "SOCKS connection to ${TestHost}:$TestPort failed. Response code: $($connectResponse[1])" + $result = $false + } + } catch { + Write-Host "Proxy test failed: $_" + $result = $false + } finally { + # 关闭连接 + if ($stream) { $stream.Dispose() } + if ($tcpClient) { $tcpClient.Close() } + } + return $result +} + + +# Test-SocksProxy -ProxyHost "192.168.6.2" -ProxyPort 1081