サービス概要

EC2 Instance Connect Endpoint (以下、EIC エンドポイント) は、パブリック IP アドレスを使用せずに EC2 インスタンスに SSH および RDP 接続できるようになるサービス
EIC エンドポイントの使用に追加料金はかかりません。標準のデータ転送料金が適用されます。なので検証が終わってもエンドポイントは削除しなくても大丈夫です。
Amazon EC2 Instance Connect supports SSH and RDP connectivity without public IP address

目的・やりたいこと

EIC エンドポイントを使用して、本当に踏み台ホストを作成する必要なくプライベート IP アドレスを持つインスタンスに SSH / RDP 接続をトンネリングできるのか検証する。

対象者

お客様環境に踏み台なしでメンテナンスしたい運用管理者(初級者~中級者)

対象となる技術

  • EC2 Instance Connect

参考URL

前提条件

  • 必要な権限やロールはあらかじめ付与されているものとします。
    Grant IAM permissions to use EC2 Instance Connect Endpoint
  • EC2 Instance Connect エンドポイントは、「利用可能」(コンソール) またはcreate-complete(AWS CLI) 状態である必要があります。
  • 接続先のインスタンスのセキュリティ グループが受信トラフィックに対して正しく構成されていることを確認してください。

注意事項

  • EICエンドポイントはアカウントごとに5つ、かつVPCごとに1つのみ作成できます。
  • RDP接続の方がポートフォワードを一旦張る関係上1ステップ余分で若干手間がかかります(SSHは1行のコマンドで行けます)。
  • 古いAWS CLIバージョンだと aws ec2-instance-connect コマンドがないと怒られます。AWS CLIは現時点での最新バージョンにバージョンアップしておいてください。
    macOS pkg ファイルをダウンロードしてインストールすればOK
$ aws --version
aws-cli/2.7.14 Python/3.9.11 Darwin/22.5.0 exe/x86_64 prompt/off

$ aws ec2-instance-connect  help

Could not find executable named "groff"

$ aws ec2-instance-connect open-tunnel help

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help

aws: error: argument operation: Invalid choice, valid choices are:

send-ssh-public-key                      | send-serial-console-ssh-public-key      
help                                    

(バージョンアップ後)

$ aws --version
aws-cli/2.12.3 Python/3.11.4 Darwin/22.5.0 exe/x86_64 prompt/off

$ aws ec2-instance-connect  help
EC2-INSTANCE-CONNECT()                                  EC2-INSTANCE-CONNECT()

NAME
       ec2-instance-connect -

DESCRIPTION
       Amazon EC2 Instance Connect enables system administrators to publish
       one-time use SSH public keys to EC2, providing users a simple and
       secure way to connect to their instances.

AVAILABLE COMMANDS

       o help

       o open-tunnel

       o send-serial-console-ssh-public-key

       o send-ssh-public-key

       o ssh

作業の流れ

概要図

事前作業

プライベートサブネット(nozaki-private-sub2)に、あらかじめ接続用のEC2(Linux)とEC2(Windows)を立てておきます。

検証手順

1.EICエンドポイントの作成
VPC>エンドポイントから作成で[EC2 Instance Connect Endpoint]を選択

VPC、プライベートサブネット(エンドポイントはnozaki-private-sub1)を選択し、[エンドポイントを作成]

2.EC2のセキュリティグループ(nozaki-ec2ep-SG)の作成
まず、EICエンドポイントからの接続を受けるEC2に適用するセキュリティグループを作成します。
これはEICエンドポイントのセキュリティグループ(nozaki-SG)からのSSHとRDPのみを許可するインバウンドルールにしました。

3.EICエンドポイントのセキュリティグループ(nozaki-SG)の作成
今度はEICエンドポイントに適用するセキュリティグループを作成します。インバウンドルールはお任せしますが、大事なのがアウトバウンドルール
このようなnozaki-ec2ep-SG宛のSSHとRDPのみ許可するアウトバウンドルールを設定するとセキュリティは高まります。

