Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
About SSH
[go: Go Back, main page]

SSH について

Last Updated at $Date: 2005/06/08 15:51:00 $.

SSH (Secure SHell) は, rsh/rlogin/rcp などの r 系コマンドを代替するために作られたプログラムです. 広く知られているように, r 系コマンドは認証手段が非常に貧弱なので,クラッカーの格好の標的となってしまいます. 対して,SSH は,公開鍵暗号に基づく強力な認証手段と通信路の暗号化により, 信用できないネットワーク上で安全な通信を行う方法を提供します.

2005年5月26日に OpenSSH 4.1 が公開されました.


Port Forwarding を利用したネットワーク接続

セキュリティ上の理由から, アクセスを受け付けるホストを制限しているメールサーバーやニュースサーバーが増えています. このようなサーバーに接続する場合,SSH の Port Forwarding の機能を利用することによって, 特定のホストから通信しているように見せかけることができます. また,SSH は Port Forwarding の対象となるネットワーク接続を暗号化しますから, 様々な通信を安全に行うことが出来るようにもなります.

この方法の具体例については, FAQ の『4.8 ftp や POP などのサービスを安全にするために ssh が使えますか?』が大変参考になります.

ただし,SSH によって作成された Port Forwarding 用の通信経路は, クライアント上の全ての local process から接続することができます. したがって,「クライアント上の全ての local user が信用できる」という環境でなければ, Port Forwarding の利用はセキュリティ上の危険を増加させる可能性があります.


SSH を経由したメールの受信

fetchmail を使っている場合,~/.fetchmailrc に以下のように記述すると,Port Forwarding を利用してメールを取得できます.

poll server
  via localhost
  port 8236
  protocol apop
  preconnect 'ssh -f -P -C -L 8236:server:110 -l username server sleep 15 </dev/null >/dev/null 2>&1'
  username "username"
  password "password"

しかし,この方法では, 指定されたポート 8236 番が何らかの理由で使用中の場合にうまく接続できません. 遠隔サーバーに connect がインストールされていれば,以下のような別の方法も利用できます.

poll server
  protocol apop
  plugin "ssh -C -l username %h connect localhost %p"
  username "username"
  password "password"

Command not found とエラーが出る

普段使っているコマンドなのに,SSH 経由で実行すると, 以下のようにエラーメッセージが出力されて実行できないことがあります.

[client:~]% ssh server command
Command not found

この問題は,ログイン先のホストでシェルが実行されているかどうかの違いに原因があります. あるホストにログインして対話的に利用する場合には, 通常のシェル初期化ファイル(~/.bashrc~/.cshrc など)が読み込まれるので,環境変数 PATH は普段通りに設定されます. しかし,この例のように単にコマンドを実行するだけの場合は, ログイン先のホストではシェルは呼び出されないため,環境変数 PATH が設定されません. その結果,普段使っているコマンドなのに見つからない,ということが起こります.

SSH はコマンド実行時の環境変数を ~/.ssh/environment というファイルから読み込むようになっています.したがって,以下のコマンドを実行して, ~/.ssh/environment を用意しておくと, 普段通りの環境変数が設定されるようになり,コマンドもきちんと見つかるようになります.

[client:~]% ssh server
[server:~]% printenv | egrep '^PATH=' > ~/.ssh/environment

しかし,NFS などでホームディレクトリを共有している異種混在環境にログインする場合には, 上述のような静的な手法では対処できません.最近の OpenSSH であれば, ~/.ssh/rc というファイルにシェルスクリプトを記述することができ, そのような環境でも対応することができます. 以下は,私の使っている ~/.ssh/rc です.

if [ -d /var/lib/dpkg ]; then
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
else
    PATH=/usr/local/bin/X11:/usr/local/bin:/usr/bin:/bin:/usr/ccs/bin:/usr/ucb
fi

if read proto cookie && [ -n "$DISPLAY" ]; then
    if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
        echo add unix:`echo $DISPLAY | cut -c11-` $proto $cookie
    else
        echo add $DISPLAY $proto $cookie
    fi | xauth -q -
fi

なお,上記スクリプトの後半部分は,X11転送を処理するためのスクリプトです. 詳しくは sshd のマニュアルを参照してください.


SOCKS 経由の通信

OpenSSH には,単体で SOCKS 経由の通信を行う機能はありません. その代わりに,ProxyCommand というオプションを利用して, SOCKS サーバーに接続する外部プログラムを呼び出すことによって通信を行います.

ProxyCommand には,指定されたホスト・ポートに対する通信を標準入出力に redirect するコマンドを指定します.そのようなコマンドとして,後藤さんによって作られた connect を利用することができます.具体的には,以下のように ~/.ssh/config に設定します.

Host *
  ProxyCommand connect -S socks-server %h %p

