Skip to content

Instantly share code, notes, and snippets.

@m-hayabusa
Created May 20, 2023 09:50
Show Gist options
  • Save m-hayabusa/09dfd2f738a4ef4aba114c3228c8f20b to your computer and use it in GitHub Desktop.
Save m-hayabusa/09dfd2f738a4ef4aba114c3228c8f20b to your computer and use it in GitHub Desktop.
pingでめっちゃ疎通監視して、ダメそうだったらルートを別のNICに切り替えてSoftEther VPNを再接続するやつ
<#
.SYNOPSIS
pingで疎通監視して、ダメそうだったらルートを別のNICに切り替えてSoftEther VPNを再接続するやつ
.DESCRIPTION
主回線で接続しているとき、主回線で0.5秒ごとにVPNサーバーへpingを送信し、2連続で失敗した場合に、
* VPNサーバーへのルートを副回線へ変更
* VPNのセッションを繋ぎなおす
副回線で接続しているとき、主回線で5秒ごとにVPNサーバーへpingを送信し、2連続で成功した場合に、
* VPNサーバーへのルートを主回線へ変更
* VPNのセッションを繋ぎなおす
.NOTES
日本語環境のWindowsでのみ動作する
Windows 10で動くのかはわからない
PowerShell 5の場合、BOMつきUTF-8でないと動かないようだ
SoftEther VPNのセットアップは各自する必要がある (デフォルト設定でよいはず)
#>
Param(
# SoftEther VPNのアカウント名 (「接続設定」名)
[Parameter(HelpMessage = 'SoftEther VPNのアカウント名(「接続設定」名)')]
[string]
$VPNAccount = "VPN",
# 主回線のインタフェースの名前
# $(Get-NetIPInterface).InterfaceAlias で取得できるもののうち1つ
# デフォルト値: イーサネット
[Parameter(HelpMessage = '主回線のインタフェースの名前 (`$(Get-NetIPInterface).InterfaceAlias)`')]
[string]
$MainInterfaceAlias = "イーサネット",
#副回線のインタフェースの名前
# $(Get-NetIPInterface).InterfaceAlias で取得できるもののうち1つ
# デフォルト値: Wi-Fi
[Parameter(HelpMessage = '副回線のインタフェースの名前 (`$(Get-NetIPInterface).InterfaceAlias)`')]
[string]
$BackupInterfaceAlias = "Wi-Fi",
#SoftEther VPNのvpncmdへのパス
[Parameter(HelpMessage = 'SoftEther VPNのvpncmdへのパス')]
[string]
$vpncmd = "C:\Program Files\SoftEther VPN Client\vpncmd.exe"
)
begin {
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) {
Start-Process powershell.exe "-File `"$PSCommandPath`" `"$VPNAccount`" `"$MainInterfaceAlias`" `"$BackupInterfaceAlias`" `"$vpncmd`"" -Verb RunAs
exit
}
$Host.ui.RawUI.WindowTitle = "VPNの再接続をするやつ (起動中...)"
# $host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.Size(34, 10)
# $Host.ui.RawUI.BufferSize = $host.UI.RawUI.WindowSize
Write-Host "(Ctrl + C で終了)"
[Console]::TreatControlCAsInput = $true
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "🪛..."
$Fallback = $False
$VpnServer = $(&$vpncmd /CLIENT localhost /CMD AG $VPNAccount | Select-String 'VPN Server 縺ョ繝帙せ繝亥錐(?: *)\|(.*)').Matches.Groups[1].Value.Trim()
if (!($VpnServer -match '[0-9A-F\.:]*')) {
$VpnServer = $(Resolve-DnsName $VpnServer -Type A)[0].IPAddress
}
&$vpncmd /CLIENT localhost /CMD AccountDisconnect vpn | Out-Null
$MainInterface = $(Get-NetIPConfiguration -InterfaceAlias $MainInterfaceAlias)
$MainInterfaceAddr = $MainInterface.IPv4Address.IPAddress
$MainGatewayAddr = $MainInterface.IPv4DefaultGateway.NextHop
$BackupInterface = $(Get-NetIPConfiguration -InterfaceAlias $BackupInterfaceAlias)
$BackupGatewayAddr = $BackupInterface.IPv4DefaultGateway.NextHop
New-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $MainInterfaceAlias -NextHop $MainGatewayAddr -RouteMetric 253 | Out-Null
# New-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $BackupInterfaceAlias -NextHop $BackupGatewayAddr -RouteMetric 250
Set-NetIPInterface -InterfaceAlias $MainInterfaceAlias -InterfaceMetric 2
Set-NetIPInterface -InterfaceAlias $BackupInterfaceAlias -InterfaceMetric 3
&$vpncmd /CLIENT localhost /CMD Accimage.pngountConnect vpn | Out-Null
$Host.ui.RawUI.WindowTitle = "VPNの再接続をするやつ (主回線)"
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "👀Ready"
$rel = 0;
}
process {
while ($true) {
if ([Console]::KeyAvailable) {
$key = [Console]::ReadKey($true)
if ($key.key -eq "C" -and $key.modifiers -eq "Control") {
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "🧹..."
$Host.ui.RawUI.WindowTitle = "VPNの再接続をするやつ (終了中...)"
[Console]::TreatControlCAsInput = $false
Remove-NetRoute -DestinationPrefix $VpnServer/32 -Confirm:$false | Out-Null
&$vpncmd /CLIENT localhost /CMD AccountDisconnect vpn | Out-Null
Set-NetIPInterface -InterfaceAlias $MainInterfaceAlias -AutomaticMetric Enabled
Set-NetIPInterface -InterfaceAlias $BackupInterfaceAlias -AutomaticMetric Enabled
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "👀Bye!"
exit
}
}
$ping = $(ping -w 500 -n 1 -S $MainInterfaceAddr $VpnServer)
if (!(($ping -match "100% の損失") -or ($ping -match "宛先ホストに到達できません。"))) {
if ($rel -lt 0) { $rel = 0 }
$rel++
if ($Fallback) {
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") OK -ForegroundColor Green
}
}
else {
if ($rel -gt 0) { $rel = 0 }
$rel--
if (!$Fallback) {
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") NG -ForegroundColor Yellow
}
}
# Write-Host $ping $rel
if ($Fallback -and ($rel -ge 2)) {
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "✅主回線に切替" -ForegroundColor Cyan
Remove-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $BackupInterfaceAlias -NextHop $BackupGatewayAddr -Confirm:$false | Out-Null
$Fallback = $False
Write-Output "AccountDisconnect $VPNAccount`nAccountConnect $VPNAccount" | &$vpncmd /CLIENT localhost | Out-Null
$Host.ui.RawUI.WindowTitle = "VPNの再接続をするやつ (主回線)"
}
if (!$Fallback -and ($rel -le -2)) {
Write-Host $(Get-Date -Format "yyyy/MM/dd HH:mm:ss") "❗副回線に切替" -ForegroundColor Red
New-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $BackupInterfaceAlias -NextHop $BackupGatewayAddr -RouteMetric 250 | Out-Null
Remove-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $MainInterfaceAlias -NextHop $MainGatewayAddr -Confirm:$false | Out-Null
$Fallback = $True
Write-Output "AccountDisconnect $VPNAccount`nAccountConnect $VPNAccount" | &$vpncmd /CLIENT localhost | Out-Null
$Host.ui.RawUI.WindowTitle = "VPNの再接続をするやつ (副回線)"
Start-Sleep 3
New-NetRoute -DestinationPrefix $VpnServer/32 -InterfaceAlias $MainInterfaceAlias -NextHop $MainGatewayAddr -RouteMetric 253 | Out-Null
}
if ($Fallback) {
Start-Sleep -Milliseconds 5000
}
else {
Start-Sleep -Milliseconds 500
}
}
}
end {
[Console]::TreatControlCAsInput = $false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment