2008/12/31(Wed)手軽で便利なssh Local PortForward

2008/12/31 20:50 Software

まずはsshの説明から

sshはSecure SHellの略だが、その名の通り、通信路のデータを暗号化して安全に端末を操作できるものである。
通常は、端末を制御するためのものだが、これをトンネル代わりに使うことで、平文通信をしているプロトコルの通信を、暗号化通信にかえることができる。
これをポートフォワードと言う。
今回はこれについてのTips。


VNCを使う場合を例にとって軽く説明すると、遠隔地にある*1VNCサーバーにアクセスする際、
MyPC   port:12456  ---------------------------> HostPC   port:5900
     (自動割り当て)

( ---> : 平文通信)
( ===> : 暗号通信)
という感じでアクセスされる。当然、HostPCは5900番をグローバルから見えるようにする必要がある。
このままでは簡単に制御権を見ず知らずの人に獲得されてしまうので、VNC Passwordなどを用いるがあまり安全ではない。しかも、VNCのプロトコル内に、キーボードの平文情報が流れ、二次的な流出もありうる。

そこで、ssh PortForward。PortFowardにはLocalとRemoteと二種類あり、次のような使い方ができる。
Local
相手sshサーバーから見た特定コンピュータのportを、自分のPCのportに割り当てる。
Remote
相手sshサーバーの特定のportに、自分のPCのportを割り当てる。
どちらの場合も、相手コンピュータと自分のPCの間はsshで暗号化通信される。*2

*1 : 同じLAN内にないということ

*2 : 但し、LocalPortFowardの場合、sshサーバー≠特定コンピュータなら、sshサーバーと特定コンピュータの間は暗号化されない

使いどころ

ここではよく使うであろうLocal Port Forwardに限って説明する。
先ほどの例で、VNCサーバーと同じコンピュータ又は、同じネットワークにSSHサーバーが居るなら、このような接続を考える。
      (自動割り当て)
MyPC   port:12456                     HostPC   port:5900
           ↓                                ↑
       port:1234  ==============> HostPC or sshServer   port:22
      (好きな番号)
( ---> : 平文通信)
( ===> : 暗号通信)
図のように、MyPCとsshサーバーの間は完全に暗号通信になっているので、盗聴の恐れが少ない。

これを実現するには、PuTTY ごった煮版のputty.exeまたは、pfwd.exeを用いるとよい。ここでは、両方の使い方を説明する。

使い方

次のように仮定する。
但し、以降sshサーバーとHostPCが同じマシンの場合は、hostpc.example.comを全てlocalhostに置き換えて読んでほしい。

sshServer: ssh.example.com:22
HostPCのVNCサーバー: hostpc.example.com:5900

Windows - putty

MyPCがWindowsの場合は先のPutty.exeを起動し、sshサーバーへの設定を済ませる。
ホスト名にsshサーバーのIP/ホストをセット、ポートを適切に設定。
ssh_pfwd1.png


[接続]-[SSH]-[トンネル]と進み、源ポートにローカル側の割り当て番号(Listenしていないポートなら何でもよい)、送り先にHostPCのホスト名とポートを:区切りで書く。
この例では、ローカルの1234番にフォワードさせた。
ssh_pfwd2.png


次に、[追加(D)]をクリックしてから、[開く]
sshにログインし、その状態でputtyを放置。

あとは、VNCサーバーからlocalhost:1234にアクセスすると、sshサーバーをぐるっと通って、hostpc.example.comの5900番に繋ぎに行ってくれる。
このフォワードの優れているところは、sshサーバーさえ外部からアクセスできれば、5900番を外部に見えるように設定する必要が無いところである。
さらに、sshサーバーとVNCサーバーが同じPCなら、VNCサーバーの接続元をlocalhostに制限することで、LAN内からすらアクセスできなくなり、安全性が高い。

Windows - pfwd

