home / uni / ssh SSH

 なんとなく敷居が高そうなsshだが、Windows用クライアントが整ってきた関係もあり、とりあえず使う分には「余分なメッセージが出るtelnet」くらいの感覚になってきた。徐々にステップアップしていけば使いこなすのはそんなに難しくないだろう。エージェント・ポートフォワード・rコマンドの置き換えは一度味わうとやめられなくなる。

home / uni / ssh 基本的な使い方

●SSH
 Secure SHellの略。暗号化通信路でリモートログインする一連のツール類のこと。shellという名がついているものの、ssh自体にはシェルの機能はない(最終的にリモート側でcshやbashが立ち上がるわけだ)。telnetの暗号化版だと思っていればだいたい間違いない。OpenSSHのものとssh.comのものがあるが、メジャーなのはOpenSSHの方。FreeBSDには標準で入っている。パスワードによる認証以外にチャレンジレスポンス、公開鍵方式などの認証がある。TCPポートフォワードを使うと簡易VPNとしても使える。
●サーバーの設定
 FreeBSDの場合、インストール時に勝手に入るはずである。止めちゃった人は /stand/sysinstall の Configure / Networking / Sshd をチェックしてリブート。サーバーには「なりすまし」を検出するための鍵(ID)があるが、これはFreeBSDの場合、インストール直後のブート時に、ソースから入れた場合は(確か)make install 時に自動的に生成される。FreeBSDの場合 /etc/ssh 以下にできるが、ソースから入れると違う場所になるはず。

 FreeBSDに限らず、最近のUnix系OSでは放っておけば勝手に入るはずである。 あとは動いているかどうかと、設定が正しいかどうか。 ちゃんとしたディストリビューションなら設定はだいたい正しいはずなので、あとはお好みに応じて調整すればよい。 開けなければならないポートは22/TCP。

●クライアントの設定(Unix)
 サーバーの鍵を先に受け取っている場合は ~/.ssh/known_hostsに書いておくとよいが、デフォルトの状態では必須ではない。他に特にやることはない。
●Windows用クライアント
 PuTTY・Tera Term・cygwinのsshなどがメジャー。 Tera TermはTTSSHという拡張モジュールでSSHに対応する(同梱されている)。 最近のものはSSH V2にも対応している。 cygwinの設定はUnixと同じ。 bashの中だけでなくコマンドプロンプトからも使える(cygwinのコマンド全般がそうなっている)。 当然コマンドライン版しかなく、若干使い勝手が悪い(特にスクロールバックの効かないWin95系のDOSプロンプトの場合)。 PuTTYはどうもgettyの反対、という意味らしい。現在のところPuTTYがお勧め。
●PuTTY
 総元締。ダウンロードのページに行って、「A Windows installer for everything except PuTTYtel」を落とすのがいいだろう。 できればPGPやGNU PGで署名を確認した方がよい。 インストーラーを使う場合、秘密鍵ファイルへの関連付けなど、およそ必要と思われることは全部やってくれる(と思う)。
●アクセスしてみる
 クライアントから、ssh hostname。ユーザー名を変えたい場合は、ssh username@hostname とするか、-l(エル)オプションを使って、ssh -l username hostname とする。初めてアクセスするサーバーの場合、サーバーの指紋(fingerprint)の確認を求められる。指紋が合っていればyesと入力すると、~/.ssh/known_hosts(Winクライアントの場合は相当品)に書き込まれ、次回からは自動照合される。指紋の照合が終わると、サーバー側でパスワード認証が許可されていれば(デフォルトでは許可)パスワードを尋ねられるので、シェルアカウントのパスワードを入力すればログイン完了となる。
