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つのオプションを追加します。
| オプション | 意味 |
| -f | sshのプロセスをbackgroundで実行する。 |
| -N | sshサーバ側でコマンドを実行しない。 |
実際に実行すると、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



コメント