はじめに
この記事は、前回のVPC構築に関する内容の続編です。
今回は、プライベートサブネットに本番サーバーを構築し、踏み台サーバーを経由してSSHで本番サーバーにログインできるようにすることをゴールとします。
このステップにより、本番サーバーへの外部からの直接アクセスを避けつつ、安全に管理できる環境を構築します。
前回のおさらい
前回の記事では、「ホンダ-vpc」という名前のVPCを作成し、各リージョン(ap-northeast-1a、ap-northeast-1c)に複数のパブリックサブネットとプライベートサブネットを配置し、セキュリティと可用性を強化しました。
VPCにはインターネットゲートウェイをアタッチし、パブリックとプライベート用のルートテーブルを作成して通信を分離しました。
また、NATゲートウェイを使用して、プライベートサブネットからのインターネットアクセスも可能にしています。
さらに、SSHアクセス用のセキュリティグループを適用した踏み台サーバーにより、VPC内リソースへの安全なアクセスを確保しました。
本番サーバー用EC2インスタンスの追加構成
ここでは、CloudFormationを使用して本番サーバー用のEC2インスタンスを構築し、専用のセキュリティグループを設定する方法を説明します。
以下は、CloudFormationテンプレートの設定例です。このテンプレートでは、インバウンドでポート22(SSH)を許可する「ProductionSecurityGroup」を作成し、本番サーバー用のEC2インスタンスに適用します。
# 本番サーバー用セキュリティグループの作成
ProductionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Allow SSH access to production server"
VpcId: !Ref HondaVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: ホンダ-sg-production
# 本番サーバー用のEC2インスタンスの作成(PrivateSubnet1に配置)
ProductionInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SubnetId: !Ref PrivateSubnet1
ImageId: ami-0b6fe957a0eb4c1b9
KeyName: "honda"
SecurityGroupIds:
- !Ref BastionSecurityGroup
Tags:
- Key: Name
Value: "本番サーバー"
追加のポイントは以下になります。
-
ProductionSecurityGroup:
本番サーバー用のセキュリティグループを作成し、SSHアクセス(ポート22)を許可しています。プライベートサブネットに配置するため、セキュリティグループで制御を行い、外部からの直接アクセスは避けます。 -
ProductionInstance:
本番サーバー用のEC2インスタンスを作成し、「ProductionSecurityGroup」を適用しています。このインスタンスは、プライベートサブネットに配置されており、踏み台サーバーを経由したアクセスのみが可能です。
完成したコード
前回のコードを組み合わせ、最終的に以下のコードが完成しました。
Resources:
# VPCの作成
HondaVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
Tags:
- Key: Name
Value: ホンダ-vpc
# パブリックサブネットの作成
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.0.0/20
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: ホンダ-subnet-public1-ap-northeast-1a
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.16.0/20
AvailabilityZone: ap-northeast-1c
Tags:
- Key: Name
Value: ホンダ-subnet-public2-ap-northeast-1c
# プライベートサブネットの作成
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.128.0/20
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: ホンダ-subnet-private1-ap-northeast-1a
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.144.0/20
AvailabilityZone: ap-northeast-1c
Tags:
- Key: Name
Value: ホンダ-subnet-private2-ap-northeast-1c
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.160.0/20
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: ホンダ-subnet-private3-ap-northeast-1a
PrivateSubnet4:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref HondaVpc
CidrBlock: 10.0.176.0/20
AvailabilityZone: ap-northeast-1c
Tags:
- Key: Name
Value: ホンダ-subnet-private4-ap-northeast-1c
# インターネットゲートウェイの作成
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: ホンダ-igw
# インターネットゲートウェイをVPCにアタッチ
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref HondaVpc
InternetGatewayId: !Ref InternetGateway
# パブリックルートテーブルの作成とパブリックサブネットとの関連付け
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref HondaVpc
Tags:
- Key: Name
Value: ホンダ-rtb-public
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
# Elastic IP の作成
ElasticIP1:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Tags:
- Key: Name
Value: ホンダ-eip-ap-northeast-1a
# NATゲートウェイの作成
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
SubnetId: !Ref PublicSubnet1
AllocationId: !GetAtt ElasticIP1.AllocationId
Tags:
- Key: Name
Value: ホンダ-nat-public1-ap-northeast-1a
# プライベートルートテーブルの作成と各サブネットとの関連付け
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref HondaVpc
Tags:
- Key: Name
Value: ホンダ-rtb-private1-ap-northeast-1a
PrivateRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
# 踏み台サーバー(Bastion)用のセキュリティグループの作成
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Allow SSH access"
VpcId: !Ref HondaVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: ホンダ-sg-bastion
# Elastic IP の作成(別のElastic IP)
ElasticIP2:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Tags:
- Key: Name
Value: ホンダ-eip-ap-northeast-1c
# 踏み台サーバーのEC2インスタンスの作成
BastionInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SubnetId: !Ref PublicSubnet1
ImageId: ami-0b6fe957a0eb4c1b9
KeyName: "honda"
SecurityGroupIds:
- !Ref BastionSecurityGroup
Tags:
- Key: Name
Value: "踏み台サーバー"
# 本番サーバー用セキュリティグループの作成
ProductionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Allow SSH access to production server"
VpcId: !Ref HondaVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: ホンダ-sg-production
# 本番サーバー用のEC2インスタンスの作成(PrivateSubnet1に配置)
ProductionInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SubnetId: !Ref PrivateSubnet1
ImageId: ami-0b6fe957a0eb4c1b9
KeyName: "honda"
SecurityGroupIds:
- !Ref BastionSecurityGroup
Tags:
- Key: Name
Value: "本番サーバー"
実際にスタックを実行してみた
CloudFormationのサービス画面からスタックの作成に進み、作成したyamlファイル
をアップロードします。
スタック名は任意で設定できます。ここでは私の名前「honda
」としています。
画面遷移後のスタックオプション設定については、個々の設定に依存するため、私は設定せずに進めていきます。
最後に確認を行い、問題がなければ最下部までスクロールし、「送信
」をクリックして完了です。
スタックを実行後、イベントタブで成功したことが確認できました(しばらく時間がかかります)。
踏み台サーバーから本番サーバーにSSH接続してみた
CloudFormationでスタックを実行後、EC2サービス画面で踏み台サーバーと本番サーバーが作成されたことを確認しました。
パブリックサブネットの踏み台サーバーにはパブリックIPが付与されていないため、Elastic IPアドレスを付与する必要があります(詳細な手順は省略します)。
ここでは、EC2インスタンスコネクトを使用して接続します。
プライベートサブネットの本番サーバーにSSH接続するには、pemファイルが必要です。
そこで、CloudShellを使用し、ローカルにダウンロード済みのpemファイルをサーバーに配置します。
まず、マネジメントコンソール画面左下からCloudShellを開き、ファイルのアップロードをクリックしてCloudShell上に配置します。
その後、以下のコマンドで踏み台サーバーにpemファイルをコピーします。
sudo scp -i honda.pem honda.pem ec2-user@ec2-54-95-224-16.ap-northeast-1.compute.amazonaws.com:~
次に、以下のコマンドでpemファイルのアクセス権を設定します。
chmod 400 "honda.pem"
最後に、以下のSSHコマンドでプライベートサブネットの本番サーバーに接続します。
ec2-54-95-224-16.ap-northeast-1.compute.amazonaws.com
実際に、踏み台サーバー経由で本番サーバーへのログインが成功しました。
まとめ
本記事では、CloudFormationを用いてプライベートサブネットに本番サーバーを追加し、踏み台サーバー経由でのアクセスを実現しました。
この構成により、外部からの直接アクセスを制限し、安全な環境で本番サーバーを管理できるようになりました。
次回は、この構成に基づく運用上の注意点やセキュリティ対策についてさらに深掘りしていきます。
関連記事
今回と似た記事として、インフラのコード化に関する記事も参考にしてみてください。