例えば、nozaki-SGのアウトバウンドルールをこのような適当なDNS(UDP)のみ許可するルールにしてみる。

するとやはり接続できないようになっているので、ちゃんとセキュリティグループが効いているのがわかります。

4.EICエンドポイント経由のEC2 SSH接続
順番は前後しますが、最後にいよいよEICエンドポイント経由でEC2にSSHしてみます。
やり方は簡単。通常通りEC2から[接続]を選ぶと、このように[EC2 Instance Connect]というタブが増えています。
そこで接続タイプで[EC2 Instance Connect エンドポイントを使用して接続する]を選び、ユーザー名をec2-userに修正、最後にEC2 Instance Connect エンドポイントを選んで[接続]

するとこのようにEC2 シリアルコンソールで接続したかのような画面になります。

とは言ってもやはり普段使ってるSSHコマンドで接続したいですよね。
AWS CLIを使う場合は、以下のように ssh と open-tunnel AWS CLI コマンドを使用します。-o ProxyCommandは、インスタンスへのプライベートトンネルを作成するopen-tunnelコマンドを囲みます。

ssh -i nozaki.pem ec2-user@i-0e6a2ad9ed618a627 -o ProxyCommand='aws ec2-instance-connect open-tunnel --instance-id i-0e6a2ad9ed618a627'

するとこのように無事?SSH接続できました。

The authenticity of host 'i-0e6a2ad9ed618a627 (<no hostip for proxy command>)' can't be established.
ED25519 key fingerprint is SHA256:/NRXGfzk7RRsAacIY96ov6guWeaU+CUKTMYKqWibF+E.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'i-0e6a2ad9ed618a627' (ED25519) to the list of known hosts.
Last login: Mon Jun 26 03:55:08 2023 from ip-10-0-30-104.ap-northeast-1.compute.internal

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-0-47-30 ~]$ 

(追記)
とここまでが公式の手順
aws ec2-instance-connect send-ssh-public-key + aws ec2-instance-connect open-tunnelコマンド相当の機能を実行したうえでSSH接続を行ってくれる便利な aws ec2-instance-connect ssh コマンドというのが新たに追加されています。

aws ec2-instance-connect ssh --instance-id i-0e6a2ad9ed618a627 --connection-type eice

こちらでも無事?SSH接続できました。

The authenticity of host '10.0.47.30 (<no hostip for proxy command>)' can't be established.
ED25519 key fingerprint is SHA256:/NRXGfzk7RRsAacIY96ov6guWeaU+CUKTMYKqWibF+E.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:36: i-0e6a2ad9ed618a627
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.47.30' (ED25519) to the list of known hosts.
Last login: Mon Jun 26 11:52:10 2023 from ip-10-0-30-104.ap-northeast-1.compute.internal

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/

どうせなら-o ProxyCommandで囲まなくていいこちらを今後は使っていきたいですね。

5.EICエンドポイント経由のEC2 RDP接続
SSHの方はうまく行ったので、今度はRDPで別のEC2に接続してみます。
次のコマンドを実行して、インスタンスが配置されている VPC へのプライベート トンネルを確立します(ポートフォワード)。

$ aws ec2-instance-connect open-tunnel --instance-id i-09ee27b5eab9c94b1 --remote-port 3389 --local-port 5555
Listening for connections on port 5555.

(Macの場合)
RDP デスクトップファイルで+(Add PC)をクリックし、[編集]します。
[PC name(接続先のインスタンス)] に「localhost:5555 」前の手順と同じ値を使用し、[Add]を選択します。

あとは通常通りパスワードを入力すれば、無事いつものRDP接続成功!

所要時間

30分

ユースケース

Bastion ホストによるパッチ適用、管理、監査の運用オーバーヘッドと追加コストを削減したいケース