🐾

鍵管理もSSMもいらない!?EC2 Instance Connect EndpointでローカルからRDSに接続する方法

2024/12/06に公開

Social Databank Advent Calendar 2024 の6日目です。

はじめに

こんにちは😃 普段趣味でAWSを使用している学生です!!
最近、RDSへの踏み台EC2をどこに建て、どのようにローカル接続するか迷っていました。

まずは代表的な方法を調べてみました!

SSH

  • EC2にパブリックIPの割り当てが必要
  • 使用者ごとに秘密鍵の自己管理および公開鍵の登録が必要
  • EC2がパブリックサブネットにあるためセキュリティグループによるIP制限が必要

SSM Session Manager

  • プライベートなEC2に接続するためにはNATゲートウェイまたはVPCエンドポイントが必要
  • NATゲートウェイおよびVPCエンドポイントのどちらも従量課金であるため使用頻度に対するコストパフォーマンスが低い

従来の方法だとSSHを使う場合はセキュリティ管理が煩雑になり、プライベートEC2に接続するためには従量課金によるコストがかかるようです。
私の場合、踏み台を使用する人数が多いため全員のSSH鍵をその都度管理したくない気持ちがあります。
また、EC2をプライベートサブネットに建てる場合も踏み台のためだけにNATゲートウェイやVPCエンドポイントを作成するのも気が引けます。

そこでこんなサービスを発見しました!
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/connect-with-ec2-instance-connect-endpoint.html
EC2 Instance Connect Endpoint(EICE)は使用無料かつパブリックIPを設定することなくIAMやSSOの権限でEC2に接続できるサービスです!
さらにポートフォワードも使えるため、EICEとポートフォワードを組み合わせれば鍵管理なし&SSMなし&プライベートな踏み台を作成できるのでは🤔と考えて実装できたので紹介します!!

ポートフォワードとEICEを用いてSSMなし&鍵管理なしでRDSにローカル接続する方法

今回紹介する方法は先程の課題を踏まえて次の利点があります!

  • 踏み台EC2をプライベートサブネットに置くことができる
  • NATゲートウェイもVPCエンドポイントも使用しないため低コスト
  • 使用者に秘密鍵を持たせず、AWS IAMやSSOによる権限管理ができる
  • EICEはCloudTrailに対応しているため接続ログを管理できる

それでは早速紹介していきます!

1. 環境の構築

まずは同一のプライベートサブネットにRDS、EC2、EICEをそれぞれ用意します。
Alt text
セキュリティグループは以下のように設定してください。

EICE EC2 RDS
ingress なし port:22, target:EICE
port:3389, target:EICE
port:DB_PORT, target:EC2
egress port:22, target:EC2
port:3389, target:EC2
解放 解放

上の設定から分かるように今回はSSHの22だけでなくRDPの3389を使用します!
なぜDBのポートではなく画面共有に使うRDP??と疑問に思われるかもしれませんが、実は以下の問題から逃れるために必要です。
https://zenn.dev/techno_tanoc/articles/3f714f91da5168

私も最初は上の記事のように 公式ドキュメント にあるCLIコマンドでRDSのポートをポートフォワードしようとしました。

aws ec2-instance-connect open-tunnel \
  --instance-id <ec2のインスタンスID> \
  --remote-port <RDSポート> \
  --local-port <ローカルで使用するポート>
  --profile <任意のprofile>

しかし、以下のエラーが出てしまいます。EICEはSSHとRDPのプロトコルしか受け付けないようです。

The specified RemotePort is not valid. Specify either 22 or 3389 as the RemotePort and retry your request.

ただ、よくよく考えると踏み台にRDPは使用しないので、RDSポートをEC2で3389にポートフォワードすれば解決できそうです!

2. EC2でEICEの3389をRDSにポートフォワード

それではポートフォワードしていきます!流れは下図のようになります。
Alt text
まずはEC2に入ります。下のコマンドで接続できます。

aws ec2-instance-connect ssh \
  --instance-id <ec2のインスタンスID> \
  --connection-type eice \
  --profile <任意のprofile>

EC2に接続した後はSSHのキーペアを作成して、公開鍵を自分自身に登録します。

ssh-keygen -t ed25519 -N '' -f /home/ec2-user/.ssh/id_ed25519
cat /home/ec2-user/.ssh/id_ed25519.pub >> /home/ec2-user/.ssh/authorized_keys

これによりEC2自身に対してSSHができるようになるため、RDSのポートをEC2のアウトバウンドに向けてポートフォワードできるようになります。
あとはRDSエンドポイントとポートを調べて、下のコマンドでポートフォワードを実行します。

ssh -L 0.0.0.0:3389:<RDSエンドポイント>:<RDSポート> -N -f ec2-user@localhost

通信元の0.0.0.0はEC2内のすべてのローカルIPという意味です!わかりやすくするため記載しましたが省略可能です。
つまり、EC2に到達した3389ポートの通信はすべてRDSに転送します!!
もちろんインバウンドはセキュリティグループによりEICEのみを許可しているため、通信はEICEに接続可能なPCのみに絞れます。
この操作により、EICE経由でRDSに接続できるようになりました😳

3. ローカルでEICEの3389にポートフォワード

あとはローカルで下のコマンドを打つだけです!

aws ec2-instance-connect open-tunnel \
  --instance-id <ec2のインスタンスID> \
  --remote-port 3389 \
  --local-port <ローカルで使用するポート>
  --profile <任意のprofile>

これでEICEからフォワードしてきたポートおよびlocalhostに対してSQLクライアントが使えるようになりました🎉

おわりに

SSHの鍵くらいクライアントに管理させるよ!という方はこちらの記事の方がスマートです☺️
https://blog.serverworks.co.jp/2024/05/17/122529

ソーシャルデータバンク テックブログ

Discussion