●サーバーの指紋?
 サーバー鍵ペアのチェックサムみたいなもので、なりすましを防ぐためのもの。サーバーの鍵ペアを入手せずになりすましを行うのは困難。鍵ペアが盗まれたらまったく意味がないので注意。FreeBSDの場合、鍵ペアは/etc/sshの下に、ssh_host_key・ssh_host_dsa_key・ssh_host_rsa_key という名前で保存されている。それぞれSSH1・SSH2 DSA・SSH2 RSAの秘密鍵。公開鍵は後ろに .pub が付く。指紋を表示するのは公開鍵の方。サーバーの鍵指紋は、ssh-keygen -l -f path/to/sshhostkey.pub で表示できる。照合時に鍵の種類が表示されるので、適切なファイル名を指定すること。

 最近はMD5以外の形式で指紋が表示されることもある。 その場合は-Eオプションで指紋の形式を指定する。

$ ssh-keygen -l -f /etc/ssh_host_rsa_key.pub -E md5
2048 MD5:01:23:45:67:89:... user@hostname (RSA)

$ ssh-keygen -l -f /etc/ssh_host_rsa_key.pub -E sha256
2048 SHA256:abcDefG29179... user@hostname (RSA)

 クライアント側で指紋の表示方法を変えたい場合は、ssh_configファイルのFingerprintHashオプションを使う。 sshのコマンドラインで指定する方法、~/.ssh/config で指定する方法、/etc/ssh/ssh_config で指定する方法などがある。 また、Host指定を使うと特定のホストだけ指紋の表示方法を変えることもできる。

$ ssh user@host.example.jp
The authenticity of host 'host.example.jp (192.0.2.2)' can't be established.
RSA key fingerprint is SHA256:AsDfGhJkLi...
...

$ ssh -o FingerprintHash=MD5 user@host.example.jp
The authenticity of host 'host.example.jp (192.0.2.2)' can't be established.
RSA key fingerprint is MD5:12:34:56:78:...
...
●何度も指紋確認を求められる
 known_hostsファイルはホスト名ベースでの記録なので、同じホストでもアクセス時の名前・ドメインが異なる場合はその都度確認する必要がある。ホストの鍵情報が変更された場合(SSHやシステム全体をインストールしなおしたような場合)は指紋が不一致である、というメッセージを受ける。この場合、ホスト管理者に新しい指紋を問い合わせる必要がある。覚えがないのに指紋不一致と指摘される場合、ほんとーにクラックされた可能性もある。sshサーバーではなくDNSがクラックされた場合にありがち。

 ~/.ssh/known_hosts はテキストファイルなので、今までアクセスしたことのあるホストに違うIPアドレスやホスト名でアクセスする場合、アクセスしたいホストの行をコピーして適当に書きかえておくとよい(書き換え方はファイルの中身を見ればすぐ分かる)。 PuTTYならばレジストリの

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys

にそれらしいものがずらずらと並んでいるので、やはりコピーしてキーの名前を書き換えればよい。

 最近のsshではホスト名がハッシュされていることがあり、どの行がどのホストか分からない場合がある。 その場合はssh-keygen -F hostnameとするとそのホストが何行目に書かれているか分かるので、その行をコピーしてホスト名を書き換えればよい。 known_hostsにハッシュされたホスト名と生のホスト名が混在していても問題ない。 ハッシュしたければssh-keygen -Hで変換できる。 ハッシュなので元には戻せない。

 なお、最近DSA(ssh-dss)形式の鍵はデフォルトで使えなくなったので注意。 HostKeyAlgorithmsを指定すればまだ使えるが、この機会に古いサーバーの鍵を更新しておくとよいだろう。 参考: openssh-7.0p1 で ssh-dss 鍵が無効になります (Arch Linux JP Project)

home / uni / ssh 公開鍵認証

 クライアント側でも鍵ペアを作り、あらかじめ登録してある鍵ペアと一致しないと認証が成立しない方式。クライアント側の秘密鍵に対してパスフレーズを設定するのが普通で、秘密鍵・パスフレーズの両方が漏れない限りクラックされない。どちらかが漏れた段階で鍵ペアを作り直せば、ホストが危険にさらされることがない。エージェントを使うことで比較的安全にパスフレーズ入力を省略することができる。これは、バッチ処理の通信路にsshを使う場合に便利。

