Amazon VPC Reachability Analyzer を用いた疎通テストの簡易化

こんにちは。SCSKのふくちーぬです。

皆さんは、AWS内の疎通テストをどのように実施していますでしょうか。pingコマンドやTest-NetConnectionコマンドを利用しているでしょうか。

今回は、VPC Reachability Analyzerを用いた疎通テストの手法をご紹介します。

VPC Reachability Analyzer

AWS内のリソース間の接続性を擬似的にテストし、どの経路地点で問題があるか分析する機能です。

Reachability Analyzerを利用することで、ルートテーブルやセキュリティグループのどこに設定不備があるか表示され、どこのネットワークに問題があるか容易に切り分けすることができます。到達不能箇所を特定することで、通信の到達性に関する問題の解決を手助けしてくれます。

気になる料金は、一律で1回の分析あたり0.10 USDとなります。

アーキテクチャ

  • EC2・VPCエンドポイントは、プライベートサブネットに配置する
  • EC2からVPCエンドポイントに向けて、Reachability Analyzerを用いてTCP:443の疎通を実施する

検証①

  • EC2インスタンスから、各VPCエンドポイントの疎通テストを実施し到達不能箇所を特定する

CloudFormationテンプレート(ネットワークスタック)

下記のリソースを作成するCloudFormationテンプレートです。

  • VPC
  • プライベートサブネット
  • ルートテーブル
  • セキュリティグループ
  • VPCエンドポイント
  • EC2
  • IAMロール

以下のテンプレートをデプロイしてください。

AWSTemplateFormatVersion: 2010-09-09
Description: cfn private EC2
Parameters:
  ResourceName:
    Type: String   
Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------#
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-VPC"          
# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------#          
  PrivateSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateSubnet-1a"
  PrivateSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateSubnet-1c"
# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------#
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateRouteTable"
  PrivateSubnet1aAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1a
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnet1cAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1c
      RouteTableId: !Ref PrivateRouteTable 
  # ------------------------------------------------------------#
  #  EC2
  # ------------------------------------------------------------#   
  EC2:
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-0b193da66bc27147b
      InstanceType: t2.micro
      NetworkInterfaces: 
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref PrivateSubnet1a
          GroupSet:
            - !Ref EC2SecurityGroup       
      Tags:
          - Key: Name
            Value: !Sub "${ResourceName}-ec2"         
  EC2SecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 10.0.0.0/16
      GroupName: !Sub "${ResourceName}-ec2-sg"
      GroupDescription: !Sub "${ResourceName}-ec2-sg"
      Tags:
        - Key: "Name"
          Value: !Sub "${ResourceName}-ec2-sg"  
  # ------------------------------------------------------------#
  #  IAM Role
  # ------------------------------------------------------------#                   
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      RoleName: !Sub "${ResourceName}-ec2-Role"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      MaxSessionDuration: 3600
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref EC2Role             
  # ------------------------------------------------------------#
  #  VPCEndpoint
  # ------------------------------------------------------------#   
  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c      
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  EC2MessageEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2messages"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  ssmmessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssmmessages"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  EndpointSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${ResourceName}-endpoint-sg"
      GroupDescription: !Sub "${ResourceName}-endpoint-sg"
      Tags:
        - Key: "Name"
          Value: !Sub "${ResourceName}-ec2-sg"          

CloudFormationテンプレート(分析スタック)

下記のリソースを作成するCloudFormationテンプレートです。

  • パスと分析

以下のテンプレートをデプロイしてください。

AWSTemplateFormatVersion: 2010-09-09
Description: Rechability Analyzer Test
Parameters:
  ResourceName:
    Type: String 
  InstanceId:
    Type: String     
  VPCeIdForSSM:
    Type: String
  VPCeIdForSSMMesssages:
    Type: String
  VPCeIdForEC2Messsages:
    Type: String
Resources:    
# ------------------------------------------------------------#
# Rechability Analyzer Test01
# ------------------------------------------------------------#
  EC2NetworkInsightsPathForSSM01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSM
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ssm
  EC2NetworkInsightsPathForSSMMessages01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSMMesssages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ssmmessages
  EC2NetworkInsightsPathForEC2Messages01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForEC2Messsages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ec2messages
  EC2NetworkInsightsAnalysisForSSM01:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSM01
  EC2NetworkInsightsAnalysisForSSMMessages:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSMMessages01
  EC2NetworkInsightsAnalysisForEC2Message:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForEC2Messages01 

分析結果の確認

以下のように、VPCエンドポイントにアタッチしているセキュリティグループに適切なインバウンドルールがないことが判明しました。

検証②

  • 各VPCエンドポイントのセキュリティグループのインバウンドルール(インバウンドルールに、HTTPS:443を許可する)を修正する
  • 再度疎通テストを実施し到達可能を確認する

CloudFormationテンプレート(ネットワークスタック)

VPCエンドポイントにアタッチ済みのセキュリティグループを修正を行います。

以下のテンプレートをデプロイして、スタックの更新をします。

