VPCピアリング環境のセキュリティグループ設定とトラブルシューティング

目次

概要

VPCピアリングは、2つのVPC間でプライベートIPアドレスを使った通信を可能にする機能です。例えば、アプリケーション用VPCとログ収集用VPCを分離しつつ、プライベートネットワーク経由でログを送信するといった構成で利用されます。

VPCピアリング接続自体は正常に確立されているにもかかわらず、通信ができないというトラブルは実務でも試験でも頻出のシナリオです。原因として多いのが、ルートテーブルの設定漏れセキュリティグループのインバウンドルール不足です。特にセキュリティグループについては、ピアリング接続の両端のVPCでそれぞれ適切なルールを設定する必要があり、片方のVPCのルール設定を見落としがちです。

本記事では、2つのVPCをピアリング接続した環境で、セキュリティグループのインバウンドルール不足により通信が失敗するケースを再現し、ルールを追加して通信が復旧するまでの手順を確認します。VPC Flow Logsも活用して、通信の成功・失敗をログレベルで確認します。

この記事のメリット

  • VPCピアリング環境で必要なルートテーブルとセキュリティグループの設定を理解できる
  • セキュリティグループのインバウンドルール不足による通信失敗を実機で確認できる
  • 通信失敗時のトラブルシューティング手順(セキュリティグループの確認→ルール追加→通信確認)を習得できる
  • VPC Flow Logsを使った通信の成功・失敗の確認方法を把握できる
  • SCS試験でVPCピアリング環境のセキュリティグループに関する問いに正確に答えられるようになる

技術解説

VPCピアリングの通信要件

VPCピアリングを使った通信を成立させるには、ピアリング接続の確立に加えて、以下の設定が必要です。

設定項目説明
ルートテーブル両方のVPCのルートテーブルに、相手VPCのCIDRブロックへのルートをピアリング接続をターゲットとして追加する
セキュリティグループ通信を受信する側のインスタンスのセキュリティグループに、送信元からのインバウンドルールを追加する
ネットワークACL必要に応じて、サブネットのネットワークACLで通信を許可する(デフォルトACLはすべて許可)

ルートテーブルの設定

VPCピアリング接続を確立しただけでは、VPC間でトラフィックはルーティングされません。各VPCのルートテーブルに、相手VPCのCIDRブロックを宛先としてピアリング接続をターゲットに指定するルートを追加する必要があります。

flowchart LR
    subgraph VPCA["VPC A  (10.0.0.0/16)"]
        RTA["ルートテーブル<br/>━━━━━━━━━━<br/>10.0.0.0/16 → local<br/><b>10.1.0.0/16 → pcx-xxxxxxxx</b>"]
    end

    PCX{{"VPC ピアリング接続<br/>pcx-xxxxxxxx"}}

    subgraph VPCB["VPC B  (10.1.0.0/16)"]
        RTB["ルートテーブル<br/>━━━━━━━━━━<br/>10.1.0.0/16 → local<br/><b>10.0.0.0/16 → pcx-xxxxxxxx</b>"]
    end

    RTA -->|"宛先 10.1.0.0/16<br/>(VPC B 宛)"| PCX
    PCX -->|"宛先 10.0.0.0/16<br/>(VPC A 宛)"| RTA
    RTB -->|"宛先 10.0.0.0/16<br/>(VPC A 宛)"| PCX
    PCX -->|"宛先 10.1.0.0/16<br/>(VPC B 宛)"| RTB

    classDef vpc fill:#eef6ff,stroke:#4a90d9
    classDef pcx fill:#fff3e0,stroke:#e8a33d,font-weight:bold
    class VPCA,VPCB vpc
    class PCX pcx

ルートテーブルの設定は 双方向 に必要です。片方のVPCだけにルートを追加しても、応答パケットが戻れないため通信は成立しません。

セキュリティグループの双方向設定

VPCピアリング環境では、通信の方向に応じて各インスタンスのセキュリティグループを適切に設定する必要があります。

以下のシナリオを考えます。

flowchart LR
    WEB(["web-server<br/>VPC A (10.0.0.0/16)"])
    PCX{{"VPC ピアリング接続<br/>pcx-xxxxxxxx"}}
    LOG(["log-server<br/>VPC B (10.1.0.0/16)"])

    WEB -->|"ログ送信"| PCX --> LOG
    LOG -.->|"応答(自動)"| WEB

この場合に必要なセキュリティグループの設定は以下の通りです。

インスタンス方向ルール
web-serverアウトバウンドlog-serverのIPアドレス(またはVPC BのCIDR)への通信を許可
log-serverインバウンドweb-serverのIPアドレス(またはVPC AのCIDR)からの通信を許可

セキュリティグループはステートフルであるため、インバウンドルールで許可した通信の応答トラフィックは自動的に許可されます。しかし、通信を受信する側にインバウンドルールがなければ、そもそも通信が拒否されるため、応答も発生しません。

