マルチプルなSSHポートフォワーディングの設定
世はまさにVPNトンネリング時代1、であるが、マジメにVPN張るのは大変だったり、SSHでトンネリングするのもちょっと面倒だったり、VPN張るまでも無く…といったケースは多々ある。実際VPN張るのはめんどくさい2。
いわゆるプロキシーサーバーを立てるのも一つではあるが、HTTPプロキシーでは汎用性に心許なく、SOCKS5プロキシーについてはサポートしているかどうか悩ましく、プロキシーサーバーまでの通信が保護されてるか不明だし、アプリの設定が大味3だったりすることもあって悩ましいところ。
そこで今回、SSHはSSHでもポートフォワーディングを駆使することで手軽にトンネリングしようという話である。
この手の話題は調べればいくらでも出てくるのであるが、ユースケースをはっきりさせた上で、最新のSSHクライアント事情に合わせて解説する。
想定環境
- クライアントOS: Windows10 バージョン 20045
- SSHクライアント: OpenSSH(7.7p1)・PuTTY
- クライアントアプリ: Firefox(80.0.1で検証)・リモートデスクトップ
※OpenSSHの有効化およびPuTTYのインストール方法についてはここでは取り扱わない。
Windows上で動く他のSSHクライアントであれば、設定の詳細はともかく、おおよその設定については参考にはなると思う。
まずはOpenSSHでポートフォワーディングしてみる
動作原理を確認するため、下記コマンドを実行してみる。
ssh -L 127.1.1.1:3389:リモデサーバー:3389 -D 127.1.1.1:1080 -l アカウント名 踏み台サーバー
- これで【クライアント】から【踏み台サーバー】までの間はSSHにより通信保護される。
- どのような通信が保護されるかというと、以下の通りである。
-
-L
オプション:127.1.1.1:3389
に接続したリモートデスクトップクライアント -
-D
オプション:127.1.1.1:1080
をSOCKS5プロキシーに指定したブラウザ(アプリ)
-
リモートデスクトップでつないでみる
ここでリモートデスクトップを立ち上げて「コンピュータ」に 127.1.1.1
を指定すれば、踏み台サーバーから「リモデサーバー」に接続(ポートフォワード)してくれる。
「踏み台サーバー」を基準に「リモデサーバー」につなぐので以下の点がメリットとなる。
- 踏み台サーバーへの認証はSSH認証6で担保。
- 踏み台サーバーを起点とする内部ネットワーク(イントラ等)への接続が可能。
- アクセス元IPが踏み台サーバーに絞れる。
- 「リモデサーバー」の接続先ポートが標準(3389)外のポート番号でもクライアント側で吸収できる。
デメリットはSSHのオプションが煩雑であることであるが、これについては後述する。
ブラウザでつないでみる
さてブラウザ(Firefox)の場合、メニューバーから「ツール」→「オプション」を選んで「一般」の画面の一番下にある「ネットワーク設定」の「接続設定」ボタンを押す。

ここで下記の設定を行うと、踏み台サーバーから任意のサイトに対し任意のプロトコルでアクセスするようになる。
インターネット接続に使用するプロキシーの設定 | SOCKSホスト | ポート |
---|---|---|
●手動でプロキシーを設定する |
127.1.1.1 |
1080 |
-
SOCKS v5
にチェックが入ってること7。 -
SOCKS v5を使用するときはDNSもプロキシーを使用する
のチェック状態はあまり問わない。 - プロキシーを通さずに接続したいサイトがあれば
プロキシーなしで接続
に当該ドメインを記述すること。
設定の要点1
今回例として 127.1.1.1
を指定したが、このIPは 127.0.0.1
以外の 127.0.0.0/8
の範疇で指定が可能で、3オクテット分の自由度がある。
この3オクテットを使って接続先サーバーの識別が可能である。
これは特にHostsファイル8に記載したときに効果的に利用できる。
なお 127.0.0.1
の指定は可能ではあるがお勧めしない。使用したいポートがいつ、どこで他者が使われるか分からないためである。
ある時は問題なかった操作が、別のタイミングで問題を起こす(動作しない等)ことがあるので、127.0.0.1
の使用はお勧めしない。
また当然 127.0.0.0
も 127.255.255.255
も使用できない9。
設定の要点2
-L
および -D
オプションは複数指定が可能なので、単一の踏み台サーバーから接続できる、複数の接続先サーバーへの設定が行える。
つまり複数台の接続先設定を一回の設定でまかなえることを意味する。
逆に複数の接続先サーバーに対して、それぞれ踏み台サーバーが異なる場合は、それぞれの踏み台サーバーに接続する必要があるため、一回の設定ではまかなえない。
オプションを最適化してみる
というのも、先の手順だと普通にサーバーにログインしてしまうので、シェルオペレーションできないようにしたい。そういう時は -N
オプションを指定する。
-
-N
: リモートコマンドを開始しない(ポート転送のみ運用向け)、-T
オプションを暗黙に指定している -
-T
: 疑似端末を確保しない(バッチ処理向け)
exit
では終了できなくなるので、CTRL-C
10で停止させることになる。exit
で終了させたい向きもあるかもしれないが、間違ってコピペしてしまったり、別のターミナルのつもりでコマンドを実行してしまう等の事故を考慮すると、このオプションの指定を推奨するものである。
またこの辺りをまとめてバッチファイルにしてしまうのがよろしいと思われ。
PuTTYでポートフォワーディングしてみる
こっちは実践と設定がほぼイコールなので、その前提で先の例を踏襲して説明する。
PuTTYを立ち上げると、設定画面が表示される。