防火壁を越えた通信

防火壁よりも外のマシンに防火壁の中からログインする場合には, 一旦,防火壁のマシン(firewall.example.net)にログインしなければならない, という状況は珍しくありません.そういう場合には,sshconnect の組み合わせを ProxyCommand として利用すると,簡単に防火壁を越えることができます. 具体的には,以下のように ~/.ssh/config に設定します.

Host *.example.net
  ProxyCommand none

Host *.*
  ProxyCommand ssh -C -x -e none firewall.example.net connect %h %p

逆に,防火壁よりも外のマシンから防火壁の中にログインする場合には, 以下のように ~/.ssh/config に設定します.

Host firewall.example.net
  ProxyCommand none

Host *.example.net
  ProxyCommand ssh -C -x -e none firewall.example.net connect %h %p

防火壁のマシンに connect が正式にインストールされていない場合でも, 個人のホームディレクトリ以下にインストールして適切に環境設定すれば, 利用できます.


Hostbased 認証

Hostbased 認証とは,登録済みのクライアントから接続があった場合は, そのクライアント上でのユーザー情報を信用して接続を許可する認証方式です. 多くのクライアントとサーバーが稼働しているサイトで適切に利用すると, ユーザーのパスワード入力の手間を減らすことができます. 設定手順は以下の通りです.

  1. クライアントのホスト鍵を作成しておきます.
    [client:~]# ssh-keygen -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key
    
    Hostbased 認証は,クライアントのホスト鍵,特に秘密鍵の秘匿性に基づいて認証を行っています. したがって,秘密鍵のファイル(/etc/ssh/ssh_host_rsa_key)の読み取り許可属性が適切に設定されていることを確認しておく必要があります.
    [client:~]$ ls -l /etc/ssh/ssh_host_rsa_key
    -rw-------    1 root     root          883 2002-01-01 12:00 /etc/ssh/ssh_host_rsa_key
    
  2. クライアント側の /etc/ssh/ssh_config に以下の設定を追加して,server に対して通信を行う時は Hostbased 認証を利用するように指定します.
    Host server
      HostbasedAuthentication yes
    
  3. サーバー側の /etc/ssh/sshd_config に以下の設定を追加して,Hostbased 認証を受け付けるように指定します.
    HostbasedAuthentication yes
    
    以下は Hostbased 認証と直接の関係はありませんが,一般ユーザーによる Hostbased 認証の乱用を禁止するために設定しておくべき項目です.
    IgnoreRhosts yes
    IgnoreUserKnownHosts yes
    RhostsAuthentication no
    RhostsRSAAuthentication no
    
  4. サーバーにクライアントの公開鍵を登録します. なお,DNS spoofing 攻撃を避けるため,クライアントのホスト名は FQDN で指定し, クライアントの IP アドレスも同時に指定しておくと良いでしょう.
    [server:~]# ssh-keyscan -t rsa client,address >> /etc/ssh/ssh_known_hosts
    
  5. クライアントからの接続を受け付けるように指定します.
    [server:~]# echo client >> /etc/ssh/shosts.equiv
    

これで,クライアントからサーバーに対してパスワード入力を省略して ssh 経由でログインすることができるようになっているはず‥‥でしたが, 私は以下のような問題で苦労しました.

OpenSSH-3.4p1 のバグ

OpenSSH-3.4p1 はバグのために,Hostbased 認証が正常に機能しないようです. パッチを適用する必要があります.

ProxyCommand との衝突

ProxyCommand と Hostbased 認証は共存できません. ProxyCommand設定されている状態で Hostbased 認証を行おうとすると,以下のようなエラーメッセージが表示されます.

% ssh server
userauth_hostbased: cannot get local ipaddr/name

OpenSSH-3.6p1 以降は ProxyCommand の設定を無効化することができるらしいので, Hostbased 認証を行うホストを対象として ProxyCommand を無効化するという設定を試してみたのですが,手元では正しく動作しませんでした. したがって,現在のところ簡単な解決策はなく, ProxyCommand を利用するホストを小まめに指定するしかないようです.

補助プログラムの実行許可属性

Hostbased 認証には,クライアントの秘密鍵の情報が必要です. 通常,秘密鍵は root 以外は読み出せないようになっていますから, OpenSSH は ssh-keysign という setuid root された補助プログラムを利用して認証を行っています.

補助プログラムが setuid root されていないと, 以下のようなエラーメッセージが表示されました.

% ssh server
could not open any host key
ssh_keysign: no reply
key_sign failed

Debian の場合は,dpkg-recongfigure ssh というコマンドを実行して, "Do you want /usr/lib/ssh-keysign to be installed SUID root?" という質問に「Yes」と答えると,適切な実行許可属性に設定されます. それ以外の環境では,以下のコマンドで修正できるでしょう.

