外部から見えないサーバへつなぐ必要があって、SSHのトンネリングというのをやってみた。
Mac,Linuxの場合
鯖1 (example.com
) でSSHサーバが動いてて、グローバルIPアドレスを持たないが鯖1と同じネットワークにいる鯖2(192.168.1.10
) につなぎたい、という場合 SSHトンネリングすると鯖2に直接接続つないでいるかのように扱うことが出来ます。
今、手元から 鯖2 の MySQL サーバにつなぎぐ場合の例です。MySQLのポートはデフォルトの 3306 とし、鯖1から接続が可能な状況とします。
以下のようにすると、自分のマシンの 19000番ポートが SSHトンネルを経由して鯖2の3306番 ポートに繋がります。
$ ssh -L19000:192.168.1.10:3306 example.com -l username
-L
はローカルのポート指定、-l
は example.com のSSHのユーザ名を指定します。詳細な書式は、下記です。
ssh -L{ローカルのポート番号}:{鯖2の、鯖1から見たhost}:{鯖2で接続したいポート番号} {鯖1のhost} -l {鯖1にSSHする際のユーザ名}
このとき、鯖1に接続可能な状態であればOKです。鍵認証でもパスワード認証でも問題ないです。鯖1から鯖2のポートに接続可能であれば、SSHトンネリングは完了です。
コマンドを実行すると、SSHで通常のログインしたのと同じ状態になりますが、閉じてしまうとトンネルも閉じてしまうので、そのままにしておきます。
もしくは、以下のように -f -N を付けてバックグラウンドで実行させておくことも出来ます。
$ ssh -f -N -L19000:192.168.1.10:3306 example.com -l username
SSHがつながった後は、localhost の 19000番ポートへMySQLでつなぎにいくと、鯖2の3306番ポートにMySQLしたのと同じようにつながります。
$ mysql -u testuser -p --port=19000 -h 127.0.0.1
この例は MySQL ですが、注意点としてはホスト(-hオプション)を 127.0.0.1に指定するということです。デフォでlocalhostなのに?と思うんですが、MySQLは localhost と 127.0.0.1 の扱いが違います。localhost は ローカルのソケットを通して接続を行なうのですが、127.0.0.1 はTCPソケットで127.0.0.1で接続を行ないます。今回は、ローカルのソケットでつなぐのではなく、TCPソケットでつなぐことになるので明示的に -h 127.0.0.1
を指定する必要があります。
Windowsの場合(PuTTY使う例)
Windows の PuTTY でもSSHトンネリングが出来ます。
先ほどの構成と同じ場合の PuTTY の設定方法です。つなぐ画面の 接続 -> SSH -> トンネル という項目を設定します。以下のように、源ポート(自分のマシンでLISTENする任意のポート)と送り先ポート(SSHログイン先から見たホストとポート)を設定します。
この状態で普通にSSHでつなぐときと同じようにホスト名いれて、ユーザ、パスワードを入力すればSSHでログインされます。先ほどと同様に、この状態でトンネルが出来ているので、PuTTY は閉じないでそのままにしておきます。
あとはMySQLクライアントで127.0.0.1の19000番ポートへつなぎに行けばつながります。
DBやアプリケーションサーバは踏み台サーバ経由でアクセスすることが多いので、SSHトンネリングの設定を .ssh/config
に書いておくと便利なことも多いかもしれません。