AWSTemplateFormatVersion: 2010-09-09
Description: cfn private EC2
Parameters:
  ResourceName:
    Type: String   
Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------#
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-VPC"          
# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------#          
  PrivateSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateSubnet-1a"
  PrivateSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateSubnet-1c"
# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------#
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ResourceName}-PrivateRouteTable"
  PrivateSubnet1aAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1a
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnet1cAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1c
      RouteTableId: !Ref PrivateRouteTable 
  # ------------------------------------------------------------#
  #  EC2
  # ------------------------------------------------------------#   
  EC2:
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-0b193da66bc27147b
      InstanceType: t2.micro
      NetworkInterfaces: 
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref PrivateSubnet1a
          GroupSet:
            - !Ref EC2SecurityGroup       
      Tags:
          - Key: Name
            Value: !Sub "${ResourceName}-ec2"         
  EC2SecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 10.0.0.0/16
      GroupName: !Sub "${ResourceName}-ec2-sg"
      GroupDescription: !Sub "${ResourceName}-ec2-sg"
      Tags:
        - Key: "Name"
          Value: !Sub "${ResourceName}-ec2-sg"  
  # ------------------------------------------------------------#
  #  IAM Role
  # ------------------------------------------------------------#                   
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      RoleName: !Sub "${ResourceName}-ec2-Role"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      MaxSessionDuration: 3600
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref EC2Role             
  # ------------------------------------------------------------#
  #  VPCEndpoint
  # ------------------------------------------------------------#   
  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c      
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  EC2MessageEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2messages"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  ssmmessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssmmessages"
      SubnetIds:
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup
      PrivateDnsEnabled: true
  EndpointSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 10.0.0.0/16
      GroupName: !Sub "${ResourceName}-endpoint-sg"
      GroupDescription: !Sub "${ResourceName}-endpoint-sg"
      Tags:
        - Key: "Name"
          Value: !Sub "${ResourceName}-ec2-sg"         
 

CloudFormationテンプレート(分析スタック)

再度パスの分析を実行します。

以下のテンプレートをデプロイして、スタックの更新をします。

 AWSTemplateFormatVersion: 2010-09-09
Description: Rechability Analyzer Test
Parameters:
  ResourceName:
    Type: String 
  InstanceId:
    Type: String     
  VPCeIdForSSM:
    Type: String
  VPCeIdForSSMMesssages:
    Type: String
  VPCeIdForEC2Messsages:
    Type: String
Resources:    
# ------------------------------------------------------------#
# Rechability Analyzer Test01
# ------------------------------------------------------------#
  EC2NetworkInsightsPathForSSM01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSM
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ssm
  EC2NetworkInsightsPathForSSMMessages01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSMMesssages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ssmmessages
  EC2NetworkInsightsPathForEC2Messages01:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForEC2Messsages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test01-ec2messages
  EC2NetworkInsightsAnalysisForSSM01:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSM01
  EC2NetworkInsightsAnalysisForSSMMessages01:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSMMessages01
  EC2NetworkInsightsAnalysisForEC2Message01:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForEC2Messages01   
# ------------------------------------------------------------#
# Rechability Analyzer Test02
# ------------------------------------------------------------#      
  EC2NetworkInsightsPathForSSM02:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSM
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test02-ssm
  EC2NetworkInsightsPathForSSMMessages02:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForSSMMesssages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test02-ssmmessages
  EC2NetworkInsightsPathForEC2Messages02:
    Type: "AWS::EC2::NetworkInsightsPath"
    Properties:
      Destination: !Ref VPCeIdForEC2Messsages
      FilterAtSource:
        DestinationPortRange:
          ToPort: 443
          FromPort: 443
      Protocol: "tcp"
      Source: !Ref InstanceId
      Tags:
      - Key: Name
        Value: !Sub ${ResourceName}-test02-ec2messages
  EC2NetworkInsightsAnalysisForSSM02:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSM02
  EC2NetworkInsightsAnalysisForSSMMessages02:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForSSMMessages02
  EC2NetworkInsightsAnalysisForEC2Message02:       
    Type: AWS::EC2::NetworkInsightsAnalysis
    Properties:
      NetworkInsightsPathId: !Ref EC2NetworkInsightsPathForEC2Messages02

分析結果の確認

VPCエンドポイントへの擬似的な疎通テストが成功していることを確認しました。

この後の作業としては、実際に各エンドポイントのAPIを叩くことにより適切なレスポンスが返却されるかテストしていただく流れになるかと思います。その際に、例えばアクセスエラーが出ればIAMロールの権限不足である可能性が濃厚となります。

最後に

いかがだったでしょうか。

VPC Reachability Analyzerを用いて、容易に疎通テストを実行することができました。

検証作業等でネットワーク疎通不可事象が発生することが多いかと思います。その際には、AWSサポートへ問い合わせする前にご自身で疎通テストを実施し到達不能箇所を特定した上で調査していただければ幸いです。

本記事が皆様のお役にたてば幸いです。

ではサウナラ~🔥

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