PowerShellでWebProxy経由のインターネット疎通を定期確認する方法|CSVログ保存付き

IT
この記事は約11分で読めます。

こんにちは、キャンペジニアです。

ネットワークやWebProxyの障害試験をしていると、「Proxy経由のインターネット通信が、いつ切れて、いつ復旧したのかを残したい」という場面があります。

単純なpingではICMPの疎通は確認できますが、WebProxyを経由したHTTP/HTTPS通信が正常かどうかまでは分かりません。

そこで今回は、実際の障害試験で使った方法をベースに、PowerShellからcurl.exeを実行し、指定したWebProxy経由で外部HTTPSサイトへ継続アクセスして、結果をCSVへ保存する方法を紹介します。

約500ms間隔で確認するため、Proxy停止・経路遮断・冗長切替などの試験で、通信断がどのタイミングで発生したかを追いやすい構成です。

┈ Twitterでも発信しているのでぜひフォローお願いします!

今回やりたいこと

  • 指定したWebProxyを必ず経由する
  • 外部HTTPSサイトへ実通信を発生させる
  • 約500ms間隔で繰り返す
  • 1回の通信は500msでタイムアウトする
  • HTTPステータス、応答時間、curlの終了コードをCSVへ残す
  • 通信断と復旧をコンソール上でも分かるようにする

通常監視というより、障害試験・切替試験で「瞬断時間を後から確認する」用途を意識しています。

なぜpingではなくHTTPS通信を使うのか

WebProxyの確認で注意したいのが、pingが通ることと、Proxy経由のWeb通信が通ることは別という点です。

例えば、端末からProxyサーバまでは到達できても、Proxyサービスが停止している、Proxyから上位ネットワークへ出られない、外向きのHTTPSだけ失敗している、といった状態では利用者はWebアクセスできません。

そのため今回は、クライアントPCからProxyを明示的に指定し、HTTPSリクエストを実際に送信します。

テスト先には例としてGoogle Public DNSのDoHエンドポイントを使っています。社内ルールなどで外部接続先が制限されている場合は、組織で許可されているHTTPS URLへ置き換えてください。

事前確認:curl.exeが使えるか

今回のスクリプトはWindowsのcurl.exeを利用します。まずPowerShellで次を実行し、バージョン情報が表示されることを確認します。

curl.exe --version

完成版PowerShellスクリプト

以下が今回使うスクリプトです。Proxyアドレスは記事用のサンプル値なので、実環境に合わせて変更してください。

$ErrorActionPreference = "Stop"

# ==============================================
# WebProxy Internet Connectivity Test
# ==============================================

# Settings
$Proxy = "http://192.0.2.10:8080"
$Target = "https://dns.google/resolve?name=example.com&type=A"
$IntervalMs = 500
$TimeoutSec = 0.5

# Log file
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$LogFile = Join-Path $ScriptDir ("proxy_test_{0}.csv" -f (Get-Date -Format "yyyyMMdd_HHmmss"))

# CSV header
"Timestamp,Result,HttpCode,ResponseTime_ms,CurlExitCode" |
 Set-Content -Path $LogFile -Encoding UTF8

$PreviousResult = $null
$OutageStart = $null

Write-Host "WebProxy connectivity test started."
Write-Host ("Proxy : {0}" -f $Proxy)
Write-Host ("Target : {0}" -f $Target)
Write-Host ("Log : {0}" -f $LogFile)
Write-Host "Press Ctrl+C to stop."
Write-Host ""

