sshコマンドのポートフォワーディングで安全に接続する方法|-L・-R・-Dオプションの使い分け

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, ネットワーク > sshコマンドのポートフォワーディングで安全に接続する方法|-L・-R・-Dオプションの使い分け
「社内のDBにSSHサーバー経由でしかアクセスできない…」
「本番サーバーで動くWebアプリをローカルブラウザで確認したい…」

こうした場面で威力を発揮するのが、sshコマンドのポートフォワーディングです。暗号化されたSSHトンネルを通じて、直接アクセスできないサーバーやポートへ安全に接続できます。

この記事では、ローカル転送(-L)・リモート転送(-R)・ダイナミック転送(-D)の3種類を、RHEL 9.4 / Ubuntu 24.04 LTSで動作確認した実行例付きで解説します。踏み台サーバー経由のDB接続からSOCKSプロキシ設定まで、一気に理解できます。

この記事のポイント

・ssh -L でローカルポートをリモートサーバーへ安全に転送できる
・ssh -R でリモート側から手元のポートを外部へ公開できる
・ssh -D でSOCKSプロキシを立ち上げ全通信をトンネリングできる
・~/.ssh/config に書けばオプション省略で毎回の打ち込みが不要


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

SSHポートフォワーディングとは何か

SSHポートフォワーディング(SSHトンネリング)とは、SSHの暗号化通信路を使って任意のポートへの通信を転送する機能です。

たとえば社内ネットワーク内のMySQLサーバー(外部から直接アクセス不可)へ、踏み台となるSSHサーバー経由で安全に接続できます。通信はSSHが暗号化するため、平文でパケットが流れる心配がありません。

ポートフォワーディングには大きく3種類あります。

ローカルポートフォワーディング(-L):手元のポートをリモートへ転送。踏み台経由でDB・Webアプリへ接続するときに使う
リモートポートフォワーディング(-R):リモートのポートを手元へ転送。外部からアクセスできない手元サービスを一時公開するときに使う
ダイナミックポートフォワーディング(-D):SOCKSプロキシとして機能。特定ポートではなく全通信をトンネル経由にしたいときに使う

ローカルポートフォワーディング(-L)の使い方

ローカルポートフォワーディングは、手元(クライアント)の指定ポートをSSHサーバー経由で別ホストのポートへ転送します。踏み台サーバー越しに内部ネットワークのホストへアクセスするときに最も多用します。

1. 基本構文

# 書式 ssh -L [ローカルポート]:[転送先ホスト]:[転送先ポート] [SSHユーザー@SSHサーバー] # 例: 踏み台サーバー bastion.example.com 経由で内部DB(192.168.10.20:3306)へ接続 ssh -L 13306:192.168.10.20:3306 admin@bastion.example.com

上記を実行すると、手元の13306番ポートへの接続がSSHサーバーを経由して192.168.10.20:3306へ転送されます。別ターミナルで以下を実行すれば、MySQLクライアントから接続できます。

# ローカルの13306番ポート経由でMySQLへ接続 mysql -h 127.0.0.1 -P 13306 -u dbuser -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 48 Server version: 8.0.36

2. トンネルが開通しているか確認する

ssコマンドでLISTENしているポートを確認します。

$ ss -tlnp | grep 13306 LISTEN 0 128 127.0.0.1:13306 0.0.0.0:* users:(("ssh",pid=12847,fd=5))

127.0.0.1:13306 がLISTEN状態であれば、トンネルが正しく開通しています。Linux ポート確認の全コマンドもあわせて参照してください。

3. バックグラウンドで起動する

ターミナルを占有させたくない場合は -fN オプションを組み合わせます。

# -f: バックグラウンドへ移行 -N: リモートコマンド実行なし(トンネルのみ) ssh -fNL 13306:192.168.10.20:3306 admin@bastion.example.com # 切断するには対象プロセスをkillする ps aux | grep ssh kill [pid]

リモートポートフォワーディング(-R)の使い方

リモートポートフォワーディングは、SSHサーバー側のポートを手元(クライアント)のポートへ転送します。外部からアクセスできない手元のサービスをリモートサーバー経由で一時的に公開したいときに使います。

1. 基本構文

# 書式 ssh -R [リモートポート]:[転送先ホスト]:[転送先ポート] [SSHユーザー@SSHサーバー] # 例: リモートサーバーの18080番ポートを手元のlocalhost:8080へ転送 ssh -R 18080:localhost:8080 admin@public-server.example.com

これを実行すると、public-server.example.comの18080番ポートへのアクセスが、SSHクライアント(手元)の8080番ポートへ転送されます。手元で開発中のWebアプリをチームに一時公開したい場面で重宝します。

2. GatewayPorts の設定

デフォルトでは、リモートポートフォワーディングは127.0.0.1のみにバインドされます。外部からリモートサーバーのIPアドレス経由でアクセスしたい場合は、SSHサーバー側の /etc/ssh/sshd_config に以下の設定が必要です。

# /etc/ssh/sshd_config に追記 GatewayPorts yes # 設定を反映する systemctl restart sshd