●鍵ペアを作る
 Unixあるいはcygwinの場合は、ssh-keygen -t 鍵タイプ で生成できる。鍵タイプはrsaかdsaを指定する。通常、秘密鍵が ~/.ssh/id_rsa あるいは ~/.ssh/id_dsa というファイルに、公開鍵が ~/.ssh/id_rsa.pub あるいは ~/.ssh/id_dsa.pub というファイルになる。

 PuTTYの場合は puttygen.exe を使う。PuTTYではSSH2 RSAが推奨されている。理由はよく分からないが。下の部分で鍵タイプを指定し、[Generate] ボタンを押したら、上半分のエリアでマウスをウリウリ動かす。と、鍵が生成されるので、パスフレーズを入力、コメントを分かりやすく書き換えて(ユーザー@クライアント名という形式を入れておくとよい)鍵を保存する。保存するのは秘密鍵だけでよい。 ファイルの拡張子は.ppkになる。

●公開鍵をホストに登録
 Unixあるいはcygwinの場合は、~/.ssh/id_*.pub のファイルをサーバーへ持って行き、~/.ssh/authorized_keys に追記する。PuTTYの場合はputtygenで秘密キーをロードすると、上の [Public key for pasting into OpenSSH authorized_keys2 file] の箱の中に追記すべき内容が出ているので、マウス右クリックを使って全選択→コピーして、これをサーバーの ~/.ssh/authorized_keys に追記する。なお、追記するためにサーバーにログインする必要があるが、安全な方法でログインすること。パスワードのみの認証を許可していないsshサーバーでは、コンソールでログインするしかない。
●秘密鍵の指定(PuTTYの場合)
 セッション設定の Connection / Auth / Private key file for authentication でいま作った秘密鍵ファイルを指定する(エージェントを利用する場合は不要)。
●準備完了
 あとは普通にログインするだけ。パスフレーズを聞かれるので、秘密鍵のパスフレーズを入力する。パスワード認証が許可されている場合は、公開鍵認証に失敗するとパスワード認証に切り替わる。PreferredAuthenticationsの設定によっては、先にパスワード認証になることもある(意味ねー)。
●パスワード認証を止める
 サーバー側の sshd_config(FreeBSDの場合 /etc/ssh/sshd_config)で、PasswordAuthenticationをnoに設定する。チャレンジレスポンス認証でもパスワードを使うため、ChallengeResponseAuthenticationもnoに設定しておくとよい。

home / uni / ssh パスフレーズ入力を省略する

 エージェントを常駐させ、あらかじめエージェントにパスフレーズ込みで秘密鍵を登録しておくことで、ログイン時のパスフレーズ入力を省略できる。これは、何度もログインする必要がある場合や、バッチ処理中でssh接続を使用する場合(cvsでリモートリポジトリにアクセスする場合など)に非常に有用である。

●Unix(あるいはcygwin)のエージェント
 ssh-agentという名前。実行の仕方は二通り。シェルから eval `ssh-agent` などと実行(バッククオートに注意)するか、ssh-agent bash などと実行する。前者の場合、エージェントがバックグランドで動くため、シェルを落ちる前に eval `ssh-agent -k` でエージェントを終了させる(やはりバッククオートに注意)必要がある。後者の場合はエージェントが子プロセスとしてシェルを起動する。子プロセスのシェルを終了するとエージェントも終了する。後者の方が迷子エージェントを作らなくで済む。ログイン/ログアウトスクリプト中に書く場合は前者の方が向いている。

 エージェントを立ち上げたら ssh-add でキーをエージェントに登録する。登録時にパスフレーズをたずねられるので入力する。あとは普通にsshを使えばよい。パスフレーズ入力なしでログインできるはずである。

 エージェントとssh本体は環境変数「SSH_なんちゃら」で指定されるUnixドメインソケットでデータをやり取りしている。したがって、この環境変数が定義されている環境ならば常駐しているエージェントが利用可能である。逆に言うと、エージェントとはまったく無関係なプロセスはエージェントを利用できない。

