犬でも分かる sshポートフォワーディング2: リバーストンネル

IT

sshのポートフォーワーディングは、ssh接続のトンネルを作成して、そのトンネルをssh以外の通信(ssh以外のport番号)に利用するという手法です(以前、こちらの記事で紹介しました)。sshのポートフォーワーディングでは、逆方向の通信を可能にするトンネルを作成することもできて、これがリバーストンネルです。今回は、リバーストンネルを実際に試してみたいと思います。

リバーストンネルはどのようなときに使う?

例えば、会社の中にあるホストlhostからインターネット上のホストrhostにssh接続が可能だとします(上の図)。会社内のFirewallは外に接続しにいくsshの通信(port=22)を許可しています。

一方で、この例において、インターネット上のホストrhostから会社内のホストlhostにはssh接続ができません。理由は、lhostのIPアドレスがプライベートなので、rhost側からは直接アクセスできないというのと、会社のFirewallが外から接続されてくるsshの通信を許可していないことのほうが多いからです。

でも、なんらかの理由でrhostからlhostにsshログインしたいことって、あると思います。
※以下は技術的な観点でできる/できないの話をします。セキュリティの観点でできる/できないは別の話ですし、実際にやる場合は、目的を明確にした上で、許可が必要となると考えています。

リバーストンネルの作り方

以下の図は、リバーストンネルのイメージです。

会社の中にあるホストlhostからインターネット上のホストrhostにssh接続が可能なので、sshポートフォーワーディングのトンネルを作成するのですが、このときトンネルの接続を逆方向で作成します(リバーストンネル)。

この例では、

ssh -R 10022:localhost:22 rhost

という引数を指定してsshコマンドを実行しています。
rhostは接続先のリモートホストです。
-R がリバーストンネルの作成を指示していて、この例では
「rhostのport 10022をlocalhost(クライアント側)のport 22に接続する」
トンネルを作成するという意味になります。

テストしてみる

インターネット上に適切なホストがないので、テストはおうちの中の2台のホスト base0 と base1 で実験します。

① base0からbase1にssh接続して、リバーストンネルを作成する

[root@base0 ~]# ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -R 10022:localhost:22 base1
root@base1's password: (base1のパスワードを入力)

Last login: Sun Jul 6 08:17:39 2025 from 192.168.2.200
[root@base1 ~]#

-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null」というオプションは、リバーストンネルとは関係ありません。~/.ssh/known_hosts にホストリストを記録するのが面倒なので、いつも付けているオプションです。

② リバーストンネル経由でbase1からbase0にsshログインする

①の操作で、base1のport 10022がbase0のport 22とリバーストンネルで接続されたので、base1からは、localhostのport 10022に対してログインします。

[root@base1 ~]# ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 10022 localhost
root@localhost's password:
(base0のパスワードを入力)

Last login: Sun Jul 6 08:21:43 2025
[root@base0 ~]#

はい、成功しましたね。

リバーストンネルを作成したsshプロセスを常駐させる

リバーストンネルを作成したsshプロセスを常駐するには、以下の2つのオプションを追加します。

オプション意味
-fsshのプロセスをbackgroundで実行する。
-Nsshサーバ側でコマンドを実行しない。

実際に実行すると、base1にsshログインすることはなく、sshのプロセスだけ実行されています。

[root@base0 ~]# ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -f -N -R 10022:localhost:22 base1
root@base1's password: (base1のパスワードを入力)
[root@base0 ~]# ps -ef | grep ssh | grep '10022:localhost:22'

root 548307 1 0 08:38 ? 00:00:00 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -f -N -R 10022:localhost:22 base1

この例では、psコマンドでsshトンネルのプロセスを確認しています。sshトンネルを削除する場合は、該当するsshのプロセスをkillしましょう(この例では pid 54307 です)。

広告主へのリンク

おうちでLinuxやるなら、ミニPCがちょうど良いです(私はこの3台を使っています)。

このブログにおける関連リンク

パスワード無しでsshするための設定
犬でも分かる sshポートフォワーディング
犬でも分かるsshのProxyJump

コメント

タイトルとURLをコピーしました