注意:GatewayPorts yes は外部からのアクセスを許可します。セキュリティリスクを十分に考慮したうえで設定してください。本番環境での常用は推奨しません。

ダイナミックポートフォワーディング(-D)の使い方

ダイナミックポートフォワーディングは、手元にSOCKSプロキシサーバーを立ち上げます。特定のポートではなく、アプリケーションが指定したすべての通信をSSHトンネル経由に流せるのが特徴です。

1. 基本構文

# 書式 ssh -D [ローカルSOCKSポート] [SSHユーザー@SSHサーバー] # 例: localhost:1080 にSOCKSプロキシをバックグラウンドで起動 ssh -fND 1080 admin@bastion.example.com

起動後、ブラウザや curl のプロキシ設定に SOCKS5://127.0.0.1:1080 を指定することで、すべての通信をSSHトンネル経由にできます。

# curlでSOCKSプロキシ経由にアクセスする例 curl --socks5 127.0.0.1:1080 http://internal-web.example.com/ # Firefoxの場合: 設定 → ネットワーク設定 → 手動プロキシ # SOCKSホスト: 127.0.0.1 ポート: 1080 SOCKS v5 を選択

~/.ssh/config で設定を省力化する

毎回長いオプションを入力する手間は、~/.ssh/config に記述することで省略できます。設定ファイルにまとめておけば、トンネル名を指定するだけで起動できます。

# ~/.ssh/config の記述例 # 踏み台サーバーの基本設定 Host bastion HostName bastion.example.com User admin IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 ServerAliveCountMax 3 # DBへのローカルポートフォワーディングをまとめて設定 Host db-tunnel HostName bastion.example.com User admin IdentityFile ~/.ssh/id_ed25519 LocalForward 13306 192.168.10.20:3306 LocalForward 15432 192.168.10.21:5432

設定後は以下のコマンドだけで複数のトンネルを一度に張れます。

# db-tunnel の設定でトンネルをバックグラウンド起動 ssh -fN db-tunnel

ServerAliveInterval と ServerAliveCountMax を指定すると、アイドル時間が長くなってもSSH接続が切れにくくなります。長時間使うトンネルには必ず設定しておきましょう。

トラブルシュート・エラー対処

「channel 2: open failed: connect failed」が出た時の対処法

このエラーはSSHサーバーから転送先ホストへの接続に失敗したことを示します。

・転送先ホスト(例: 192.168.10.20)が稼働しているか確認する
・転送先ポート(例: 3306)がListenしているか、SSHサーバー上でssコマンドで確認する
・SSHサーバーから転送先ホストへの経路(ファイアウォール・セキュリティグループ)を確認する

接続先ホスト名が正しく解決されているかどうかは、dig コマンドで DNS を調べることで確認できます。

「AllowTcpForwarding no」で転送が拒否される場合

SSHサーバー側の /etc/ssh/sshd_config でポートフォワーディングが無効になっている場合があります。

# 設定を確認 grep AllowTcpForwarding /etc/ssh/sshd_config # yes に変更して反映 AllowTcpForwarding yes systemctl restart sshd

「bind: Address already in use」が出た時の対処法

ローカルポートがすでに使用中の場合は、別の番号を指定してください。どのプロセスが使っているかは ss -tlnp コマンドで特定できます。

# 13306番を使っているプロセスを確認 $ ss -tlnp | grep 13306 LISTEN 0 128 127.0.0.1:13306 0.0.0.0:* users:(("ssh",pid=9843,fd=5)) # プロセスIDを確認してkillする kill 9843

接続後すぐに「Connection closed by remote host」が出る場合

SSHの接続が切れると、そのトンネルも切断されます。~/.ssh/config の ServerAliveInterval で定期的にキープアライブパケットを送信するよう設定してください。

# ~/.ssh/config に接続維持設定を追加 Host * ServerAliveInterval 60 ServerAliveCountMax 3

ServerAliveInterval 60 は「60秒ごとにキープアライブを送信」、ServerAliveCountMax 3 は「3回応答なしで切断」の意味です。

本記事のまとめ

やりたいこと コマンド
手元のポートをリモート経由で転送(ローカル) ssh -L 13306:192.168.10.20:3306 user@bastion
バックグラウンドでトンネルを起動(ローカル) ssh -fNL 13306:192.168.10.20:3306 user@bastion
リモートのポートを手元へ転送(リモート) ssh -R 18080:localhost:8080 user@server
SOCKSプロキシをバックグラウンドで起動(ダイナミック) ssh -fND 1080 user@bastion
curlでSOCKSプロキシ経由アクセス curl --socks5 127.0.0.1:1080 http://example.com/
設定ファイルからトンネル起動 ssh -fN db-tunnel
トンネルのListenポートを確認 ss -tlnp | grep [ポート番号]

SSHの基礎から現場で使えるサーバー管理スキルを体系的に学びたいなら

SSHポートフォワーディングを使いこなせると、踏み台構成・安全な通信設計の幅が格段に広がります。
ネットの断片的な情報をつなぎ合わせるだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として15年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。