ローカルネットワーク間のSSHログインにおけるポートフォワードの使い方を紹介します!

ポートフォワードとは?
SSHのポートフォワード機能とは特定のポートのデータ通信を他のポートへ転送することです。この機能によってVPNが設置されていない内部ネットワーク間での通信などが可能になります。なお今回は公開鍵認証でクライアントの認証をします。
ここで出てくる端末のアドレスはグローバルやプライベートアドレスを問わず端末AならaddrA, 端末XならaddrXとします。
ポート番号はそのプロトコルでデフォルトのポート番号を使い、ユーザーが指定するポート番号は他のサービスと重複しないものを選び、この説明では5桁の番号を使います。
ローカルポートフォワードを使ってみる
ここでローカル端末A(ネットワークには繋がり、AUserの秘密鍵を持っている)からAUserとしてインターネットで到達可能な端末X(端末Xではユーザー名AUserとAUserの公開鍵が登録してある)があります。
またXと同じネットワークで端末Aからインターネットで直接アクセスできない端末Yがあります。端末Aから端末Yにポートフォワードを使ってログインすることを考えます。
SSHで端末Yにログインする
端末Aから端末XにSSHログインする
1
|
$ ssh AUser@addrX -i (AUserの秘密鍵) #端末Xにログインされます
|
端末Aから端末Y(ユーザー名AUserとAUserの公開鍵が登録されていてSSHサーバが稼働している)にログインする
1
2
|
$ ssh -L 10022:addrY:22 -Nf AUser@addrX -i (AUserの秘密鍵)
#端末Xを経由して端末Yのポート22番と端末Aの10022番が繋がる
|
端末Aから
1
|
<strong><mark>$ ssh AUser:localhost -p 10022 -i (AUserの秘密鍵) #端末YにSSHでログインされます。</mark></strong>
|
端末Aから端末Yに別のユーザーとしてログインする
今度は端末Aから端末Yにユーザー名BUserとしてログインします(端末AはBUserの秘密鍵を持っていて、また端末Yにはユーザー名BUserとBUserの公開鍵も登録されている)。
1
2
|
$ ssh -L 10022:addrY:22 -Nf AUser@addrX -i (AUserの秘密鍵)
#AUserとして端末Xを経由して端末Yのポート22番を端末Aのポート10022にポートフォワードする
|
端末Aから
1
2
|
<strong><mark>$ ssh BUser:localhost:10022 -i (BUserの秘密鍵)
#端末YにBUserとしてログインされる</mark></strong>
|
端末Yから内部ネットワークに公開されているWebコンテンツを見る
端末Aから
1
2
|
$ ssh -L 10080:addrY:80 -N AUser@addrX -i (AUserの秘密鍵)
#端末Xを経由して端末Yの80番ポートを端末Aの10080番ポートにポートフォワードする
|
ブラウザを起動してURL http://127.0.0.1:10080を開きます。なおこの通信においてSSHで暗号化されるのは端末Aと端末Xの間で、ポートフォワードされる端末Xと端末Yの間は暗号化されていません。
端末YのMySQLサーバと通信する
まず端末AにMySQLクライアントがインストールされている必要があります。端末Yで稼働するMySQLサーバでのユーザー名はAUserMy、パスワードはAUserPassとします。
端末Aから
1
2
|
$ ssh -L 33306:addrY:3306 -Nf AUser@addrX -i (AUserの秘密鍵)
#端末Xを経由して端末Yの3306ポートを端末Aの33306ポートにポートフォワードする
|
端末AからMySQLを起動する
1
|
$ mysql -h 127.0.0.1 -P 33306 -u AUserMy -p #AUserPassを入力する
|
端末YのGUI画面を使う(X11フォワーディング)
Linuxなどで使用されているGUI画面を端末Aから使います。
1
2
|
$ ssh -X AUser@addrX -i (AUserの秘密鍵)#端末Xにログインされる
$ firefox & #GUIアプリケーションのコマンドを入力するとGUI画面が使えます
|
WindowsやMac、Linux等で使うことができます。サーバ、クライアントの設定や必要なライブラリなどの準備が必要なので確認してください。
ポートフォワードの実践的な活用方法
ここでは、ローカルネットワーク間のSSHログインにおけるポートフォワードの使い方を説明します。また、それに伴う複数回のSSHログインする際の鍵の管理方法およびダイナミックフォワードについても紹介します。
ここで出てくるAUserはSSHでログインするそれぞれの端末にユーザー名がAUserとして登録されているものとします。
これまでは通信先がネットワークを介して繋がる端末でしたが、今度はポートフォワードを活用してローカルネットワーク内やファイヤーウォールなどによって外部からアクセスできない端末とSSHによって通信します。
ローカルネットワーク間で通信する
SSHクライアントもSSHサーバの属するネットワークもいずれもインターネットからアクセス可能なグローバルIPアドレスを持っていない場合を考えます。ここでインターネット上にグローバルIPアドレスを持つ端末P(中継サーバ)を用意します。
ここで端末Xと端末Yは同一のネットワークで、端末A、端末X、端末Yいずれもインターネットには繋がりますがインターネットからはアクセスできません。SSHのリモートフォワードを使って端末Aから端末Pを経由してさらに端末Xを経由して端末Yにログインします。
リモートフォワーディングとは
まず端末Xから端末Pを繋ぎます。端末Pのポート10022からaddrXへポートフォワードしています。
1
2
|
$ ssh addrP -R 10022:addrX:22
#この箇所は偶然接続がきれた際手動で再接続ができないのでautosshコマンドを導入したほうがよい
|
次に端末Aから端末PにSSHでログインします
1
|
$ ssh addrP
|
ここでログイン中の端末Pから
1
|
$ ssh localhost -p 10022
|
このようにすると端末Pから端末XのSSHサーバにログインすることができます。このようなポートフォワードをリモートフォワードと呼びます。最後に端末XのSSHから端末YのSSHにログインします。
1
|
$ ssh addrY
|
以上のようにして端末Aから端末Pを経由して端末Xから端末YのSSHサーバに順次ログインすることができます。端末P、端末X、 端末YにはSSHサーバが稼働している必要があります。
適切に鍵を配置するには
上の例のように複数回SSHサーバを経由した通信が行われていますが、インターネット上の端末Pに端末Xにログインするための秘密鍵を配置するのはセキュリティー上のリスクがあります。
そこで秘密鍵は端末Aで一括して管理することにします。しかし問題があります。なぜならこのままではログイン先のSSHサーバからでは次のログイン先の秘密鍵が参照できないからです。この問題を解決するため端末Aに置かれた秘密鍵にssh-agentコマンドを実行します。
ssh-agentコマンドで秘密鍵を登録する
端末Aから
1
2
3
4
5
6
|
$ ssh-add (端末Pのログインに必要な秘密鍵) #ssh-agentで鍵の登録をする
$ ssh-add (端末Xのログインに必要な秘密鍵)
$ ssh-add (端末Yのログインに必要な秘密鍵)
#ターミナルを起動する度に登録がリセットされます。永続化するには
$ ssh-add -K (.ssh/・・・・_rsa) # -Kオプションを付けてください
|
端末Pおよび端末XのSSHサーバを設定します。端末Pと端末Xの/etc/ssh/sshd_configファイルの#AllowAgentForwarding yesをコメントアウトします。
Agent Forwardingによってログインする
先程の例では端末Aから
1
2
3
|
$ ssh -A AUser@addrP #端末Pにログインされます
$ ssh -A AUser@localhost -p 10022 #端末Xにログインされます
$ ssh -A AUser@addrY #端末Yにログインされます
|
本来現在ログイン中の端末上に秘密鍵が無い場合は次のSSH接続ができませんがAgent Fowarding機能によって端末Aに置かれた秘密鍵がSSH接続先の端末に転送されます。
ssh-agentによって登録されたSSHの秘密鍵は、ユーザー名と接続するホストに応じて適切な秘密鍵を接続の際に注入します。
コマンドオプションを書かないでSSHを使う
コマンドをSSH接続の度に入力するのは面倒で記述が煩雑になりがちです。SSH接続元の自端末のホームディレクトリ.ssh/configにSSH接続設定を書き込みます。上記の例を示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
Host A
HostName A:addrA
User AUser
ForwardAgent yes
Host P
Hostname P.addrP
User AUser
IdentityFile ~/.ssh/(端末Pでの認証に必要な秘密鍵)
Host X
Hostname X.addrX
User AUser
IdentityFile ~/.ssh/(端末Xでの認証に必要な秘密鍵)
ProxyJump P:10022
Host Y
Hostname Y.addrY
User AUser
IdentityFile ~/.ssh/(端末Yでの認証に必要な秘密鍵)
ProxyJump X
端末Aから
$ ssh Y # <strong><mark>これで端末YとSSH接続される</mark></strong>
|
ダイナミックフォワードとは
これまでに説明したポートフォワードでは、WEBサーバなどに接続する際、ホストが変わるごとにまた新たにポートを割り当てる必要がありました。さらに、サイト内のリンクが絶対パスで書かれていた場合リンク先に移らなかったり不便な点があります。
そこでSOCKSパケットでカプセル化されたパケットをSSHサーバに中継しポートフォワードします。接続先のポートと一対一での通信ではないので接続先のホストやポートが変わってもブラウザなどで普段通りに通信できます。
SSHクライアントをSOCKSプロキシにする
端末Aからインターネットで繋がる端末XとXと同じネットワークでインターネットからはアクセスできない2台の端末Yと端末Zに置かれているWEBコンテンツを閲覧します。端末Aから
1
2
3
4
5
|
<strong><mark>$ ssh -D 1080 -Nf addrX#端末Aのポート1080からaddrXまでSSHで繋がれる</mark></strong>
$ curl --socks5 127.0.0.1:1080 addrY:80 #YのWEBコンテンツを見る
$ curl --socks5 127.0.0.1:1080 addrZ:80 #ZのWEBコンテンツを見る
#ポート番号1080はSOCKS通信を受け入れるデフォルトポートです
|
端末AのブラウザやFTPクライアントのプロキシの設定画面を開きSOCKS HOSTをlocalhostと入力します。またポート番号を1080と入力してプロキシのDSNを使う、をチェックします。
SOCKSでカプセル化された通信
このようにしてブラウザを開くとSOCKSでカプセル化された端末Aからの通信はSSHで端末Xに中継され、内部の端末Yと端末ZのWEBコンテンツをポート番号を追加することなく普段のWEBと同じように閲覧することができます。
また端末Xの属するネットワークで使われているDNSを参照してインターネットに繋げることもできます。
さらに、WEBに限らずファイル転送やメールなど、使用するアプリケーションがSOCKSに対応していればダイナミックフォワードを利用することも可能です。
ダイナミックフォワードを応用する
次は端末Pがインターネットからアクセス可能なグローバルIPアドレスを持っていて、端末Xはローカルネットワーク内でインターネットには繋がりますが、インターネットからはアクセスできません。
端末Xと同じネットワークに存在する端末Yと端末ZのWEBコンテンツを端末Pから見ることを考えます。端末Pと端末XにはSSHサーバが稼働しています。
端末PからSOCKSパケットを端末XまでSSH接続させ前項のダイナミックフォワーディングを実現します。
ローカルネットワーク上のサーバをダイナミックフォワードで繋ぐ
まず端末Xから
1
2
3
|
$ (auto)ssh -R 10022:localhost:10088 addrP
#端末Pのポート10022と端末Xのポート10088を繋ぎます。
$ ssh -D 10088 localhost#端末Xの10088ポートとSSHサーバポートが繋がれます
|
端末Pから
1
2
|
$ curl --socks5 127.0.0.1:10022 addrY:80
$ curl --socks5 127.0.0.1:10022 addrZ:80
|
アプリケーションが対応していればSOCKSプロキシを設定することによりブラウザなどで普段と同じように通信ができます。
端末PのブラウザやFTPクライアントなどのプロキシの設定画面を開きSOCKS HOSTをlocalhostと入力します。またポート番号を10022と入力してプロキシのDSNを使うをチェックします。
まとめ
本記事に出てきたコマンド以外にも多数のSSHコマンドが存在する為、自分の端末のman ssh・・コマンドをお読みください(和訳は相当に古いので)。
SSHは便利で強力ですが、大規模で継続的なセキュリティー対策が求められる場合はVPNの利用を検討することをおすすめします。
ネプラス株式会社はサービス開始から10年以上
『エンジニアの生涯価値の向上』をミッションに掲げ、
多くのインフラエンジニア・ネットワークエンジニアの就業を支援してきました。
ネプラス株式会社はこんな会社です
秋葉原オフィスにはネプラス株式会社をはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
インフラ業界に特化
ネットワーク・サーバー・データベース等、ITインフラ業界に特化。Cisco Systemsプレミアパートナーをはじめ各種ベンダーのパートナー企業です。
業界を知り尽くしているからこそ大手の取引先企業、経験豊富なエンジニアに選ばれています。
-
正社員なのにフリーランスのような働き方
正社員の方でも希望を聞いたうえでプロジェクトをアサインさせていただいており、フリーランスのような働き方が可能。帰社日もありません。
プロジェクト終了後もすぐに次の案件をご紹介させていただきますのでご安心ください。
-
大手直取引の高額案件
案件のほとんどが大手SIerやエンドユーザーからの直取引のためエンジニアの皆様へに高く還元できています。
Ciscoをはじめ、Juniper、Azure、Linux、AWS等インフラに特化した常時300件以上の案件があります。
-
スキルアップ支援
不要なコストを削減し、その分エンジニアの方へのスキルアップ支援(ネットワーク機器貸出、合格時の受験費用支給など)や給与で還元しています。
受験費用例)CCNP,CCIE:6-20万円、JNCIS:3-4万円、AWS:1-3万円など
※業務に関連する一定の資格のみ。各種条件がありますので詳しくは担当者へにお尋ねください。
-
現給与を保証します!※
前職の給与保証しており、昨年度は100%の方が給与アップを実現。収入面の不安がある方でも安心して入社していただけます。
※適用にはインフラエンジニアの業務経験1年以上、等一定の条件がございます。
-
インセンティブ制度
ネットワーク機器の販売・レンタル事業等、売上に貢献いただいた方にはインセンティブをお支払いしています。
取引先企業とエンジニア側、双方にメリットがあり大変好評をいただいています。
-
社会保険・福利厚生
社員の方は、社会保険を完備。健康保険は業界内で最も評価の高い「関東ITソフトウェア健康保険組合」です。
さらに様々なサービスをお得に利用できるベネフィットステーションにも加入いただきます。
-
東証プライム上場企業グループ
ネプラスは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
ネプラス株式会社に興味を持った方へ
ネプラス株式会社では、インフラエンジニアを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
オンライン面接も随時受付中。ぜひお気軽にご応募ください。