【接続】→【SSH】→【トンネル】より、一行一行、下記の設定を「追加」する。
源ポート | 送り先ポート | 下記にチェックを入れる |
---|---|---|
127.1.1.1:1080 |
(記述しない) | ダイナミックポート |
127.1.1.1:3389 |
リモデサーバー:3389 |
ローカル |

今回、以下の2つの設定は無関係なのでスルーしてよい。
- 「ローカルポートは他のホストからの情報を受け入れる」
- 「リモートポートも同様(SSH-2のみ)」
この後【セッション】に戻って、「ホスト名」を入力、接続タイプに「SSH」にチェックを入れて「開く」ボタンを押せば、ポートフォワーディング開始となる。
オプションの最適化と設定の保存
先の説明と同じく、PuTTYでもいくつかの設定すべき/した方がよいオプションがある。
- 【接続】
- 【データ】
- 「自動ログインのユーザー名」: OpenSSHではローカルパート11のないしは-l
オプションでの指定に相当する。。 - 【SSH】
- 「シェルやコマンドを開始しない」: OpenSSHでは-N
オプションに相当する設定である(-T
オプション相当とは独立)。
- 【TTY】
- 「疑似端末を確保しない」: OpenSSHでは-T
オプションに相当する設定である。
- 【データ】
- 【ウィンドウ】 ※画面の隅に置いておくサイズで
- 「桁」: 個人的には「
80
」辺りに設定するの推奨 - 「業」: 個人的には「
4
」辺りに設定するのを推奨 - 「スクロールバックの行数」: 個人的には「
0
」辺りに設定するのを推奨 - 【外観】
- 「フォントの設定」→「変更」ボタンを押す: サイズを8~10ポイント程度の小さめのフォントを選択する。
- 「桁」: 個人的には「
他にも設定した方がよい設定があるが、運用(SSH鍵認証等)と密接に絡むパラメータなので、ここでは取り上げない。
上記設定がなされた後、【セッション】にて「セッション一覧」の下のボックス(上側)にセッション名(たとえば ssh-port-forward
など)を入れて「保存」ボタンを押す。
OpenSSHのポートフォワーディング設定
OpenSSHの場合、オプションを保存しておこうと思ったら、バッチファイルを作成することになるが、一応設定を保存しておくことが可能である。
コマンドプロンプトを立ち上げた際のホームディレクトリ(C:\Users\アカウント名
)の下に .ssh
ディレクトリを作成(事前に作成済みの場合もある)、config
という名前のテキストファイル(拡張子無し)を作成する。取り急ぎ先の例にならい、下記の設定を行う。
Host ssh-port-forwarding
HostName 踏み台サーバー
User アカウント名
DynamicForward 127.1.1.1:1080
LocalForward 127.1.1.1:3389 リモデサーバー:3389
ExitOnForwardFailure yes
これで ssh -N ssh-port-forwarding
と実行するだけで、ポートフォワードしてくれるようになる。また終了は CTRL-C
10で停止することになる。
-
HostName
、User
: 踏み台サーバーのサーバー名とアカウントの指定 -
DynamicForward
:-D
オプション相当 -
LocalForward
:-L
オプション相当 -
ExitOnForwardFailure
: 指定された-D
、-L
、-R
、-w
オプションのどれかでセットアップに失敗すると終了する(起動しない)
なお -N
オプションは特別で、コマンドラインでしか指定できない。
-T
オプション相当であるところの RequestTTY no
設定は -N
オプションの指定があるので無意味である12
よくある質問とその答え
Q.多段ポートフォワードすれば一個の設定で行けるじゃないのか!
A.行けないことは無いですが、まずは基本を抑えておきましょう。そのうちここでも解説するかもしれない。
あと必ず前段の踏み台サーバーを経由することが必須なので、その分の帯域とレイテンシーにペナルティがかかります。
場合によっては、そういう深い構成のネットワークを相手にする場合もあるので、多段せざるをえない場合もあります。
言い直すと、直列多段のユースケースはありますが、並列多段を直列化するのはお勧めしません。
Q.第三者サーバーto第三者サーバーの設定方法は?
A.基本的なロジックは同じなのですが、本件での位置付けとしては別物なので、ここでは取り扱いません。
Q.-R
オプションあるいは RemoteForward
って何だ?
A.-L
オプションあるいは LocalForward
の逆向きの設定です。何が逆向きかというと、下図のようにリモート側の何かクライアントが、ローカル側の何かサービスへアクセスする、といった向きです。
SSHの接続する方向性は変わりありませんので実にやっかいです。
ユースケースが限られる、というかこれを使いたい状況というのが説明しにくいのと、実用する場合には、更に注意点(GatewayPorts
設定)があるので、ここでは取り扱いません。
いずれにせよ下記のようなユースケースでは欲しいと思う状況は一般に発生しないです。ゼロとは言わないのでこのオプションが存在するわけですが、「そうせざるを得ない」という意味で極めて特殊です。

