セッションマネージャー over SSH 経由でプライベートサブネット内のRDSへ接続する方法


概要

プライベートサブネット内に立てた Amazon RDS には、グローバル DNS が発行されないため、ローカルから AWS 上の RDS への接続はできません。

そんなときはセッションマネージャーとプライベートサブネット内の EC2 経由で RDS へ接続することができます!!!!

この方法で接続できる前提条件

下記条件を満たしている環境の場合、セッションマネージャーを利用してリモート RDS へ接続することができます。

  • プライベートサブネット内に踏み台用の EC2 が起動されていること
  • EC2 内にセッションマネージャーがインストールされていること
  • EC2 内の ec2-user に公開鍵を配置していること

コンテナ環境のみや踏み台サーバを RDS と同じ VPC 内に建てられない場合、公開鍵を配置できない場合はこの方法では接続できませんのでご注意ください。

構成概要図

下記のようなルートでリモートの RDS へ接続できます。

なぜセッションマネージャーにさらに SSH 接続しているか

SSH コマンドのポートフォワード機能を使うのでどうしても SSH 接続が必要だったから。
DB クライアントから接続する場合、「セッションマネージャから接続するかたへ」みたいに便利な接続方法を提供しているわけではありません。
なので普通の TCP/IP 接続で接続できるように、SSH を利用したポートフォワーディングを設定しています。

しかし、セッションマネージャーで EC2 に接続するのでセキュリティグループには SSH のポートを許可する必要はありません。

参考:
セッションマネージャー越しにSSHアクセスすると何が嬉しいのか

設定内容

では詳しく設定コマンドを記述していきます。

前提

下記の設定を事前に完了している必要があります。

  • AWS CLI のインストールと config の設定。
  • 踏み台サーバ内にセッションマネージャーをインストール。
  • RDS のセキュリティグループに EC2 のセキュリティグループを登録。
  • ec2-user に SSH 接続用の公開鍵を登録。

参考:
※ セッションマネージャーをインストールされていない方はこちらを参考に
Systems Manager セッションマネージャを使ったら SSH 管理不要になった

ローカルにセッションマネージャーをインストール

ローカルの端末にセッションマネージャーをインストールします。
今回は Mac を想定しています。

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
$ unzip sessionmanager-bundle.zip
$ sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin
$ session-manager-plugin

他の OS の場合は下記公式サイトを参考してください。
(オプション) AWS CLI 用の Session Manager plugin をインストールする

ssh config の設定

SSH の config ファイルにセッションマネージャーをプロキシーとした SSH の設定を記述します。
HostName は踏み台サーバの EC2 インスタンスの ID になります。
profile は AWS CLI を利用するときに設定する ~/.aws/config に記載されている対象 AWS アカウントのプロファイル名を指定します。
profile を指定しない場合は default アカウントが適応されます。

# vi ~/.ssh/config
host remote-ec2
    HostName i-xxxxxxxxxxxxxxx
    Port 22
    User ec2-user
    IdentityFile ~/.ssh/id_rsa.pem
    ProxyCommand sh -c "env PATH=/usr/local/bin:$PATH aws ssm start-session --profile <プロファイル名> --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

SSH の接続確認

踏み台 EC2 への接続確認を行います。
もし、多要素認証を設定している場合はここで認証コードを聞かれますので、入力してください。

多要素認証なし
$ ssh remote-ec2
# ログインが成功し、リモート EC2 のIPアドレスが表示されたら接続成功。
# [ec2-user@ip-xx-xx-xx-xx ~]$ 
多要素認証あり
$ ssh remote-ec2
Enter MFA code for arn:aws:iam::xxxxxxxxxxxx:mfa/syoimin: 
# [ec2-user@ip-xx-xx-xx-xx ~]$ 

ポートフォワーディングを実行

最後に SSH コマンドでポートフォワーディングのプロセスを実行します。
このプロセスが実行中の間はローカルの 33306 番ポートに対してリモート RDS の 3306 番ポートにポートフォワーディングされます。

$ ssh -N remote-ec2 -L 33306:xxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com:3306

DB クライアントでリモート RDS へ接続

接続の準備が整ったので、実際に リモートの Amazon RDS へ接続してみます。
下記の設定項目は MySQL Workbench を参考にしています。

Connection Method: Standard(TCP/IP)
Hostname: 127.0.0.1
Port: 33306
Username: <DB ユーザ名>
Password: <DB パスワード>
Default Schema: <データベース名>

接続先ホストはローカルIP。
接続先ポートは先程ポートフォワードした接続元のポート番号になります。
他の DB クライアントやコマンド等でも同様に上記アクセス情報でアクセスできると思います。

感想

セッションマネージャーで SSH のポートワードできることは知っていましたが、ポートフォワードを使ってどうにかして ローカルの DB クライアントからリモートの RDS への接続ができないかなと思い悪戦苦闘していました。

踏み台の EC2 インスタンスと SSH の鍵が必要にはなりますが、セッションマネージャー経由なので踏み台用の EC2 インスタンスには SSH のポートを一切開けなくて済みます。
セキュアな状態を保ったままリモートの RDS へ接続できるのでこの方法が今の所ベストな方法ではないのかなと思います!!!

今回は、DB クライアントから接続したかったので SSH のポートフォワーディングを使った接続方法で接続しました。
コマンドラインだけだとセッションマネージャや AWS CLI 単体だけで接続できると思うので、コマンドラインで済ませる方はここまで複雑なことはやらなくていいかもです。