スキップしてメイン コンテンツに移動

SSH ポートフォワーディング

ポートフォワーディング



ssh hostname] -l [usrname] -N -f [-L

 
オプション



  • -N


    • ログイン時にシェルを立ち上げない


  • -f


    • sshをバックグラウンドで実行する


  • -L


    • ローカルからリモートにフォワーディングする


  • -R


    • リモートからローカルにフォワーディングする


  • -l


    • ユーザIDを指定する




ローカルの8080番をホスト名server.sample.jpのHTTP(80番)にフォワードする.


 
接続の確立.



$ ssh -f -N -L 8080:localhost:80 server.sample.jp -l username

 
上記コマンドのlocalhostは,server.sample.jpが解釈するホスト名であることに注意する.つまり,server.sample.jpから見たlocalhostなので,localhost = server.sample.jpとなる.従って,上記コマンドは,以下のコマンドと同等である.



$ ssh -f -N -L 8080:server.sample.jp:80 server.sample.jp -l username

 
フォワーディングされていることを確認.



$ firefox localhost:8080

ローカルの2222番をゲートウェイgw.sample.jp経由でserver.sample.jpに接続する.



$ ssh -f -N -L 2222:server:22 gw.sample.jp -l username
$ ssh -p 2222 localhost

良くわかる解説















































































































































 
sshの特徴の一つとして,ポートフォワーディングがある.たとえば,次のようにsshを実行する.



% ssh -L X:Remote:Y Remote -l username

 
このあと,別のウィンドウからローカルマシン(Local)のX番ポートに接続すると,sshによって,その通信はすべてRemoteのY番ポートへ転送される.これをポートフォワーディングという.


 
sshでポートフォワーディングができる一番の意義は,ローカルとリモートマシン間の通信がsshが提供するレベルのセキュアなものになるということである.従って,この機能を使ってSMTP(25番)やPOP(110番)と通信すれば,メールの内容を盗み見られるといった心配がなくなる.


 
ただし,FTPに関しては注意が必要である.別紙参照


 
以下,sshポートフォワーディングに関するいくつかの接続例である.各入力例のうち,ユーザ名が同じ場合は -l username は要らない.また,フォワード元のポート番号(矢印が出ているところ)には,root以外のユーザは1024番以下の特権ポートを指定できない.


 
なお,以下の接続例のうち私が実際に試したのは例1と例2くらいである.その他のうち,例2ダッシュと例4と例5は,ネットで調べて見掛けたものである.それ以外の例には根本的な間違いがあるかも知れない.


例その1


 
上で解説されている状態を絵で書くと、下図のようになる.



% ssh -L X:Remote:Y Remote -l username

 
図中,Sはsshdと接続するためにsshクライアントが適当に使っている番号.==== の部分は暗号化されているので,盗聴されても大丈夫.矢印の向きは,ポートにconnectするか,bindしてlistenするかの違い.



+--Local--+ +--Remote---+
| | | |
| +--> S ======> 22 --+ |
| | | | | |
| +--- X Y <--+ |
| | | |
+---------+ +-----------+

例その2


 
ポートフォワードのターゲットポートはRemote以外のマシンのものでもよい.


 
たとえば,



% ssh -L X:Remote_2:Y Remote -l username

 
とする.


 
すると,Remote(ここではsshdが動いている)を経由して,Remote_2への通信が可能になる.


 
図中,SとTは適当にあてがわれる番号である.この方式の場合、暗号化されるのは ==== の部分のみで,Remote:T ---> Y:Remote_2間の通信は暗号化されない.RemoteとRemote_2がファイアーウォールの中にあるなど,通信を盗聴されない環境であることが必要になる.



+--Local--+ +--Remote---+ +-Remote_2-+
| | | | | |
| +--> S ======> 22 -------> T --------> Y |
| | | | | | |
| +--- X | | | |
| | | | | |
+---------+ +-----------+ +----------+

例その2ダッシュ


 
フォワードするポート番号(Y)に22を指定すると,Remoteを介して,Remote_2への直接のsshログインが可能になる.


 
たとえば,



% ssh -L X:Remote_2:22 Remote -l username

 
として,ssh通信を一つ確立した後で,



% ssh -p X localhost -l username

 
とする.


 
この場合は,Remote:T ---> Y:Remote_2 間の通信も暗号化される.というか,XからYまでの通信はsshプロトコルによってすべて暗号化される.図中,Local:SとRemote:22間は2重に暗号化されていることになる.



+--Local--+ +--Remote---+ +-Remote_2-+
| |---------| | | |
| +==> S ======> 22 =======> T ========> 22 |
| U |---------| | | |
| U | | | | |
| +=== X | | | |
| | | | | |
+---------+ +-----------+ +----------+

例その3


 
例2で,さらにRemoteとRemote_2間の通信も暗号化するためには,remote_2上でもsshdを動かし,2段階のポートフォワードをおこなう.


 
たとえば,



% ssh -L X:Remote:Z Remote -l username

 
でログインした後,



% ssh -L Z:Remote_2:Y Remote_2 -l username

 
でさらにログインをする.





 
すると,以下のように,Z番ポートを経由した通信経路が出来上がる.Zの辺りが絵的に少し苦しいけど、それでも通信は暗号化される.



+--Local--+ +--Remote---+ +-Remote_2-+
| | | | | |
| +--> S ======> 22 -+ +-> T ========> 22 --+ |
| | | | | | | | | |
| +--- X | | | | Y <--+ |
| | | +->-+ | | |
+---------+ +-----Z-----+ +----------+

 
あるいは,例2ダッシュの方法を応用してもよい.


 
たとえば,



% ssh -L Z:Remote_2:22 Remote -l username

 
としてssh通信を一つ確立した後で,



% ssh -p Z -L X:Remote_2:Y localhost -l username

 
とする.



+--Local--+ +--Remote--+ +-Remote_2-+
| |---------| | | |
Z ======> S ======> 22 ======> T ========> 22 --+ |
|<---+ |---------| | | | |
| | | | | | | |
| +--- X | | Y <--+ |
| | | | | |
+---------+ +----------+ +----------+

例その4


 
逆に,Remoteのポートをフォワードすることも可能である.これには,-Lオプションの代わりに-Rオプションを用いる.


 
たとえば,



% ssh -R X:Local:Y Remote -l username

 
としてログインする.


 
すると,RemoteのX番ポートがLocalマシンのY番へフォワードされる.



+--Local--+ +--Remote--+
| | | |
| +--- S ======> 22 <-+ |
| | | | | |
| +--> Y X ---+ |
| | | |
+---------+ +----------+

例その5


 
例4において,-Lオプションの時と同様,フォワードする相手先は,必ずしもLocalマシンのポートでなくてもよい.


 
たとえば,



% ssh -R X:Remote_2:Y Remote -l username

 
とすると,次のようになる.


 
この場合,LocalとRemote_2間の通信は暗号化されない.



+--Local--+ +--Remote--+ +-Remote_2-+
| | | | | |
| +--- S ======> 22 <-+ | | |
| | | | | | | |
| +--> T --+ X ---+ | +--> Y |
| | | | | | | |
+---------+ | +----------+ | +----------+
| |
+-----------------------+

例その6


 
例5において,さらにLocalとRemote_2間の通信を暗号化する方法.


 
たとえば,あるターミナルで,



% ssh -R X:Local:Z Remote -l username

 
としてログインし,別のターミナルで



% ssh -L Z:Remote_2:Y Remote_2 -l username

 
とする.


 
これで,RemoteのX番ポートからRemote_2のY番ポートまで,ローカルホストのZ番ポートを介したセキュアな通信経路を確保できる.



+--Local--+ +--Remote--+ +-Remote_2-+
| | | | | |
|+---<--- S ======> 22 <-+ | +==> 22 --+ |
Z| | | | | U | | |
|+--->--- T ==+ X ---+ | U Y <--+ |
| | U | | U | |
+---------+ U +----------+ U +----------+
U U
+=======================+

 
あるいは,例3で例2ダッシュを応用した時と同じようなロジックでも可能.


 
たとえば,



% ssh -R Z:Remote_2:22 Remote -l username

 
としてログインし,そこからさらに,



% ssh -p Z -L X:Remote_2:Y Remote_2 -l username

 
とする.



+--Local--+ +--Remote--+ +-Remote_2-+
| |---------| | | |
| +=== S ======> 22 <====== Z +==> 22 --+ |
| U |---------| +--->| U | | |
| U | | | | U | | |
| +==> T ==+ X ----+ | U Y <--+ |
| | U | | U | |
+---------+ U +----------+ U +----------+
U U
+=======================+

 
この場合,RemoteからRemote_2へsshが出来ることが必要である.ので,本当なら次のようにする方が簡単ではある.



% ssh Remote -l username

 
としてログインし,そこからさらに,



% ssh -L X:Remote_2:Y Remote_2 -l username

 
とする.



+--Local--+ +--Remote--+ +-Remote_2-+
| | | | | |
| S ======> 22 +--> T ========> 22 --+ |
| | | | | | | |
| | X ----+ | Y <--+ |
| | | | | |
+---------+ +----------+ +----------+

関連サイト

このブログの人気の投稿

TeXマクロプログラミング

2012.03.30 更新 スライド化しました.   新しいマクロ定義 以下に例を示す. \dev\hoge{ほげ}    これにより,\hogeが「ほげ」に変換される.引数を使うには,以下のように記述する. \dev\hour#1{今は#1時です}   別の方法 上に示した処理は,以下のようにも記述できる. \newcommand{\hoge}{ほげ} \newcommand{\hour}[1]{今は#1時です}   defとnewcommand違い defとnewcommandが異なる箇所として,以下が上げられる. 定義命令を定義している処理系 マクロを多重定義した場合の動作 引数のとり方  まず,定義されている処理系が異なる.defはtexで定義されており,newcommandは,latexで定義されている.  次に,多重定義した際の動作が異なる.defでは,新しい定義で上書きする.一方,newcommandではエラーを出力する.  最後に,defでは,引数のとり方としてパターンマッチングを利用できる.例えば,以下のマクロ定義があるとする. \def\Hatchr(#1,#2)(#3,#4)#5 これにより,以下に示すインターフェイスを実現する. \Hatchr(3,4)(7,8){hoge}   マクロの複製 以下の処理では,\hogeの内容を\fugaに複製する. \let\fuga\hoge   マクロの初期化 以下のコードで,\hogeを初期化する. \let\fuga\relax  ここで,\relaxは初期化のために利用する空の定義である.   マクロに文字を追加し再定義 defによる定義は,マクロの多重展開をおこなわない.例えば,以下のコードを考える. \def\hoge{ほげ} \def\hoge{\hogeふぇふぇ}  この後,\hogeを利用すると「\hogeふぇふぇ」と展開される.つまり,一度だけしかマクロは展開されない.  マクロを展開してから定義する際には,以下の記述を用いる. \edef\hoge{\hogeふぇふぇ}  これに

beamerでしおりを付ける

しおり   しおりとは,acroreadなどでpdfを表示する際に,ウィンドウの左側に表示される目次のようなものである.このしおりを使うことで,文章の構成を大まかに把握したり,特定の項目に移動することが簡単にできる.   beamerには,標準でしおりを付ける機能が備わっている.以降では,しおりを付ける方法について述べる. しおりをつける   beamerでしおりを付けるには,次のコマンドをtexの文章中に記述する. section{} subsection{} subsubsection{}   カッコの中に記述する文字列が,しおりの項目名に使用される.また,section,subsection,subsubsectionを使い分けることで,階層化をすることも可能. 文字化け対策   しおりは,標準の仕様ではUnicodeのみがサポートされている.EUCを使う場合は,そのままではしおりの日本語が文字化けする.このため,Unicodeを用いない際には,何らかの対策が必要である.   以下では,EUCを利用する人のための対処策を述べる.ここで,dviからpdfを生成する際の方法によって,対処の仕方が異なることに注意する.具体的には,(1)dvipdfmxを用いる場合と,(2)dvipsおよびps2pdfを用いる場合で,対処の仕方が異なる.以降,それぞれについて述べる. dvipdfmxを用いる場合   次のコードをプリアンブルに記述しておくことで解決できる.これにより,しおりの部分の文字列が,自動でUnicodeに変換される. \ifnum 42146=\euc"A4A2 \AtBeginDvi{\special{pdf:tounicode EUC-UCS2}}\else \AtBeginDvi{\special{pdf:tounicode 90ms-RKSJ-UCS2}}\fi   ただし,実行にはEUC-UCS2というファイルが必要.texをインストールする際に,標準でシステムに入る場合はこのままコンパイルできるが,無ければコンパイルできない.私がこれまで経験したなかでは,Vine 5.0, Mac OSXには含まれているが,Debian lennyには入っていなかった.   システムにEUC-UCS2が無い場合,以下のようなサイトから取ってくる.取って

ssh-agentの管理を自動化する

ssh-start.sh ssh-agentの管理を自動化するスクリプトssh-start.shを紹介する. 詳細 ssh-agentを使うことで,sshでリモートログインする際に,パスワードの入力を省略できる. ssh-agentを利用するためには,ソケットのパスとプロセスIDを環境変数に登録する必要がある.環境変数に登録すべき情報は,ssh-agentの起動時に,以下のように標準出力に出力される. $ ssh-agent SSH_AUTH_SOCK=/tmp/ssh-XTqIvn4918/agent.4918; export SSH_AUTH_SOCK; SSH_AGENT_PID=4919; export SSH_AGENT_PID; echo Agent pid 4919; 上記のように,ssh-agentの出力はシェルコマンドとなっており,実行すれば環境変数がセットされる.このため,多くの解説記事では,次のようにevalを用いる方法が述べられている. $ eval `ssh-agent` Agent pid 4919 しかし,この方法は,同じssh-agentのプロセスを複数のシェルから利用することはできない.上記コマンドを他のシェル上でも実行すれば,動作はするが,次の点で優れた手法とは言えない. ssh-agentのプロセスを複数起動する (本来は1個で充分). 起動毎に秘密鍵の登録,およびパスフレーズの入力が必要となる. 上記の問題は解決するには,1個のssh-agentを複数のシェルから再利用すればよい.例えば2個のターミナルから1個のssh-agentプロセスを利用するには,次のようにする. # terminal 1 $ ssh-agent > ~/tmp.sh $ source ~/tmp.sh Agent pid 4919 # terminal 2 $ source ~/tmp.sh Agent pid 4919 こうすることで,2個のターミナルから同一プロセスのssh-agentを利用できる. 以上の処理を自動化したものが,ここで紹介するスクリプトである. 使い方 環境変数を扱かうため,通常のスクリプトのようには利用できない.このため,sourceコマンドや.(ドット)コマンドで実行する. $ source /path/to/dir/s