11
3

SSHトンネル使ってMySQLに接続してみた

Posted at

はじめに

先日業務でSSHトンネルとポートフォワーディングを使用する機会がありました。
今まで使ったことがなかったので、勉強と復習を兼ねて記事にしてみました。

やること

外部から直接アクセスできない環境で、SSHトンネルを使用して安全にDBにアクセスします。

例えばこのような場合です。

  • ローカルからWebサーバへSSH接続が可能
  • ローカルから直接DBにアクセスすることはできない
  • DBにはWebサーバーからしかアクセスできない(Webサーバーが踏み台サーバーとして機能)

名称未設定ファイル.drawio (2).png

SSHトンネルとは?

SSHを使って作られる、暗号化された安全な通信路です。これを利用することで、リモートサーバーへの接続等を安全に行うことができます。
リモートのDBやサーバーに接続する際の「暗号化された専用のトンネル」を作るイメージです。

ポートフォワーディングとは?

ポートフォワーディングは、SSHトンネルで使われる機能の一つです。
ローカルマシンのポートとリモートサーバーのポートを繋げて、特定のポート間の通信を転送する仕組みを提供します。これにより、ローカルのポートを通してリモートサーバーのサービスにアクセスできるようになります。

ポートフォワーディングには以下の3種類があります。

  1. ローカルポートフォワーディング
    ローカルマシンのポートをリモートサーバのポートに転送します
  2. リモートポートフォワーディング
    リモートサーバのポートをローカルマシンのポートに転送します
  3. ダイナミックポートフォワーディング
    SOCKSプロキシを使用して動的にポートを転送します

今回はこの中のローカルポートフォワーディングを使用します。

やってみた

AWSのAmazon Lightsailというサービスを使ってこのような環境を作りました。
上記の図のWebサーバが、Lightsailのインスタンスに置き換わった形です。
勉強を兼ねてTerraformで構築してみました。(ほぼドキュメント通りですが)

名称未設定ファイル.drawio (3).png

# インスタンス
resource "aws_lightsail_instance" "test" {
  name              = "test"
  availability_zone = var.availability_zone
  blueprint_id      = "ubuntu_22_04"
  bundle_id         = "nano_3_0"
  ip_address_type   = "ipv4"
}

# ポートの設定
resource "aws_lightsail_instance_public_ports" "test" {
  instance_name = aws_lightsail_instance.test.name

  # SSHしか使わないので22番ポートだけ
  port_info {
    protocol  = "tcp"
    from_port = 22
    to_port   = 22
    # 一応IPアドレス制限
    cidrs     = [var.ip]
  }
}

# DB
resource "aws_lightsail_database" "test-db" {
  relational_database_name = "testdb"
  availability_zone        = var.availability_zone
  master_database_name     = var.master_database_name
  master_password          = var.master_password
  master_username          = var.master_username
  blueprint_id             = "mysql_8_0"
  bundle_id                = "micro_2_0"
}

SSHトンネルの作成とMySQLへの接続

Lightsailの環境構築が完了したら、SSHトンネルを使ってローカルからMySQLに接続します。

1. SSHトンネルの作成

ssh -L [ローカルのポート番号]:[DBエンドポイント]:[DBポート番号] -i [インスタンスSSH鍵] [インスタンスユーザー名]@[インスタンスパブリックIP]

コマンドのオプション説明

  • -Lオプション
    ローカルポートフォワーディングを行うオプションです。

  • ローカルのポート番号
    ローカルで空いている任意のポート番号を指定します。このポートにアクセスすると、SSHトンネル経由でリモートホストに転送されます。
    3307

  • DBエンドポイント
    DBサーバのエンドポイントです。
    (Lightsailの場合):ls-....amazonaws.com

  • DBポート番号
    DBサーバがリッスンしているポート番号です。
    3306

  • インスタンスSSH鍵
    LightsailインスタンスにSSH接続する際の秘密鍵ファイルのパスを指定します。
    .ssh/LightsailDefaultKey-[リージョン].pem

  • インスタンスユーザー名
    SSH接続時のユーザー名です。
    ubuntu

  • インスタンスパブリックIP
    SSHで接続するLightsailインスタンスのパブリックIPアドレスです。
    1.234.56.78

実際のコマンド例

ssh -L 3307:ls-....amazonaws.com:3306 -i .ssh/LightsailDefaultKey-[リージョン].pem ubuntu@1.234.56.78

この例の場合、ローカルの3307ポートにアクセスすると、SSHトンネルを経由してリモートホストに転送されます。
このとき、転送先はリモートホストのls-....amazonaws.comのポート3306となります。

2. MySQLに接続

mysql -h 127.0.0.1 -P [ローカルのポート番号] -u [DBユーザー名] -p
  • 127.0.0.1
    SSHトンネルを通してリモートホストに接続するため、リモートのDBエンドポイントではなく、ローカルホストを指定します。

  • ローカルのポート番号
    先ほどSSHトンネルの設定で指定したローカルのポート番号を指定します。
    3307

実際のコマンド例

mysql -h 127.0.0.1 -P 3307 -u user -p

このコマンドを実行すると、127.0.0.1(ローカル)のポート3307を通じて、SSHトンネル経由でリモートのMySQL(ls-....amazonaws.com:3306)に接続することができます。

GUIツールを使う場合

(GUIは甘え。という声が聞こえてきそうですが。。)
私が普段使用しているDBeaverでの接続方法になります。

  1. データベース > 新しい接続を選択
    スクリーンショット 2024-09-30 22.31.28.png

  2. DBを選択
    スクリーンショット 2024-09-30 22.31.51.png

  3. 接続情報を入力
    先程の設定を例に入力していきます。

  • 一般
    スクリーンショット 2024-09-30 22.46.09.png

  • SSH
    SSH Tunnelを使用するにチェックを入れると入力できるようなります
    スクリーンショット 2024-09-30 22.47.32.png

テスト接続でこうなれば成功です
スクリーンショット 2024-09-30 22.48.36.png

SSHトンネルで接続した場合はこのようなアイコンが表示されるので分かりやすいです
スクリーンショット 2024-09-30 22.51.33.png

GUIツールは便利ですが、簡単にデータを変更できてしまうので、ローカル環境以外では、読み取り専用で接続するようにしています。

さいごに

記事の作成を通して、これまで知らなかったSSHトンネルやポートフォワーディングについて理解を深めることができました。
今回学んだことを今後の業務に役立てていきたいと思います。

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3