Q.HTTPプロキシーとSOCK5プロキシーで何が違うんだ?
A.今時なんでも(VPNですら)HTTP(HTTPS)で通信するのでどっちでも良いと言えばどっちも違いは無いように見えないこともないですが、プロトコル汎用プロキシーとして設計されているSOCKS5の場合、UDPすらプロキシーできたりするので、そこの部分だけ違いがあると言えば違いがあるかもしれません。
Q.-L
オプションと -D
オプションの使い分けは?
アプリの対応状況によって使い分けます。
SSH自体にはHTTPプロキシー機能が無いので、SOCK5プロキシーが使えるアプリでは -D
オプションを使用(指定)します。宛先を良きに計らってくれるため、使い勝手が良いです。
接続先の指定しかできないアプリでは、-L
オプションにより擬似的(127.x.x.x:yyyy
)に宛先を乗っ取ってやる必要があります。
参考文献
-
2020年09月現在。2020年初頭のSARSコロナウィルス2禍によるリモートワーク推奨にともなう。 ↩
-
ルーティングをどう設定するかの問題が…。頭空っぽに設定するなら、そう面倒では無い。 ↩
-
プロキシーサーバーを指定しての「オン」か「オフ」かしかなく4、オン/オフするのもメニューの深いところにあったりするなど。 ↩
-
接続先に応じて複数のプロキシーサーバーを指定する、または指定しないなどのファインチューニングする機能が無かったりする。 ↩
-
原理的にはWindows7から実績あり。Windows7には標準でOpenSSHが無いので話を割り引く必要がある。 ↩
-
鍵認証またはパスワード認証等。鍵認証のみに制限することを勧める。 ↩
-
SOCKS5の時点で前世紀のプロトコルなのにSOCKS4は無いわ~。 ↩
-
具体的には
C:\Windows\System32\drivers\etc\hosts
というファイル。 ↩ -
ネットワークアドレスとブロードキャストアドレス。 ↩
-
コントロールキーを押しながら「
c
」を押す。「C
」でもかまわないが、大文字のC
であることが必須の場合CTRL-SHIFT-C
という表現になる(とは言え、一般的な表現ではない)。 ↩ ↩2 -
「ローカルパート
@
ホスト名」と指定した場合の@
より前の文字列のこと ↩ -
設定しても問題は無い。
RequestTTY yes
といった矛盾した設定の挙動は調べてない。調べる気も無い。 ↩