●PuTTYのエージェント
 pageant.exeを実行するとタスクトレイに常駐する。タスクトレイ内のエージェントアイコン上で右クリック→Add Keyを選択し、秘密鍵を登録する。このときにパスフレーズをたずねられるので入力する。あとは普通にPuTTYを使えばよい。パスフレーズ入力なしでログインできるはずである。

 PuTTYの場合は一度常駐してしまえば、以後立ち上げるPuTTY・plink・psftp・pscpなどで有効である。プロセスの親子関係はなくてもよい。 起動時にコマンドライン引数で秘密鍵ファイルを指定できるので、ショートカットを作ってコマンドライン引数を指定しておくとよい。 そんな面倒なことをしなくても、.ppkファイルのショートカットを作って関連付けをpageant.exeにしておけばよい (複数の鍵を使い分けてる場合は特に。インストーラーでイントールした場合は既にそうなってるかもしれない。 はるか昔のことなので忘れてしまった。 よく分からなかったらサーチエンジンに聞いておくれ)。 この場合、エージェント起動時にパスフレーズをたずねられる。

 ちなみに、つづりはpagentではなく、pageant(ページェント)である。 私は5年くらい間違って「ピーエイジェント」だと思って覚えていた。

●cygwinからPuTTYのエージェントを使う (22 Nov 2015)
 ssh-pageantというプログラムがある。 以前はサードパーティー扱いだった気がするが、現在はcygwinのsetupからインストールできる。 Netカテゴリーの中に入っているが、pageantで検索したほうが早いだろう。 使い方はssh-agentとだいたい同じ。 pageantを自動的に起動してくれたりはしないので、あらかじめpageantを起動して、鍵を入れておく(パスフレーズを入力しておく)必要がある。 あとは、例えばssh-pageant ssh hostnameなんていうように使えば、PuTTYのエージェントを使ってssh接続してくれるし、ssh-pageant bashとすれば、このbashの中ではPuTTYと同じようにsshを使えるようになる。 次に説明するエージェントフォワードと組み合わせるとさらに便利。
●エージェントフォワード
 sshでログインしたホストから、さらにsshで別のホストへログインする場合、最初にログインする時にエージェントを使っていれば、次のホストへのログイン時にエージェントを使わなくてもパスフレーズなしでログインできる。そのためにはエージェントフォワードを有効にしておく必要がある。

 とりあえず、最初のログイン元ホストでエージェントを常駐させ、鍵を登録しておく。そして、Unix(cygwin)のsshでは最初のログインの時に-Aオプションを指定する。PuTTYでは Connection / SSH / Auth / Allow agent forwarding をチェックしておく。こうしてログインしたら、あとは普通にsshで次のホストへログインする。と、認証動作が最初にログインしたホストへ転送されて行われ、二つ目のホストへはエージェント・パスフレーズなしでログインできる。

 もちろん、最初のログインの時に使った公開鍵を、二つ目のホストの ~/.ssh/authorized_keys にあらかじめ書き込んでおく必要がある。エージェントフォワードを有効にしてログインする(最初のホストの方)と、エージェントを常駐させたときと同じ環境変数が既に定義されていることがわかる。そして、エージェントフォワードは多段につなげていくことが可能である。しつこいけど、ログイン先には一番最初にログインした(エージェントを常駐させた)ホストで使った公開鍵と同じ鍵が登録されている必要がある。-Aをつけるのは一段前のログイン時である点にも注意。

鍵ペアのあるホストで
エージェント常駐
エージェントに鍵登録
$ ssh -A host1 host1に公開鍵が
登録されていれば
ログインできる
$ ssh -A host2
(エージェント不要)
host2に公開鍵が
登録されていれば
ログインできる
$ ssh host3
(エージェント不要)
host3に公開鍵が
登録されていれば
ログインできる
$ ssh host4
(エージェント不要)
host4に公開鍵が
登録されていれば
ログインできる
$ ssh host5 host5は自動では
ログインできない
●エージェント使用上の留意点
 一度パスフレーズを入力すれば以後は入力を省略できるのだら、パスフレーズは長めにしておく。エージェントを常駐させたら、席を離れるときは必ずコンソールをロックする(重要)。
