こんにちは、佐野(マナティ)です!
AMIからEC2を作成したら、Security Groupは問題ないのにTCP通信が通らない…
なぜだろうと調べてみると、原因はAWSではなくOS側にありました。
本記事ではこの事象の原因と対処法を解説したいと思います!
-----------------------------------------------------------------------
【目次】
- はじめに
- 何が起きたのか
- 原因:AMIコピーはOS内の設定もそのままコピーする
- 確認手順:Windows Firewallルールの調べ方
- 修正手順:RemoteAddressの更新
- 修正後の確認
- AMIコピー後に確認すべきOS内設定
- まとめ
- 参考
-----------------------------------------------------------------------
■ はじめに
AMIからAmazon EC2インスタンスを複製して新しい環境を構築する、というのはよくある作業だと思います。
Security Groupも設定した、Network ACLも問題ない、ルートテーブルも確認した。
なのに Test-NetConnection でTCP疎通を確認すると TcpTestSucceeded: False が返ってきてしまう…
今回、まさにこの状況に遭遇しました。
原因はAWS側の設定ではなく、OS上のWindows Firewallルールでした。
本記事では、AMIコピー時にWindows Firewallがどう引き継がれるのか、確認・修正の手順、そして再発防止策をまとめます。
■ 何が起きたのか
環境構築の作業で、既存のWindows Server EC2からAMIを取得し、そのAMIから新しいEC2インスタンスを3台作成しました。
AWS側の設定は一通り完了し、結合試験としてEC2間のTCP通信確認に入ったところ、特定のポートへの通信がすべてFalseになりました。
Test-NetConnection -ComputerName 10.x.x.x -Port 8011
# TcpTestSucceeded : False
Security Groupのインバウンドルールは正しく設定されています。
Network ACLも全開放になっている。ルートテーブルも問題ありません。
「…AWS側は全部合っているのに、なんでだ??」という状態でした。
■ 原因:AMIコピーはOS内の設定もそのままコピーする
AMIはEBSスナップショットとメタデータで構成されています。
AMIからEC2を作成すると、OSのディスク状態がそのまま引き継がれます。
つまり、Windows Firewallのルールもコピー元の設定がそのまま残ってしまうということです。
ここで問題になるのが RemoteAddress(接続元IP制限)です。コピー元のEC2では、特定のIPアドレスからの通信のみを許可するWindows Firewallルールが設定されていました。AMIコピーで作成した新しいEC2にも、このルールがそのまま引き継がれていました。
新しい環境のEC2は異なるIPアドレスを持っているため、旧環境のIPを参照しているWindows FirewallルールのRemoteAddressに一致せず、OS側でブロックされていたというわけです。
ざっくり整理するとこういう状態です。
- コピー元EC2のWindows Firewallルール:RemoteAddress = 10.x.x.100(旧環境のIP)
- 新しいEC2から通信:送信元IP = 10.x.x.200(新環境のIP)
- Windows Firewall:「10.x.x.200 は許可リストにないのでブロック」
Security GroupやNACLはAWSのネットワーク層で動作しますが、Windows FirewallはOS層で動作します。AWS側の設定がすべて正しくても、OS上のファイアウォールでブロックされればパケットは到達しません。