ピアリング先のセキュリティグループ参照

同一VPC内ではセキュリティグループIDを参照してルールを定義できますが、VPCピアリング環境でもピアリング先VPCのセキュリティグループIDを参照することが可能です。ただし、ピアリング先のセキュリティグループを参照するには、VPCピアリング接続のオプションで「リモートセキュリティグループの参照を有効にする」設定が必要です。

CIDRブロックで指定する方法と比較すると、セキュリティグループ参照にはIPアドレスの変更に影響されないというメリットがあります。

VPC Flow Logsによる通信確認

VPC Flow Logsは、VPC内のネットワークインターフェイスを通過するIPトラフィックの情報をキャプチャします。Flow Logsの action フィールドで通信の許可(ACCEPT)または拒否(REJECT)を確認できるため、セキュリティグループやネットワークACLのルール設定が正しいかどうかのトラブルシューティングに活用できます。

実践

ここでは、2つのVPCをVPCピアリングで接続した環境で、セキュリティグループのインバウンドルール不足による通信失敗を確認した後、ルールを追加して通信を復旧させます。

前提条件

  • リージョン: ap-northeast-1(東京)
  • 以下のリソースが作成済みであること
リソース種別リソース名用途
VPCvpc-a (10.0.0.0/16)web-server用VPC
VPCvpc-b (10.1.0.0/16)log-server用VPC
パブリックサブネットvpc-a-public-subnetweb-server配置用
パブリックサブネットvpc-b-public-subnetlog-server配置用
VPCピアリング接続vpc-a-to-vpc-b2つのVPC間の接続
EC2インスタンスweb-serverVPC A内のWebサーバー
EC2インスタンスlog-serverVPC B内のログサーバー
セキュリティグループweb-server-sgSSHのみインバウンド許可(VPC Bからのインバウンドルールなし=トラブル対象)
セキュリティグループlog-server-sgweb-serverからのインバウンド許可

VPCピアリング接続の確認

AWSマネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。

上部の検索バーに VPC と入力し、表示された「VPC」を選択します。

左側ナビゲーションの「ピアリング接続」を選択します。

vpc-a-to-vpc-b という名前のピアリング接続が表示され、ステータスが「アクティブ」であることを確認します。

VPCピアリング接続一覧(ステータスが「アクティブ」の状態)

ルートテーブルの確認

左側ナビゲーションの「ルートテーブル」を選択します。

vpc-a-public-rt を選択し、「ルート」タブを確認します。以下のルートが設定されていることを確認します。

  • 10.0.0.0/16 → ターゲット: local
  • 10.1.0.0/16 → ターゲット: pcx-xxxxxxxx(ピアリング接続)
  • 0.0.0.0/0 → ターゲット: igw-xxxxxxxx(インターネットゲートウェイ)
vpc-a-public-rt のルート一覧(ピアリング接続へのルートが設定された状態)

同様に vpc-b-public-rt を選択し、VPC AのCIDRブロック 10.0.0.0/16 へのルートがピアリング接続をターゲットとして設定されていることを確認します。

通信失敗の確認

セキュリティグループはステートフルなため、web-serverが通信を開始する場合(web-server→log-server)は、応答パケットがweb-server-sgのインバウンドルールになくても自動的に許可されます。問題が顕在化するのは、log-server側が通信を開始するケース(log-server→web-server)です。ここではその方向で通信を試します。

log-serverにSSHで接続し、web-serverのプライベートIPアドレスに対して通信を試みます。

ssh -i ~/.ssh/luxy_common.pem ec2-user@<log-server-public-ip>

log-server上で、web-serverのプライベートIPアドレスに対してpingを実行します。

ping -c 3 <web-server-private-ip>

web-server-sgにVPC B(log-server)からのインバウンドルールが存在しないため、pingの応答が返りません(タイムアウトします)。

PING 10.0.1.xx (10.0.1.xx) 56(84) bytes of data.

--- 10.0.1.xx ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2003ms

同様に、curlコマンドでweb-serverのポート80への接続を試みます。

curl -m 5 http://<web-server-private-ip>:80

こちらもタイムアウトします。

curl: (28) Connection timed out after 5001 milliseconds

セキュリティグループの確認

通信が失敗する原因を確認するため、web-server-sgのインバウンドルールを確認します。

上部の検索バーに EC2 と入力し、表示された「EC2」を選択します。

左側ナビゲーションの「ネットワーク&セキュリティ」→「セキュリティグループ」を選択します。

web-server-sg を選択し、「インバウンドルール」タブを確認します。

SSHのみが許可されており、VPC BのCIDR(10.1.0.0/16、log-server側)からのインバウンドルールが存在しないことが確認できます。

web-server-sg のインバウンドルール(SSH のみ許可されている状態)

次に、log-server-sg を選択し、「インバウンドルール」タブを確認します。

