SSHポートフォワード:OpenSSH の -L と -R オプションの動作を図解

SSHのポートフォワード(トンネリング)に関してはほかのサイトでもたくさん紹介されています。しかし、Windows で TeraTerm や PuTTY などの GUI を用いた方法が紹介されているだけだったり、OpenSSH 等のコマンドラインを利用していても -L(ローカル) か -R(リモート) どちらか片方だけの説明だったり と、ローカルポートフォワード と リモートポートフォワード を比較説明しているサイトは、少ないように感じました。

そこで今回は、Windows 10 にも標準搭載となった OpenSSH の -L(ローカル) と -R(リモート) のオプションについて説明します。(実際には -L だけ覚えておけば大丈夫です)。

スポンサーリンク

SSHポートフォワードについて

このサイトを訪問されている方はすでに、SSHポートフォワードの概要については理解されていると思いますが、導入として SSHポートフォワードについてすこしだけ触れておきます。(すでにご存じの方は読み飛ばしてください。)

SSHポートフォワードとは、以下のように SSHコネクション上で、別のサービス(別の端末の別のポート)へ通信を転送(フォワーディング/トンネリング)することです。

具体的なイメージとしては、以下のようにSSHのコネクションを通して、Web や RDP(リモートデスクトップ)へアクセスできるようになります。フォワーディングされた通信(SSHコネクション上)は暗号化されているため、http のサービスにアクセスしていても、SSHコネクション上(緑色の線)では盗聴の危険はありません。

SSHフォワーディング:

フォワーディング(トンネリング)対象となるサービスが暗号化されていない場合は、SSHコネクション外では盗聴の可能性があります。

そしてSSHポートフォワードには、「ローカルポートフォワード」と「リモートポートフォワード」があります。以下では、実際のコマンドを利用して、ローカルポートフォワードとリモートポートフォワードについて、説明していきます。

本サイトでの前提

ローカルポートフォワードとリモートポートフォワードを説明するにあたり、以下のように用語を定義しておきます。以降、文中や図中で使われますので意識しておいてください。また、リモートポートフォワードは、リバースポートフォワードと呼ばれることもあるようですが、私は openssh の man の該当箇所に reverse という言葉を見つけられなかったため、リモートポートフォワードと呼んでいます。

サービス:
最終的なサービスを提供する端末をさします。Webサーバー(80/443)や、リモートデスクトップ(RDP)サーバー(3389)のことです。

クライアント:
サービスを利用するクライアントをさします (SSHのクライアントではないことに注意)。Webブラウザやリモートデスクトップ(RDP)クライアントのことです。

SSHサーバー:
踏み台となるSSHのサーバーのことをさします。

SSHクライアント:
踏み台となるSSHサーバーに対し、SSHコネクションを開始するクライアントのことをさします。
なお以降、ローカルポートフォワードはローカルフォワード、リモートポートフォワードはリモートフォワードと呼びます。

-L オプション:ローカルフォワード

SSHクライアント側にサービスへの転送ポートを開きます。SSHサーバーはサービスへ通信をフォワードします。クライアントが、SSHクライアントの転送ポートに対しアクセスをすることで、サービスが利用可能になります。

コマンド:

ssh (SSHサーバのアドレス) -L (SSHクライアントで待ち受けるポート):(サービスのIPアドレス):(サービスのポート番号)
ssh 192.168.1.10 -L 13389:192.168.1.20:3389

TeraTerm:
TeraTermで実行する場合は以下のように設定します。

どのように使うのか

インターネットから宅内(社内)に入ることを想定すると以下のようになります。その場合、通常はルータのアドレスが外に見えていて、内部はNAT(NAPT)されています。そのため、インターネット上から宅内の SSHサーバーに接続できるように、ルータに対してSSHサーバーへポートフォワードする設定(図中ピンク色の線)が必要です。

インターネット上のクライアントとなる端末で SSHクライアントを起動し、ローカルフォワードを実行します(SSHサーバーに接続します)。

例では、クライアントの localhost:13389 へのアクセスが、192.168.1.20:3389 へフォワードされます。これにより、インターネット上のクライアントから、宅内のPCへリモートデスクトップ接続ができるようになります。

-R オプション:リモートフォワード

SSHサーバー側にサービスへの転送ポートを開きます。SSHクライアントはサービスが動いているサーバーから起動します。クライアントが、SSHサーバーの転送ポートに対しアクセスをすることで、サービスが利用可能になります。


コマンド:

ssh (SSH サーバのアドレス) -R (SSHサーバのアドレス):(SSH サーバで待ち受けるポート):(サービスのポート番号)
ssh 192.168.1.10 -R 192.168.1.10:13389:localhost:3389

TeraTerm:
TeraTermで実行する場合は以下のように設定します。(未検証)

どのように使うのか

-R オプションに関して、この後紹介する -g オプションを使い、SSHサーバー側からサービスに対して -L オプションで SSH接続を実施すると同じことができるため、私は利用していません。

あえて -L との違いをつけようとすると、SSHサーバーがインターネット上にある場合です。この場合、-L の際に行ったルータのポートフォワード設定は不要になります。ただし、クライアントとSSHサーバー間の通信はSSHコネクションではなくフォワードするアプリケーションの通信がそのまま流れますので、アプリケーションレベルでの暗号化が必要です

localhost(127.0.0.1)以外で待ち受けするには、SSHサーバーの設定(sshd_config)で GatewayPorts を yes に設定しておく必要があります。

コマンド利用時便利なオプション

OpenSSH で、ポートフォワードを行いたいだけの場合、よく使う便利なコマンドがあります。
-f :バックグラウンド実行のオプション
-N :何もコマンドを実行しません(ポートフォワード時に有用)
-g :ローカルフォワードの待ち受けを他の端末へ公開します。(Gatewayモード)つまり、localhost(127.0.0.1)で待ち受けるのではなく、その他のIPアドレス(0.0.0.0)で待ち受けるようになります。

OpenSSH の manpage 一部抜粋:

-f Requests ssh to go to background just before command execution.
This is useful if ssh is going to ask for passwords or
passphrases, but the user wants it in the background. This
implies -n. The recommended way to start X11 programs at a
remote site is with something like ssh -f host xterm.

If the ExitOnForwardFailure configuration option is set to “yes”,
then a client started with -f will wait for all remote port for‐
wards to be successfully established before placing itself in the
background.

-N Do not execute a remote command. This is useful for just for‐
warding ports.

-g Allows remote hosts to connect to local forwarded ports. If used
on a multiplexed connection, then this option must be specified
on the master process.