●rコマンドの代替としてのssh
 rコマンドとはrlogin・rsh・rcpのことである。sshはエージェントに秘密鍵を登録していればパスフレーズ入力を省略できるため、これらのコマンドの代わりに使える。rloginはrshでコマンドラインにホスト名だけ指定した場合と同じだから、sshがrshの代わりになればよい。

 実際、sshのコマンドラインはrshとよく似ており、ほとんどの場合そのまま代用可能である。例えば、rshでcvsリポジトリにリモートアクセスしているような場合、リポジトリのあるサーバーにsshでログインできる環境を整えれば、あとはCVS_RSH環境変数をsshと設定するだけでsshを使ってリモートアクセスできる。

 rshとくらべ、~/.rhosts などの名前ベースの認証を使用しないため、なりすましが非常にやりにくく、また、通信路も暗号化されているため、より安全な方式といえる。 遅い通信路を使う場合、圧縮することも可能である。 sshの設定に慣れてしまえば、他に覚えなければいけない設定もない。

 rcpに対応するものとしてはscpが用意されている。もちろん、エージェントを利用可能である。

●rコマンドの代替としてのPuTTY
 PuTTYの場合、コマンドライン版としてplink.exeというプログラムが付いてくる。概ねsshと同じコマンドラインとなるので、やはりrshなどの代わりに使用できる。plinkの場合、PuTTYのセッション設定名をホスト名に使用できる。例えば、somehostというPuTTYセッション名でcvsリポジトリのあるサーバーにログインできる場合、CVS_RSH環境変数にplinkを、CVSROOT環境変数に
:ext:user@somehost:/path/to/repository

を指定すれば、plinkを使ってリモートアクセスできる(CVSはcygwin付属のものを使う)。pageantも利用可能(というか、標準出力と標準エラー出力がごっちゃになるようなので、使ったほうがよい)。

 WindowsでCVSを使う場合、このほかに改行コードの変換と、ログメッセージの入力の問題があるので注意すること。前者はcygwinのテキストモードマウントを使うことで、後者は-mオプションやCVSEDITOR環境変数を使うことで解決できる。

●ホストにニックネームをつける
 ssh_config( ~/.ssh/config あるいは /etc/ssh/ssh_config )で以下のように書くと、aliasという名前で host.example.jp に接続できる。
Host alias
  Hostname host.example.jp

 Hostがあると、以後のオプションはそのホスト名にだけ適用される。 もう一度Hostを書くと対象のホスト名が変わる。 したがって、上の2行の組み合わせをずらずら書いておけば、いくらでもニックネームを作れる。 Hostにはワイルドカードとして*が指定でき、オプション内に%hを書くと*がマッチした部分と置き換えてくれる。 すべてのホストに共通な設定は最初のHostの前に書くか、

Host *
とした後に書けばよい。

 HostnameにはIPアドレスも指定できるので、DNSで名前が解決できず、/etc/hosts を編集する権限もない場合に重宝する。

 plinkの場合はセッション名がそのままニックネームとして使える。

home / uni / ssh ポートフォワード

 SSHの便利な機能としてポートフォワードがある。トンネルとも言う。これは、SSHによってできあがっている暗号化された通信路内に、別のTCP通信路を通してしまおうという機能。一種のVPNと言え、暗号化に対応していないプロトコルでも簡単に暗号化通信路を使うことができる。

 ポートフォワードを使うと、SSHサーバーのTCPポート22へ接続できるようにファイアウォールを設定するだけで、ファイアウォール内のSSHサーバー以外のホストにも簡単に接続できる。これはファイアウォールのルールが簡単になると同時に、簡単にファイアウォールを越えられるということも意味している。ファイアウォール外からsshによるログインを許可する場合はこの点を考慮に入れ、慎重に検討する必要がある。

 ポートフォワードできるのはTCPだけで、UDPはできない。UDPの場合、最悪 Ether over TCP over SSH で通す手もあるが、私はやったことはない。

