SSHトンネル内にSSHトンネルを通して、踏み台2つを経由した多段ポートフォワーディングをしてみた

踏み台の奥に目的のサーバがある環境では、踏み台経由の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 ポートを、Mac13306 ポートにつなげたいとします。

 

ダメだった接続

1本のSSHトンネルを使う場合は、以下のような方法で接続します。

 
ただ、今回の場合、サーバ 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へポート 10022SSH接続するとともに、GatewayからBastionヘSSHするためのポート 20022Macのローカルポート 11022 を接続しています。

これにより、Macのローカルポート 11022SSHすることで、裏側ではBastionの 20222 ポートとのSSHトンネルが作成されます。

なお、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鍵を移動できないという制限があります。これにより、MacSSH鍵がある前提の 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)

 
接続できたので、動作確認です。

Mac13306 ポートにつながっていると思われる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