踏み台の奥に目的のサーバがある環境では、踏み台経由のSSHトンネルを作り、多段ポートフォワーディングにてアクセスすることがあります。
そんな中、SSHトンネル1つだけでは接続できない環境がありました。
そこで、SSHトンネル内にSSHトンネルを通して、踏み台2つを経由した多段ポートフォワーディングした時のメモを残します。
なお、もしかしたらより良い方法があるかもしれないため、ご存知の方は教えていただけるとありがたいです。
目次
環境
ネットワーク構成は以下のとおりです。
Mac -- (ssh) -> 踏み台A -- (ssh) --> 踏み台B -- (ssh) --> DBサーバ
各サーバの設定内容です。いずれもSSH用のポートしか外部に開放されていません。
種類 | ホスト名 | 開放ポート | SSHユーザ | SSH鍵のありか | サーバ設定変更可否 |
---|---|---|---|---|---|
踏み台A | Gateway | 10022 (SSH) | shinano_gold | Mac | 不可 |
踏み台B | Bastion | 20022 (SSH) | shinano_dolce | Mac | 不可 |
DBサーバ | DB | 30022 (SSH) | akibae | Bastion | 不可 |
この時、DBサーバの 3306
ポートを、Macの 13306
ポートにつなげたいとします。
ダメだった接続
1本のSSHトンネルを使う場合は、以下のような方法で接続します。
- つながるSSHトンネルが俺の力だ! - くろのて
- 踏み台サーバを経由した多段SSHのやり方 - Qiita
- つまみがなければ鼻でもつまむ:Apple Remote Desktop on SSH - livedoor Blog(ブログ)
- linux - Setting up ssh config file with id_rsa through tunnel - Super User
ただ、今回の場合、サーバ Gateway で何かしらの設定がされているようでした。そのため、Mac - DBサーバ間で通信できませんでした。
一方、
Mac -- (ssh) --> 踏み台B -- (ssh) --> DBサーバ
であれば接続できたものの、踏み台Aを回避する方法はさすがにダメでした。
SSHトンネル内にSSHトンネルを通す接続
上記のとおり、踏み台A(Gateway)が厄介そうでした。
そこで、以下の資料を参考に、SSHトンネル内にSSHトンネルを通すことで、踏み台A(Gateway)を通過することにしました。
1本目のSSHトンネル
1本目は、Macから踏み台B(Bastion)へ直接SSH可能にするためのSSHトンネルを用意します。ssh/configは以下のとおりです。
Host sub user shinano_gold HostName Gateway Port 10022 IdentityFile /mac/path/to/gateway_key LocalForward 11022 Bastion:20022 AddKeysToAgent yes UseKeychain yes
ポイントはLocalForwardにある 11022 Bastion:20022
です。
MacからGatewayへポート 10022
でSSH接続するとともに、GatewayからBastionヘSSHするためのポート 20022
とMacのローカルポート 11022
を接続しています。
これにより、Macのローカルポート 11022
へSSHすることで、裏側ではBastionの 20222
ポートとのSSHトンネルが作成されます。
- AddKeysToAgent
- UseKeychain
の両方を yes
としておくと、AgentとKeychainが使われるため、パスフレーズの再入力が不要となります。
続いて、このconfigを使って、ターミナルでGatewayサーバに接続します。見た目は普通のSSHですが、ログを見るとポートフォワードも有効になっています。
$ ssh sub -v ... debug1: Local connections to LOCALHOST:11022 forwarded to remote address Bastion:20022 debug1: Local forwarding listening on 127.0.0.1 port 11022. ... [shinano_gold@Gateway ~]$
1本目のSSHトンネル内に通す、SSHトンネル
まずは、1本目のSSHトンネルを使って Mac -> Bastion でSSHするためのssh/configを書きます。
Macのローカルポート 11022
に、DBの3306ポートからフォワードされる予定のポート 50000
を接続しています。
Host main user shinano_dolce HostName 127.0.0.1 Port 11022 IdentityFile /mac/path/to/bastion_key LocalForward 13306 localhost:50000 AddKeysToAgent yes UseKeychain yes
続いて、Mac -> Bastion の接続を行います。
1本目のSSHトンネルのターミナルはそのままにして、別のターミナルを開いてMac上で実行します。
$ ssh main -v ... debug1: Local connections to LOCALHOST:13306 forwarded to remote address localhost:50000 debug1: Local forwarding listening on 127.0.0.1 port 13306. ... [shinano_dolce@Bastion ~]$
50000
ポートへのフォワードが成功しました。
続いて、Bastion -> DBの接続です。
本当は Bastion -> DB の接続も ssh/config 化したいのですが、Bastionサーバ上からSSH鍵を移動できないという制限があります。これにより、MacにSSH鍵がある前提の ProxyCommand
が使えないことから、ssh/config化をあきらめました*1。
では、2本目のターミナル上にて、DBのポート 3306
を、Bastion のポート 50000
ポートへとポートフォワーディングするようSSHしてみます。
[shinano_dolce@Bastion ~]$ ssh -N -L 50000:DB:3306 akibae@DB -p 30022 -i /bastion/path/to/db_key -v ... debug1: Local connections to LOCALHOST:50000 forwarded to remote address DB:3306 ...
なお、今回は -N
オプション無しだと接続が切れてしまったので、あえて付けています。
SSH (1) | OpenSSH-7.3p1 日本語マニュアルページ (2016/10/15)
接続できたので、動作確認です。
Macの 13306
ポートにつながっていると思われるDBに、telnetで接続します*2。
$ telnet localhost 13306 Trying 127.0.0.1... Connected to localhost. ... mysql_native_password
DBサーバのポート 3306
に接続でき、また、DBサーバ上で動いているMySQLと会話ができました。
*1:何か良い方法があるのかな...
*2:High Sieera以降は telnet が無いようなので、homebrew などでインストールします https://support.apple.com/ja-jp/HT208430