●基本的な使い方
 クライアント(ローカル)からサーバー(リモート)への転送と、その反対がある。前者を使うことが多く、SSHクライアントが転送したいポートで接続を待ち、接続があったらSSHサーバーが転送先へ接続することで仮想的な暗号化通信路ができあがる。

 例えば、メールサーバーとして pop.example.jp:110 を使っており、pop.example.jp にsshで接続できるとする。ローカルのTCPポート110を、サーバーの localhost:110 に転送する設定にし、メーラーの設定は pop.example.jp:110 から localhost:110 に変更する。この状態でメールを読むと、メーラーは localhost:110 へ接続しに行き、ポート110はsshが待ち受けていて、サーバー(=pop.example.co.jp)の localhost:110 へ、暗号化通信路を通してデータが転送される。これで、暗号化通信路を通してメールを読むことができる。APOPはパスワードのみ暗号化されるが、この場合はメールの内容も全部暗号化される。APOPよりも強力といえる。

 転送先ホストはlocalhostでなくともよい。例えば、ファイアウォールの内側に ssh.example.jp と pop.example.jp があって、ssh.example.jp にのみsshで接続できる場合は、ローカルのポート110 を、リモートの pop.example.jp:110 に転送する設定にすればよい。ローカル側で localhost:110 へ接続すると、ssh.example.jp が pop.example.jp:110 へ接続しに行ってくれる。

$ ssh ... ssh.example.jp
localhost:110で待ち受け
<<--暗号化通信路-->> [ssh.example.jp:22]
pop.example.jp:110へ接続
メーラーでlocalhost:110へ接続 <<--仮想通信路-->> [pop.example.jp:110]
POP3デーモン起動
●Unix(あるいはcygwin)のポートフォワード
 -L オプションを使う(オプションの大文字・小文字は区別されるので注意)。先の例は
ssh -L 110:pop.example.jp:110 ssh.example.jp

となる。最初の110がローカル側の待ち受けポート、後ろの110がリモート側の接続ポートである。普通は同じにするが、変えることもできる。例えば、自分専用のPOP3デーモンがpop.example.jpのTCPポート11100で待ち受けているなら、

ssh -L 110:pop.example.jp:11100 ssh.example.jp

とすればよい。

●PuTTYのポートフォワード
 セッション設定の Connection / SSH / Tunnels に設定がある。Port forwarding の中の Source port にローカル側のポートを、Destinationにリモート側のホストとポートを書き込み、Localラジオボタンを選択してAddボタンを押すと設定される。先の例だと Source port が110、Destinationが pop.example.jp:110 になる。Addボタンを押すと Forwarded ports リストボックス内に
L110 pop.example.jp:110
という項目が追加される。このまま普通にログインし、メーラーの設定を変更して使えばよい。
●FTPとSSH
 FTPもTCPを使ったプロトコルなので原理的にはポートフォワード可能なのだが、ファイル転送時にポート番号が動的に変わったりするため実際には難しい。ファイアウォールをFTPに対応させるのがちょっと面倒なのも同じ理由。実は、SSHにはsftpというプログラムが付属していて(PuTTYの場合はpsftp.exe)、これを使うとFTPとほぼ同じことができる。sftpはTCPポート22さえ開いていれば使えるので、ファイアウォールを越えたファイル転送が非常に簡単になる。しかもエージェントが利用可能である(!)。一度SSHが動き出したら、telnetだけでなくFTPも止めてしまおう。

 規格的にmget・mputがサポートされていない。OpenSSHのsftpはgetなどでワイルドカードが使用可能のようである。PuTTYのpsftpは現在のところワイルドカードは使えないようだ。また、テキスト・バイナリという概念もないので、必要に応じて改行コードの変換を行う必要がある。

 ディレクトリを丸ごと転送するのならばrsyncを使うと楽。 これも、トンネルとしてsshを使うことができるが、現在、PuTTY 0.60のplinkはrsyncのトンネルとして使えないので、Cygwinのsshを使う必要がある。 なので、Cygwinのsshにも慣れておくとよい。


Copyright (C) 1997-2015 akamoz.jp

$Id: ssh.htm,v 1.16 2015/12/03 15:20:00 you Exp $