Spring Bootで踏み台をSSHで通して本来アクセスできないDBに接続する
どっかにデータベースサーバーがあるけど、そこはローカルにしかポートが開かれてなくて直接つなげない。
データベースサーバーが入ってるネットワーク内にある踏み台サーバにSSH接続して、
そこからクライアントを起動してデータベースサーバーにアクセスするってのはよくある運用だと思う。
とにかくデータベースを外に出さないってのは重要だと思う。
ただどうしても外から覗きたいことってあるとおもう。
関連会社に公開したり、複数のプロジェクトで同じデータベースサーバーを使うとか。
Kotlin + Spring Bootを使って、外からつなぐときの動きを作る。
環境
Kotlin
Gradle
Spring Boot(JPA)
JSch
接続先はMySQLを想定しています。
普段はPostgreSQLかMongoDBしか使わないから久しぶり。
使用するライブラリ
まずはSSH接続やポートフォワーディング機能のあるJSchを使います。
gradleのdependenciesにimplementation("com.jcraft:jsch:0.1.55")を入れればOKです。
※0.1.55は記事作成時点での最新
今回はMySQLに接続するので、ドライバも追加しておく
implementation("mysql:mysql-connector-java")
実装
code:SshTunnelTestApplication.kt
package com.example.sshtunneltest
import com.jcraft.jsch.JSch
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.jdbc.core.JdbcTemplate
@SpringBootApplication
class SshTunnelTestApplication
fun main(args: Array<String>) {
connect()
val ctx = runApplication<SshTunnelTestApplication>(*args)
val jdbc = ctx.getBean(JdbcTemplate::class.java)
jdbc.queryForList("show tables").forEach { println(it) }
}
fun connect() {
val jsch = JSch()
jsch.addIdentity("root/step_server.pem")
jsch.setKnownHosts("root/known_hosts")
val session = jsch.getSession("ssh server user", "ssh.server.host.name", 22)
session.connect()
session.setPortForwardingL(3309, "secret.database.server.host.name", 3306)
}
やってることは単純です。
mainのメソッドでは、SpringBootのアプリケーション実行前にconnect()をよんでいるだけです。
一応最後にちゃんと繋がってるよねーって確認でテーブル一覧を見てます。
connectメソッドでは、つないでポートフォワードしてるだけです。
ssh接続はパスワードではなくキーで接続しているので、SSHのためのキーと、ホストの許可をしているknown_hostsファイルを指定しています。
known_hostsファイルの作り方は備忘のためにも後程追記する。
getSessionは踏み台になるSSHで接続可能なサーバの情報です。
引数は、ユーザー名、ホスト名、ポートです。
setPortForwardingLはローカルのポートに接続先のポートを上書きしちゃいます。
引数は、ローカルのポート、踏み台から接続する先のホスト名、踏み台から接続するポートです。
つまり、DBサーバのホスト名とポートを指定します。
ホスト名と言っていますが、IPアドレスでもOKです。
最後にBeanからjdbcを取ってきてクエリを流して終わりです。
重要なポイント
まず、Spring Bootのアプリケーションが起動するより先にport forwardingしましょう。
Spring Bootでは起動時にデータベースへのコネクションを作成しちゃっているので、先にポートフォワーディングしないと繋がらずに失敗で終わります。
あとは引数を間違えないことですかね。
known_hostsの作り方
Windowsで開発をしているのですが、基本的にコマンドはgitbashから実行しています。
gitbashで下記コマンドを実行すればファイルが作られます。
$ ssh-keyscan -H -t rsa ssh.server.host.name >> root/known_hosts
これで作ったファイルをプロジェクトは以下の分かりやすいところにおいて、指定するだけです。
簡単!!!
参考
最終更新日 : 2019/12/25