図1:パケットはSecurity GroupとNetwork ACLを通過するが、OS上のWindows Firewallで RemoteAddress の不一致によりブロックされる
■ 確認手順:Windows Firewallルールの調べ方
● ①有効なインバウンドルールの一覧を取得
まず、どんなルールが有効になっているかを確認します。
Get-NetFirewallRule -Enabled True -Direction Inbound | Select-Object Name, DisplayName
● ②特定のルールのRemoteAddressを確認
問題がありそうなルールが見つかったら、そのルールのRemoteAddress(接続元IP制限)を確認します。
Get-NetFirewallRule -DisplayName "ルールの表示名" | Get-NetFirewallAddressFilter
ここで返ってくる RemoteAddress が旧環境のIPアドレスになっていれば、それが原因です。
■ 修正手順:RemoteAddressの更新
● 注意:DisplayNameよりもName(GUID)で指定する
Set-NetFirewallRule は -DisplayName パラメータを公式にサポートしていますが、DisplayNameはロケール依存のため、日本語環境と英語環境で表示名が異なるケースがあります。表示名が一致しないと、以下のようにオブジェクトが見つからずエラーになります。
# DisplayNameがロケールや特殊文字でずれているとエラーになる
Set-NetFirewallRule -DisplayName "ルールの表示名" -RemoteAddress "10.x.x.200"
# Set-NetFirewallRule : No MSFT_NetFirewallRule objects found...
確実なのは、ロケールに依存しない内部名(Name = GUID)で指定する方法です。
# Step 1: Nameを特定する
Get-NetFirewallRule -DisplayName "ルールの表示名" | Select-Object Name, DisplayName
# 出力例:
# Name DisplayName
# ---- -----------
# {12345678-abcd-1234-efgh-123456789012} ルールの表示名
# Step 2: Nameを使ってRemoteAddressを更新
Set-NetFirewallRule -Name "{12345678-abcd-1234-efgh-123456789012}" -RemoteAddress "10.x.x.200"
なお、Set-NetFirewallRule および New-NetFirewallRule の実行には 管理者権限のPowerShell が必要です。RDP接続の場合は「管理者として実行」でPowerShellを起動してください。AWS Systems Manager Fleet Manager経由であれば、Administratorで接続されるので問題ありません。
● 新規ルールの作成が必要な場合
既存のルールにRemoteAddressを追加するのではなく、新しいルールを作成する方がシンプルなケースもあります。
New-NetFirewallRule `
-DisplayName "ルール名" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 8002 `
-RemoteAddress "10.x.x.200" `
-Action Allow
■ 修正後の確認
修正が完了したら、Test-NetConnection で疎通を確認します。
Test-NetConnection -ComputerName 10.x.x.x -Port 8011
# TcpTestSucceeded : True
TcpTestSucceeded: True が返ればOKです。
● 補足:アプリケーションが稼働していない場合の確認方法
通信先のEC2でアプリケーションがまだ動いていない場合、対象ポートでリッスンしているプロセスがないため、Test-NetConnection は False を返します。これだとWindows Firewallの問題なのかアプリが動いていないからなのか区別がつきません。
こういうときは、PowerShellで一時的にTCPリスナーを起動して確認できます。
# 通信先のEC2で一時リスナーを起動(例:ポート8011)
$listener = [System.Net.Sockets.TcpListener]::new(
[System.Net.IPAddress]::Any, 8011
)
$listener.Start()
Write-Host "Listening on port 8011..."
この状態で、送信元のEC2から Test-NetConnection を実行します。
確認が終わったら、リスナーを停止します。
$listener.Stop()
この方法なら、アプリケーションのデプロイ前でもネットワーク経路とWindows Firewallの設定が正しいかどうかを確認できます。
■ AMIコピー後に確認すべきOS内設定
今回の教訓は、AWSリソースの設定確認とOS内の設定確認は別物だということです。
AMIコピーでEC2を作成した後は、AWS側の設定(Security Group、IAMロールなど)だけでなく、OS内の設定も確認する必要があります。
以下は、AMIコピー後に確認しておきたいOS内設定のチェックリストです。
|
# |
確認項目 |
確認コマンド(PowerShell) |
|
1 |
Windows FirewallルールのRemoteAddress |
Get-NetFirewallRule | Get-NetFirewallAddressFilter |
|
2 |
hostsファイル(旧環境のIP参照がないか) |
Get-Content C:\Windows\System32\drivers\etc\hosts |
|
3 |
ネットワークアダプタの固定IP設定 |
Get-NetIPConfiguration |
|
4 |
DNSサーバーの設定 |
Get-DnsClientServerAddress |
|
5 |
Windowsサービスの接続先設定 |
アプリケーション固有の設定ファイルを確認 |
|
6 |
タスクスケジューラの設定 |
Get-ScheduledTask |
特にWindows Firewallは「AWSのSecurity GroupがOKなのになぜか通信できない」という形で表面化するため、原因の切り分けに時間がかかりがちです。
AMIコピー直後にRemoteAddressを確認しておけば、結合試験で慌てずに済みます。
■ まとめ
AMIコピーでAmazon EC2を作成すると、OSのディスク状態がそのまま引き継がれます。
Windows Firewallのルールも例外ではなく、RemoteAddress(接続元IP制限)が旧環境のIPのまま残ります。
個人的にはAWS側の設定確認に意識が集中しがちで、OS内の設定まで頭が回らなかったのが反省点です。「Security Groupは通っているのにTCPが繋がらない」という状況に遭遇したら、OS上のファイアウォールを疑うのも一つだと感じました。
AMIコピーを使う構築案件では、AWS側のチェックリストに加えてOS内設定のチェックリストも用意しておくことをおすすめします。
■ 参考
- Amazon Machine Images (AMI) - Amazon EC2 ユーザーガイド
- Get-NetFirewallRule - Microsoft Learn
- Set-NetFirewallRule - Microsoft Learn
- Get-NetFirewallAddressFilter - Microsoft Learn
- New-NetFirewallRule - Microsoft Learn
- Test-NetConnection - Microsoft Learn