while ($true) {
 $LoopSw = [System.Diagnostics.Stopwatch]::StartNew()
 $RequestSw = [System.Diagnostics.Stopwatch]::StartNew()

 $HttpCode = "000"
 $CurlExitCode = -1
 $Result = "NG"

 try {
 $CurlOutput = & curl.exe `
 -sS `
 -o NUL `
 -w "%{http_code}" `
 --proxy $Proxy `
 --connect-timeout $TimeoutSec `
 --max-time $TimeoutSec `
 $Target 2>$null

 $CurlExitCode = $LASTEXITCODE
 $RequestSw.Stop()

 if ($null -ne $CurlOutput) {
 $HttpCode = ($CurlOutput | Out-String).Trim()
 }

 if (($CurlExitCode -eq 0) -and ($HttpCode -match "^2[0-9][0-9]$")) {
 $Result = "OK"
 }
 }
 catch {
 $RequestSw.Stop()
 $Result = "NG"
 }

 $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
 $ResponseTimeMs = [math]::Round($RequestSw.Elapsed.TotalMilliseconds, 0)

 $CsvLine = "{0},{1},{2},{3},{4}" -f `
 $Timestamp, $Result, $HttpCode, $ResponseTimeMs, $CurlExitCode

 Add-Content -Path $LogFile -Value $CsvLine -Encoding UTF8

 if (($Result -eq "NG") -and ($PreviousResult -ne "NG")) {
 $OutageStart = Get-Date
 Write-Host ("[{0}] NG HTTP={1} curl={2}" -f `
 $Timestamp, $HttpCode, $CurlExitCode)
 }
 elseif (($Result -eq "OK") -and ($PreviousResult -eq "NG")) {
 $RecoveredAt = Get-Date
 $OutageMs = [math]::Round(($RecoveredAt - $OutageStart).TotalMilliseconds, 0)
 Write-Host ("[{0}] RECOVERED outage={1}ms" -f `
 $Timestamp, $OutageMs)
 }

 $PreviousResult = $Result

 # Keep the loop close to 500 ms start-to-start.
 $SleepMs = $IntervalMs - $LoopSw.ElapsedMilliseconds
 if ($SleepMs -gt 0) {
 Start-Sleep -Milliseconds $SleepMs
 }
}

設定する箇所

Proxy

$Proxy = "http://192.0.2.10:8080"

ここを実際のProxyサーバのIPアドレスまたはFQDN、ポート番号へ変更します。記事では内部ネットワーク情報を公開しないため、ドキュメント用アドレスへ置き換えています。

Target

$Target = "https://dns.google/resolve?name=example.com&type=A"

Proxy経由でアクセスする確認先です。運用環境では、組織で許可されている安定したHTTPS URLを使うのがおすすめです。

IntervalMsとTimeoutSec

$IntervalMs = 500
$TimeoutSec = 0.5

今回は障害試験用として、約500ms間隔・500msタイムアウトにしています。かなり短い設定なので、一時的な遅延でもNGとして拾う可能性があります。通常監視に流用する場合は、目的に合わせてタイムアウト値を長くしてください。

スクリプトの実行方法

ファイル名をproxy_test.ps1として保存し、PowerShellから次のように実行します。

powershell.exe -NoProfile -ExecutionPolicy Bypass -File ./proxy_test.ps1

停止するときはCtrl + Cです。スクリプトと同じフォルダへ、次のような名前でCSVが作成されます。

proxy_test_20260910_113000.csv

CSVログの見方

Timestamp,Result,HttpCode,ResponseTime_ms,CurlExitCode
2026-09-10 11:30:00.123,OK,200,82,0
2026-09-10 11:30:00.623,OK,200,79,0
2026-09-10 11:30:01.124,NG,000,503,28
2026-09-10 11:30:01.625,NG,000,502,28
2026-09-10 11:30:02.126,OK,200,91,0

ResultOKならHTTPSリクエスト成功、NGなら失敗です。

HttpCodeはHTTPステータス、ResponseTime_msは応答時間、CurlExitCodecurl.exeの終了コードです。

例えばProxy停止試験なら、NGへ変わった時刻とOKへ戻った時刻を見ることで、利用者目線の通信断時間を追えます。

500ms間隔をどう実現しているか

単純に通信処理の後で毎回Start-Sleep -Milliseconds 500すると、実際の周期は「通信時間+500ms」になります。

今回はループ開始時にStopwatchを開始し、処理にかかった時間を500msから引いてSleepしています。

$SleepMs = $IntervalMs - $LoopSw.ElapsedMilliseconds
if ($SleepMs -gt 0) {
 Start-Sleep -Milliseconds $SleepMs
}

これにより、可能な範囲で1回目の開始から次の開始までを約500msに合わせています。

ただし、WindowsのスケジューリングやCPU負荷、通信処理の時間によって完全に500ms固定になるわけではありません。厳密なリアルタイム測定ではなく、障害試験時の時系列確認用途として使っています。

実際にハマったポイント:ps1の先頭に「powershell」が入っていた

今回、自分でも少しハマったのがこれです。スクリプトをコピーして確認したところ、ファイルの先頭が次のようになっていました。

powershell
# ==============================================
# WebProxy Internet Connectivity Test
# ==============================================

Markdownのコードブロックに付いていた言語名のpowershellまで、スクリプト本文としてコピーしてしまった状態です。

.ps1の1行目にこの文字列が入っていると、PowerShellはコマンドとして実行しようとするためエラーになります。

Web上のコードをコピペするときは、コードブロックの言語名や余計な記号まで含まれていないかを最初に確認すると切り分けが早いです。

文字化けやParseErrorが出る場合

別の環境へスクリプトをコピーした際、文字コードや特殊記号が混ざって構文エラーになることがあります。特に全角記号、スマートクォート、見た目が似ているダッシュなどは気付きにくいポイントです。

原因不明のParseErrorが出る場合は、一部分だけ直し続けるより、新しい.ps1ファイルを作って貼り付け直す方が早い場合があります。

このテストで分かること・分からないこと

このスクリプトで確認できるのは、クライアントPCから指定Proxyを経由して、外部HTTPS通信が成立したかです。

一方、NGになっただけでは障害箇所までは断定できません。クライアント〜Proxy間、Proxyサービス、Proxy〜上位ネットワーク間、DNS、外部サイト側など複数の原因が考えられます。

障害が出た場合は、Proxyサーバのログ、ルータ・Firewallのログ、パケットキャプチャなどと時刻を突き合わせて確認します。

障害試験で使うときの例

  • WebProxyプロセス停止時の影響確認
  • Proxyサーバ再起動試験
  • 冗長Proxyの切替試験
  • 上位回線・Firewallの経路切替試験
  • ネットワーク遮断から復旧までの時間確認

試験開始前からスクリプトを動かしておけば、操作した時刻とCSVのNG時刻を比較できます。

「切替は成功した」だけでなく、実際のWeb通信が何秒止まったのかを証跡として残せるのがメリットです。

運用監視へそのまま使う場合の注意

このスクリプトは短時間の障害試験向けです。500msごとに外部通信とファイル書き込みを行うため、24時間365日の監視へそのまま流用する用途には向きません。

長期監視へ使う場合は、確認間隔を数秒〜数十秒へ伸ばす、ログローテーションを入れる、監視ツール側でHTTPチェックを実装する、といった設計をおすすめします。

まとめ

WebProxyの疎通確認では、Proxyサーバへのpingだけでなく、実際にProxy経由のHTTPS通信を発生させて確認することが重要です。

今回のPowerShellスクリプトなら、約500ms間隔で通信結果をCSVへ残せるため、障害試験や冗長切替試験の時系列確認に使えます。

HTTPステータスだけではなく、応答時間とcurl.exeの終了コードも同時に残しておくと、後からログを確認したときの切り分け材料が増えます。

今後は、このCSVをExcelで可視化して瞬断時間を見やすくする方法や、Squid側のアクセスログと突き合わせる方法もまとめていきたいと思います。

コメント

タイトルとURLをコピーしました