先のPuTTYのリンクで、本家ではなく"ごった煮版"へリンクを張ったのは、便利なpfwd.exeが付属しているからである。
pfwd_sample.iniをpfwd.iniにリネームするか、コピーして、次のように設定してみよう。
[SSH]

Host=ssh.example.com
Port=22
Compression=1
ProtocolVersion=2
PrivateKey=
User=myuserid
Password=

[FORWARD]

01=L1234:hostpc.example.com:5900
[SSH]ではPuTTYに設定したセッション情報を使うこともできるし、ここで指定することも可能。PrivateKeyには公開鍵暗号の秘密鍵をセットすることもできる。
[FORWARD]には01,02,03...と番号を増やして好きなだけForwardできる。

こうした後、保存して、pfwd.exeを起動すれば、パスワードを入力するだけで面倒な設定なしに一発でsshサーバーにログインし、フォワード設定をして、タスクトレイに常駐する。
右クリックして、閉じるを選択すれば、終了する。

Linux

Linuxはもっと簡単。ほとんどのディストリビューションにsshコマンドが初期装備されているはずなので。
ターミナルを一枚開き、次のように打つ。
$ ssh -L 1234:hostpc.example.com:5900 user@ssh.example.com

一歩進んだ使い方。
MyPC以外のコンピュータも、自分のport:1234を通してhostpc.example.com:5900にアクセスさせる場合、-gを付ける。
但し、使用にはくれぐれも注意。アクセス権のないPCをLocalForwardで素通りさせる危険性があるからだ。*3
$ ssh -g -L 1234:hostpc.example.com:5900 user@ssh.example.com

PortForwardだけさせて、sshでloginしたターミナルが不要な場合は、-fと-Nを付ける。
$ ssh -f -N -L 1234:hostpc.example.com:5900 user@ssh.example.com

Linux Tips

2枚以上のNICが入っているマシンや、IPv4とIPv6の両方のアドレスを持っている場合は、bind addressの設定をするとよい。
これは、-Lの3つのパラメータの前にもう一つパラメータを付け、そのNICのアドレスに対してForwardを行うというもの。
省略した場合は、*が割り当てられるので、全てのIPアドレスに対してbindが行われる。


マシンが、192.168.2.11と192.168.11.21というIPアドレスを持っているとして、
$ ssh -L 192.168.2.11:1234:hostpc.example.com:5900 user@ssh.example.com
とすれば、192.168.2.11:1234はForwardされるが、192.168.11.21:1234はされない。

IPv6アドレスを指定するには、角括弧で囲む。
$ ssh -L [::1]:1234:hostpc.example.com:5900 user@ssh.example.com
この状況下では
$ telnet localhost 1234
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused

$ telnet ::1 1234
Trying ::1...
Connected to ::1.
Escape character is '^]'.
~~~応答~~~
Connection closed by foreign host.
という挙動を示す。


たまに、bind: Address already in useという警告が表示されることがあるが、これは、複数のNICにフォワードされたという警告であり、使用上は問題ない。
上記のようにbind addressを設定すれば消える。

Linux ssh_config

Linuxでいちいちsshの長ったらしいコマンドを打つのはしゃくなので、登録してしまおう。
まずは次のように、パーミッションを制限したディレクトリ、ファイルを作る。
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ touch ~/.ssh/config
$ chmod 600 ~/.ssh/config
viやemacs等で~/.ssh/configを編集。
Host example
HostName ssh.example.com
User myuserid
Port 22
LocalFoward 1234:hostpc.example.com:5900
GatewayPorts yes

と作り、保存すれば、"ssh -g -L 1234:hostpc.example.com:5900 myuserid@ssh.example.com"と同様の設定になる。
Hostという行から次にHostという行が始まるまでが、一つの設定としてみなされるので、複数定義してよい。

書き方に迷ったら、$man ssh_configをしてみるとよい。

*3 : 例えば、無線LANスポットを使っていて、見ず知らずの人に社内ネットワークに入られてしまう等が考えられる