Amazon EC2への接続方法を整理する
はじめに
Amazon EC2への接続方法はいくつか存在しますが、改めてそれぞれの長所・短所など整理したかったので、ここにまとめています。
4つの方法と比較
Amazon EC2にアクセスする方法は現状以下の4通りがあります。ただしシリアルコンソールでのアクセスはトラブルシューティングが目的であること、利用できるインスタンスが限られること、OSユーザーにログインパスワードを設定する必要があることなどから、ここでは特に触れていません。
種別 | 概要 | アクセスコントロール |
---|---|---|
SSH | インスタンス起動時に指定するキーペアのプライベートキーを利用してアクセスする。AWSのサービスに依存せず、従来サーバーにログインする際に使われる方法。 | プライベートキーの有無・ユーザー所有権、Security Group |
Session Manager | AWS Systems Manager Session Managerを利用し、AWSマネジメントコンソールやローカル環境からアクセスする。IAMポリシーでアクセスを制御する。 | IAMポリシー |
Instance Connect | インスタンス起動時に指定するSSH鍵を利用し、AWSマネジメントコンソールからアクセスする。プライベートキーを使用せずSecurity Groupでアクセスを制御する。 | IAMポリシー、Security Group |
シリアルコンソール | 一部のインスタンスタイプに対し、シリアルポートにアクセスする方法。トラブルシューティングで利用する。 | IAMポリシー |
それぞれの使い分けは以下のように考えています。
- 基本的にはSession Manager / Instance Connectのどちらかを利用する。対応するOSの種類やバージョンの多さ、可用性、Security Groupインバウンド方向のポート開放が不要な点から、個人的にはSession Managerを利用するほうが良いのではと考える。
- SSHは運用面・セキュリティ面からできる限り利用しないようにする。
- シリアルコンソールは現状利用する場面があまりないかもしれません。
方法1. SSH
SSHでのアクセスを利用するには、EC2インスタンス作成時にEC2キーペアを指定し、そのキーペアに対応するプライベートキー (.pem
ファイル) を所有している必要があります。またアクセス元の環境 (ローカル環境や別のEC2インスタンス、AWS Cloud Shellなどの環境) からEC2にアクセスするため、Security Groupなどのアクセス制限でアクセスが許可されている必要があります。細かな条件などは公式ドキュメントに記載されています。
アクセス方法ですが、アクセス用のプライベートキーを既に所有している場合は、Linux / Windowsターミナルから ssh
コマンドを実行したり、Tera Term / Putty / RLoginなどのクライアントソフトを利用します。
# ssh -i <.pemファイルのファイルパス> <EC2インスタンスOSユーザー名>@<パブリックIPアドレス or DNSホスト名>
$ ssh -i ~/.ssh/test-key.pem ec2-user@1.2.3.4
なお、プライベートキーの取得方法は、EC2インスタンス及びSSH鍵をどう作成したかによって変わります。
- AWSマネジメントコンソール: キーペアor EC2インスタンス作成時に、
.pem
ファイルを団ロードするよう案内されます。プライベートキーを取得できるのはこのタイミングだけです。 - AWS CLI:
aws ec2 create-key-pair
コマンドを実行してキーペアを作成し、作成に成功した場合のレスポンスに含まれる文字列を.pem
ファイルとして保存します。 - CloudFormation: CloudFormationでキーペアを作成した場合、AWS Systems Manager Parameter Storeに
/ec2/keypair/{key_pair_id}
という名称でプライベートキーが保存されます。Parameter Storeに保存された文字列を.pem
ファイルとして保存します。
方法2. Session Manager
AWS Systems Manager
はEC2の運用に関するサービスを多数提供していますが、その中にSession Managerも含まれます。Session Managerは前述のSSH鍵を使用せずEC2インスタンスにアクセスする方法を提供しており、主にAWSマネジメントコンソールからEC2にアクセスすることができます (設定をすることで、ローカル環境からSession Managerを使用してアクセスすることも可能です) 。
Session Managerを利用することのメリットは公式ドキュメントで紹介されており、いくつか抜粋します。
-
ポートを開放する必要がない
: SSHアクセスのためにSecurity Groupでポートを開放する必要がありません。不必要に開放するポートは攻撃リスクを高めるため、ポートを開放しないことがセキュリティ向上につながります。 -
SSH鍵の管理が不要
: Session ManagerはAWSのマネージドサービスであり、インスタンスへの接続はSSM Agentなどを利用します。SSH鍵の管理は不要となり、鍵の管理をする必要がなくなります。 -
踏み台サーバーが不要
: 前項と似た理由ですが、SSM Agentによるアクセスを提供しており、踏み台サーバーも不要になります。 -
IAMポリシーによるアクセス制御
: Session ManagerによるアクセスはIAMポリシーによって制御されるため、IAMユーザー・グループに対してアクセス制御を一元化できます。 -
ログ記録・監査機能の提供
: Session Managerによるアクセスを行う場合、誰がアクセスしたか、セッション中にどんなコマンドを実行したか記録することができます。運用やセキュリティ上の理由でこれら情報の管理・提供が求められる場合も対応できます。
なお、Session Managerによるアクセスを試す用のCloudFormationは以下に配置します。ここではPrivate Subnet上のEC2インスタンスに対して、AWS PrivateLinkを使用してアクセスを行っています。
CloudFormationテンプレート
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
EnvName:
Type: String
Default: ec2-example
VPCCIDR:
Type: String
Default: "10.0.0.0/16"
PrivateSubnetCIDR:
Type: String
Default: "10.0.0.0/24"
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Ec2InstanceType:
Type: String
Default: t3.medium
KeyPair:
Type: String
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${EnvName}-VPC
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Ref PrivateSubnetCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-PrivateSubnet
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-PrivateRouteTable
PrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet
RouteTableId: !Ref PrivateRouteTable
EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EndpointSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-EndpointSecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VPCCIDR
EndpointSSM:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointSSMMessages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointEC2Messages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EC2IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${EnvName}-SSM-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: EC2IAMRole
InstanceProfileName: !Sub ${EnvName}-EC2InstanceProfile
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2SecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2SecurityGroup
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref Ec2InstanceType
SubnetId: !Ref PrivateSubnet
ImageId: !Ref Ec2ImageId
SecurityGroupIds:
- !Ref EC2SecurityGroup
IamInstanceProfile: !Ref EC2InstanceProfile
KeyName: !Ref KeyPair
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2Instance
方法3. Instance Connect
Instance ConnectはSSH鍵を利用してインスタンスにアクセスする方法ですが、ここでのSSH鍵は認証ユーザーがアクセスするたびに一時的なSSHキーを生成し、それを利用します。アクセスはAWSマネジメントコンソール、もしくはAWS CLIから行います。
Instance Connectの利点はいくつかあります。
-
IAMポリシーによるアクセス制御の一元化
: EC2インスタンスへのアクセスをIAMポリシーベースで制御できます。 -
ephemeralなSSHキーの利用
: 一時的なSSHキーを利用することで、ユーザーがプライベートキーを管理する必要がなくなります。 -
CloudTrailによる監査
: Instance Connectによる接続はCloudTrailに記録されるため、監査に対応しやすくなります。 -
プライベート空間のインスタンスにも対応
: Instance ConnectはSession managerと同様、パブリック・プライベートどちらのEC2インスタンスにも対応しています。プライベートの場合はInstance Connect Endpointを利用して接続します。
Instance Connectは利用するうえでいくつか制約があります。本サービスは比較的最近登場したこともあり、新しいバージョンのAmazon Linux / Ubuntuにしか対応していません。またInstance Connectを利用するには、特定のIPレンジまたはInstance Connect EndpointからEC2インスタンスへのインバウンド方向の通信を許可する必要があります。
Instance ConnectもCloudFormationテンプレートを置いておきます。ここではパブリック・プライベート両方のパターンを置いており、プライベートのほうはInstance Connect Endpointを利用しています。
Instance Connect CloudFormationテンプレート
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
EnvName:
Description: "Environment Name"
Default: "ec2-example"
Type: String
VPCCidr:
Description: "VPC CIDR"
Default: "10.0.0.0/16"
Type: String
PublicSubnet1Cidr:
Description: "Public Subnet 1 CIDR"
Default: "10.0.0.0/24"
Type: String
PrivateSubnet1Cidr:
Description: "Private Subnet 1 CIDR"
Default: "10.0.2.0/24"
Type: String
PublicSubnet1AZ:
Description: "Public Subnet 1 AZ"
Default: "ap-northeast-1a"
Type: String
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Ec2InstanceType:
Type: String
Default: t3.medium
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidr
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: environment
Value: !Ref EnvName
PublicSubnet1:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
CidrBlock: !Ref PublicSubnet1Cidr
VpcId: !Ref VPC
AvailabilityZone: !Ref PublicSubnet1AZ
Tags:
- Key: environment
Value: !Ref EnvName
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: environment
Value: !Ref EnvName
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: environment
Value: !Ref EnvName
PublicRoute:
Type: AWS::EC2::Route
#DependsOn: AttachGateway
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
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2SecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2SecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: "3.112.23.0/29"
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref Ec2InstanceType
ImageId: !Ref Ec2ImageId
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref PublicSubnet1
GroupSet:
- !Ref EC2SecurityGroup
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2Instance
Instance Connect Endpoint CloudFormationテンプレート
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
EnvName:
Type: String
Default: ec2-example
VPCCIDR:
Type: String
Default: "10.0.0.0/16"
PrivateSubnetCIDR:
Type: String
Default: "10.0.0.0/24"
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Ec2InstanceType:
Type: String
Default: t3.medium
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${EnvName}-VPC
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Ref PrivateSubnetCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-PrivateSubnet
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-PrivateRouteTable
PrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet
RouteTableId: !Ref PrivateRouteTable
InstanceConnectEndpoint:
Type: AWS::EC2::InstanceConnectEndpoint
Properties:
SecurityGroupIds:
- !Ref EndpointSecurityGroup
SubnetId: !Ref PrivateSubnet
EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EndpointSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-EndpointSecurityGroup
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2SecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2SecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref EndpointSecurityGroup
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref Ec2InstanceType
SubnetId: !Ref PrivateSubnet #{ Fn::ImportValue: !Sub "PrivateSubnet1-${EnvName}" }
ImageId: !Ref Ec2ImageId
SecurityGroupIds:
- !Ref EC2SecurityGroup
Tags:
- Key: Name
Value: !Sub ${EnvName}-EC2Instance
Session Manager / Instance Connectの比較
最後に、EC2インスタンスへの4つの接続方法のうち、特に利用機会が多そうなSession Manager / Instance Connectの比較をしています。
対応するOS
- Session Manager
- Linux: AWS Systems ManagerのサポートするすべてのOS (詳細はこちら)
- Windows: Windows Server 2012 - 2022
- Instance Connect
- インストール済み: Amazon Linux 2023 / Amazln Linux 2 2.0.20190618 以降/ Ubuntu 20.04以降
- インストール可能: Amazon Linux 2 / Ubuntu 16.04以降
セキュリティ
- Session Manager
- Security Group
- Inbound: 特になし
- Outbound: 特定のエンドポイントへの443番ポートの許可
ec2messages.region.amazonaws.com
ssm.region.amazonaws.com
ssmmessages.region.amazonaws.com
- IAMポリシー: 接続対象のEC2インスタンスに
AmazonSSMManagedInstanceCore
というAWSマネージドポリシーを付与する
- Security Group
- Instance Connect
- Security Group:
- Inbound: 特定のIPレンジ (パブリック)、またはEndpoint (プライベート)に対して22番ポートを許可
- Outbound: 特になし
- IAMポリシー: 利用するIAMユーザーは以下の権限を付与される必要がある
ec2-instance-connect:SendSSHPublicKey
ec2:osuser
ec2:DescribeInstances
- Security Group:
可用性
- Session Manager
- プライベートサブネットの場合はVPCエンドポイントを利用する。VPCエンドポイントはVPCあたり複数作成することができるため、複数のサブネットに作成することでAZ障害に対応できる
- Instance Connect
- Instance Connect EndpointはVPC当たり1つしか作成できないため、AZ障害に対応できない
コスト
- Session Manager
- Session Managerは無料で利用できる
- VPCエンドポイントを使う場合は
0.014USD/時×3
の利用料金が発生する
- Instance Connect
- 無料で利用できる
Discussion