log-server-sgには、VPC AのCIDRブロック(10.0.0.0/16)からのICMPとTCPの通信が許可されていることを確認します。

log-server-sg のインバウンドルール(VPC A からの通信が許可されている状態)

ここで問題が明確になります。log-server-sgはweb-serverからの通信を受け入れる設定になっていますが、web-server-sgにはlog-serverが開始する通信を受け入れるルールがありません

Note: セキュリティグループはステートフルなため、web-serverが通信を開始する場合(web-server→log-server)、web-server-sgのアウトバウンドで許可されていれば応答パケットは自動的に許可されます。一方、log-serverが通信を開始する場合(log-server→web-server)は、web-server-sg側のインバウンドルールで明示的に許可されていない限り、その通信はブロックされます。双方向の通信(log-serverからweb-serverへのデータ送信など)が必要な構成では、この点が問題になります。

セキュリティグループへのインバウンドルール追加

web-server-sgにlog-serverからの通信を許可するインバウンドルールを追加します。

web-server-sg を選択した状態で、「インバウンドルール」タブの「インバウンドルールを編集」をクリックします。

「ルールを追加」をクリックし、以下を入力します。

  • タイプ: すべての ICMP - IPv4
  • ソース: 10.1.0.0/16(VPC BのCIDR)
  • 説明: ICMP from VPC B (log-server)

もう一度「ルールを追加」をクリックし、以下を入力します。

  • タイプ: カスタム TCP
  • ポート範囲: 0 - 65535
  • ソース: 10.1.0.0/16(VPC BのCIDR)
  • 説明: TCP from VPC B (log-server)

セキュリティグループのルールの説明には、日本語などのマルチバイト文字は使用できません(使用できるのは半角英数字と一部の記号のみ)。説明は半角英字で入力します。

web-server-sg のインバウンドルール編集画面(VPC B からの ICMP と TCP を追加した状態)

「ルールを保存」をクリックします。

インバウンドルール一覧に、追加したルールが表示されることを確認します。

web-server-sg のインバウンドルール(VPC B からの通信ルールが追加された状態)

通信復旧の確認

再度log-serverにSSHで接続し、web-serverへの通信を確認します。

ping -c 3 <web-server-private-ip>

今度はpingの応答が返ることを確認します。

PING 10.0.1.xx (10.0.1.xx) 56(84) bytes of data.
64 bytes from 10.0.1.xx: icmp_seq=1 ttl=255 time=0.5 ms
64 bytes from 10.0.1.xx: icmp_seq=2 ttl=255 time=0.4 ms
64 bytes from 10.0.1.xx: icmp_seq=3 ttl=255 time=0.4 ms

--- 10.0.1.xx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.400/0.433/0.500/0.047 ms

通信が復旧したことが確認できます。

VPC Flow Logsでの通信確認

VPC Flow Logsで通信の成功・失敗をログレベルで確認します。

上部の検索バーに CloudWatch と入力し、表示された「CloudWatch」を選択します。

左側ナビゲーションの「ログ」→「ロググループ」を選択します。

/aws/vpc-peering-lab/flowlogs を選択します。

ログストリーム一覧から、web-serverのENIに対応するログストリームを選択します(ENI IDは eni- で始まります)。

セキュリティグループ修正前のログでは、log-serverのIPアドレスからの通信が REJECT になっていることが確認できます。

2 123456789012 eni-xxxx 10.1.1.xx 10.0.1.xx 0 0 1 1 84 1711111111 1711111115 REJECT OK

セキュリティグループ修正後のログでは、同じ通信が ACCEPT に変わっていることが確認できます。

2 123456789012 eni-xxxx 10.1.1.xx 10.0.1.xx 0 0 1 1 84 1711111116 1711111120 ACCEPT OK
VPC Flow Logs のログイベント(REJECT から ACCEPT への変化が確認できる状態)

まとめ

  • VPCピアリング接続が「アクティブ」であっても、ルートテーブルセキュリティグループの設定が双方のVPCで正しくなければ通信は成立しない
  • VPCピアリング環境で通信できない場合、まず確認すべきは以下の3点である
  • ピアリング接続のステータスが「アクティブ」であること
  • 両方のVPCのルートテーブルに相手VPCのCIDRへのルートが設定されていること
  • 通信を受信する側のセキュリティグループに適切なインバウンドルールが設定されていること
  • セキュリティグループはステートフルだが、通信を受信する側にインバウンドルールがなければ通信は拒否される
  • VPC Flow Logsの action フィールド(ACCEPT / REJECT)で、セキュリティグループやネットワークACLによる通信の許可・拒否を確認できる
  • ピアリング先のセキュリティグループIDを参照することも可能だが、オプションで有効化が必要である

参照先

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社Luxy(https://luxy-inc.com)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した会社を引き継ぎ、代表に就任。

目次