# chmod u+s /usr/lib/ssh-keysign

商用 SSH との相互運用

久しぶりに,OpenSSH ではなく商用の SSH がインストールされている環境を使うことになったのですが, 公開鍵認証によるログインがうまくいかずに,かなり悩みました.

より詳しい情報は, 「OpenSSH と SSH の相互運用」や 「相互運用のための鍵管理」を参照してください.


設定内容のデバッグ

クライアント側の設定に問題があると考えられる場合は, -v オプションを指定してクライアントを実行した結果を調べると原因が分かることがあります.

% ssh -v server

サーバー側の設定に問題があると考えられる場合は, -d -d -d オプションを指定してサーバーを実行した結果が有用です.

# /etc/init.d/ssh stop
# /usr/sbin/sshd -d -d -d

SSH 対応版 impost

SSH 対応版 impost は,最早,メンテナンスされていません.

概要説明

メール/ニュースを送信する時の通信を, Port Forwarding を利用して中継できるように改造した impost です.

なお,impost は既に開発が終了しています. 後継版は imput と名前が変更され IM の一部となっています.

使用方法

SSH 対応版 impost では,3つのオプションが拡張されています.

-SMTPServers <str,>
-NNTPServers <str,>
従来の書式に加えて,server:local および server/remote:local の2つの書式が使えるようになっています.
-Clientname <str>
このオプションで指定されたホストにログインして,Port Forwarding を行います.

使用例

たとえば,次のようにオプションを指定すると,

-SMTPServer mail.example.net:8025
-NNTPServer news.example.net/6119:8119
-Clientname firewall.example.net

メールの場合は,

ssh -n -x -o BatchMode yes -L8025:mail.example.net:25 firewall.example.net

というコマンドを先に実行しておき,その上で localhost の8025番ポートにアクセスします. そうすると,mail.example.net からみると, この通信はあたかも firewall.example.net からの通信のように見えます. 同様に,ニュースの場合は,

ssh -n -x -o BatchMode yes -L8119:news.example.net:6119 firewall.example.net

となります.

localhost 上で使用するポート番号については,なるべく他のプログラムによって使用されないようなポートを指定してください. なお,指定されたポートが使用中の場合は,ポート番号を1つずつ順に増やして,未使用のポートを検索します.

その他

SSH は,通信路を暗号化すると同時に,その通信路を経由する通信を圧縮する機能を持っています. ~/.ssh/config に以下の設定を加えておくと,常に圧縮されるようになります.

Host *
  Compression yes
  CompressionLevel 9

Gnus と impost を組合わせて使用する場合は,以下のように設定してください.

(setq news-inews-program (expand-file-name "~/bin/impost")
      sendmail-program (expand-file-name "~/bin/impost"))

なお,~/.impostrc は,次のように設定しています.

mnews と impost の組合わせを利用する場合は,mnews によって付加された Path: ヘッダがおかしいというエラーメッセージが出力されて,送信できない場合があります. その場合は,このパッチを試してみてください. また,mnews と impost を組合わせて利用する方法について, 大塚さんが解説されています.

更新履歴
1997年12月31日
最初のバージョンを作成.
1999年9月25日
Perl4 でも動作するようにした.
エラー処理が不完全な部分を修正した.
指定されたローカルポートが既に使用されている場合は,順次検索するように改善した.
1999年9月26日 (fj に投稿した記事)
動作記録が重複して出力されていたバグを修正した.
SIGALRM のハンドラを回復するように変更した.
1999年9月28日
キュー処理および接続失敗の場合に,接続の後片付けを行うように修正した.
使用されたローカルポートが動作記録に残るように変更した.
ローカルポートを検索する時に再帰呼び出しをしないように変更した.
子プロセスが余分な改行を返した場合に対処するように変更した.
Message-ID の生成式を変更し,Message-ID からユーザー名が分からないように変更した.
1999年9月29日
複数のメッセージを同時に -ProcessQueue によって処理した場合のサーバーの動作記録が矛盾していたバグを修正した.
処理中のキューのファイル名を変更することにより,複数の impost を同時に実行しても安全なようにした.
メールとニュースに同じ記事を送信する場合,その記事に含まれる Newsgroups: ヘッダを X-Newsgroups: ヘッダに変換してメールとするように変更した.
ニュースサーバーが 435,437,440,441 を返した場合は,致命的エラーとするように変更した.
1999年11月24日
サーバーの指定が異なる複数のメッセージを同時に -ProcessQueue によって処理した場合に,サーバーをきちんと使い分け出来ていなかったバグを修正した.
中継ホストを指定するためのオプション -SSHserver を新設した. このオプションが省略された場合は,従来通りに -Clientname によって指定されたホストが利用される.
キューの形式を拡張した.

[Top] / [SSH について]