オフィシャルサイト: OpenSSH

sshd

移転しました

独自ドメインサイトへ移行しました。5秒後に

https://straypenguin.winfield-net.com/

へジャンプします。

telnet (23番ポート) や FTP サーバーなど、危なくて起こしておけない。代わりに、全ての通信が暗号化される SSH やそのサブコンポーネントである SCP, SFTP を使おう。ここでは、インストール行程は省き、sshd (サーバ) の設定と、そこへ接続するための数種のクライアントの設定を取り上げる。なお、sshdchroot 化する手順は chroot jail のページで詳しく述べている。

Table of Contents

sshd の設定

sshd の設定ファイルは /etc/ssh/sshd_config 。RedHat 系のデフォルト設定では少々セキュリティが甘いので、調整が必要だ。記述規則としては、大文字小文字の違いは「キーワード」では問題でないが、引数では区別される。 # で始まるコメント行と、空行は無視される。設定ディレクティブはかなり多いが、その中でも必須と思える項目だけを解説する。詳しくは man sshd_config していただきたい。 SCP, SFTPsshd のサブプログラムなので、それらもこのファイルによってコントロールされる。

なお、ファイヤーウォールはポート 22 の TCP パケットが通るようにしておかなくてはならない。 SFTP にしたところで、 FTP のように TCP 22 以外のポートを開くようなことはない。 iptables で言えば、サーバに対して宛先が TCP 22 のパケットと、それに ESTABLISHED な双方向のパケットを通せば OK だ。

sshd_config の主なディレクティブ

ディレクティブ設定例 引数
SyslogFacility AUTHPRIV syslog のどのファシリティ (チャンネルみたいなもの) にログを送るか。 /etc/syslog.conf の設定と相まって、(デフォルトの syslog.conf ならば) AUTHPRIV なら /var/log/secure にログが記録される。 LOCAL で始まるファシリティ、例えば LOCAL5 とし、/etc/syslog.conf
LOCAL5.*      /var/log/sshd_log
などと書いておけば sshd のログだけを /var/log/sshd_log に出力することもできる。
LogLevel INFO どこまで重篤度の高いログまでを記録するか。通常なら INFO が適当。認証がうまくいかない理由を突き止めたい時などは DEBUG にすると情報が得やすい。
PermitRootLogin no これは是非とも no にしたい。ssh 経由でいきなり root にログインさせるというのは服を一枚脱いで下着でいるようなものだ。リモートから root 権限の必要な操作をしたい時には、ユーザで接続を確立してから su - すべき。
StrictModes yes これはデフォルトの yes のままにする。ストリクトモードでは、接続の確立前に、ログインするユーザのホームディレクトリとファイルが誰にでも読めるパーミションになっていないかチェックし、合格しないと接続させない。
RSAAuthentication yes SSH プロトコル 1 において「RSA 非対称鍵 ver.1」を使用する。
PubkeyAuthentication yes SSH プロトコル 2 において「非対称鍵認証」を使用する。 SSH 2 では RSA と DSA が使える。
PasswordAuthentication yes プレーンテキストによるパスワード認証を許すか。上記 RSAAuthenticationPubkeyAuthentication も yes になっている場合の優先順位は、クライアントが決めることであって、サーバに決定権はない。
AuthorizedKeyfile .ssh/authorized_keys 公開鍵をリストしたファイルの場所を指定。ユーザ毎のホームディレクトリからの相対パス。
AllowUsers foo bar ... ログインできるユーザを限定できる。複数指定する場合はスペースで区切る。是非定義しておきたい。ワイルドカード `*' や '?' を使うこともできる。 ID ナンバーによる指定はできない。また user@host という形も可能。
AllowGroups group group ... 上記のグループ版。プライマリグループだけでなく、サブグループも検討される。
UseDNS no ホストが接続してきた際に DNS ルックアップを行い、IP アドレスから逆引きしたホスト名と、そのホスト名からリゾルブした IP が合致するかどうかチェックする。効果よりオーバーヘッドのほうが大きい気がする。特にクローズドなネットワークでは不要。
X11Fowarding no 使い道よりセキュリティリスクのほうが甚大。クライアントが Windows ならなおさら意味なし。ただし、サーバのローカルでしか使えないGUIユーティリティをリモートの X Window 上で使うには便利な機能だ。
UsePAM yes OS の備える PAM メカニズムを sshd の認証やアカウント管理に利用したい場合は yes に。 sshd 経由でシステムに接続するユーザを chroot したい時、PAM を活用して chroot を行うなら、これを yes にして、もうひとつのディレクティブ ChallengeResponseAuthentication を no にするとよい。

ローカル上からだけrootでの接続を許可する方法

サービス起動スクリプトや管理コマンドの中で、コマンドを ssh でラップすると便利な時がある。例えば、Linuxホストへ VNC で接続している時に、通常では起動できないシステム管理系の GUI ツール (system-config-*virt-manager 等) があるが、

user$ ssh -Y root@localhost virt-manager

ssh でラップしてやると起動できる (「よろず環境設定」のページも参照のこと)。そのためには、ローカルからローカルへだけは root での ssh ログインを許可する必要が出てくる。他のホストからは root ログインを禁止しつつこれを許可するには、sshd_configMatch ディレクティブを使うやり方 (RHEL/CentOS 6 以降) と、PAM で規制を掛けるやり方がある。

`Match' というディレクティブ が使えるのは openssh 4.3p2 からとなっているが、RHEL5 の opehssh-server には未実装。ソースRPM と パッチを入手してリビルドしようとしたが、Match を実装するためのパッチが標準のパッチ群と干渉して断念した。RHEL/CentOS 6 に載っている openssh 5.3 では Match ディレクティブが使用できる。Debian Etch の sshd でも Match が使えるらしい。

Matchで規制する方式

/etc/sshd/sshd_config の要点は下記の通り。ループバックインターフェイスでは IPv6 が有効になっているかも知れないので、::1 にもマッチさせるようにした方がいい。

...
PermitRootLogin no
...
Match Address 127.0.0.1,::1
    PermitRootLogin yes

PAMを使う方式

こちらは古めの openssh でも使えるオーソドックスな方法。RHEL/CentOS 6 の openssh 5.3 以降でも使える。この方式の場合、sshd_configPermitRootLoginyes にしておく必要がある。

/etc/pam.d/sshd を修正

pam_access.so を `account ... system-auth' より上に挿入。

/etc/pam.d/sshd

auth       include      system-auth
account    required     pam_nologin.so
account    required     pam_access.so accessfile=/etc/security/access_sshd.conf
account    include      system-auth
password   include      system-auth
session    optional     pam_keyinit.so force revoke
session    include      system-auth
session    required     pam_loginuid.so
/etc/security/access_sshd.conf を作成

/etc/security/access_sshd.conf

+ : ALL EXCEPT root : ALL
- : root : ALL EXCEPT 127.0.0.1 

クライアントからの接続

認証方法について

クライアントの設定や操作に共通することなので、ここで取り上げておく。

SSH の認証方法の主なものとしては、プレーンパスワードによる方法と、非対称鍵認証 (パブリックキー認証, 公開鍵認証とも呼ぶ) がある。プレーンパスワードによる認証の場合、ログインの際のやりとりは暗号化通信が確立する前に行われるわけであり、生のパスワードがネットワークを流れるため盗聴の恐れがある。それに対して、非対称鍵による認証では、生パスワードがネットワークを流れることはなく、より高い安全性が確保できる。プレーンパスワードよりも準備が少しだけ面倒だが、仕組みさえ理解してしまえばそんなに難しい作業ではない。以降のクライアントの説明では、主に SSH 2 の RSA 認証について扱う。

SSH にはプロトコルバージョン 1 と 2 があり、現行の sshd はその両方のプロトコルで接続を待ち受けている。なぜそんなことがここで問題となるかというと、SSH 1 と SSH 2 では、認証方法や鍵ファイルの置き場所や標準のファイル名が違うから。それをまとめたのが下の表だ。

プロトコル 対応する非対称鍵
方式 秘密鍵標準ファイル名 方式 秘密鍵標準ファイル名
SSH 1 RSA1 identity - -
SSH 2 RSA id_rsa DSA id_dsa

非対称鍵認証は、その名の通り、内容の異なる 2 個ひと組の鍵を使用する。秘密鍵 (プライベートキー) と 公開鍵 (パブリックキー) だ。 SSH 通信に関する限り、鍵の所有者はクライアント側のユーザ (サーバではない!)。プライベートキーは基本的に上表のファイル名でクライアント側に格納し、それ自体は決して誰にも見せたり送ったりしない。一方、パブリックキーは、接続先となる sshd サーバ上にある当該 UNIX ユーザのホームディレクトリに置くこととなる。

鍵の作成と配置の手順 (RSA)

下に紹介しているクライアントソフト WinSCP では PuTTYgen という鍵ペア作成ユーティリティが付属しているが、それで作った公開鍵では Fedora Core 3 の OpenSSH 3.9x サーバで認証が成り立たなかった。Linux クライアントからサーバへ接続したいなら、以下の手順は Linux クライアント上で行う。Windows のクライアントプログラムから接続したい場合も、鍵ペアは Linux を使って作ったほうが確実だ。

鍵ペアの作成

作成には ssh-keygen というプログラムを使う。作業は、これから接続相手にしようとしている Linux ユーザ ("hoge" としよう) で行う。

hoge$ cd ~
hoge$ mkdir .ssh
hoge$ cd .ssh
hoge$ ssh-keygen -t rsa -b 2048 -f hoge_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
...

ssh-keygen への引数のうち、緑色の要素は省略してもいい。鍵の長さを指定する -b 2048 はたいていデフォルトだ (かつては 1024 だった)。また、 -f file_name を指定しなければ ssh-keygen が訊いてくるが、追加で別のペアを作成する際にも確実な、この方法を勧める。passphrase のところでは、特別な理由がない限りパスフレーズを入れる。「パスワード」と異なるのは、スペースも含めたあらゆる文字が使え、長さも事実上無制限なこと。ただしあまり長くしても憶えられないので、一般的には 10 から 30 文字が適当とされる。この passphrase は鍵のランダムな文字列を生成するためのタネ=ランダムシードとして使われ、実際にプライベートキーとパブリックキーを照合する際にも必要となるので、憶えておかなくてはいけない。後で ssh-keygen -p で変更することはできるが、その際にも旧パスフレーズの入力が必要で、忘れたら新たにペアを作り直すしかない。

何かの理由でどうしてもパスワードなしでログインできるようにしたい場合には、鍵の作成時の passphrase プロンプトで何も入力せずにエンターすれば、パスフレーズなしのプライベートキーができる。

接続の時に「パスワードをいちいち入力しなくていいのがパブリックキーの利点じゃないの?」と思っている人は、ちょっと勘違いだ。クライアント側にある秘密鍵を「解読」してサーバ側の公開鍵と照合するためには、passphrase で入力したパスフレーズが要る。しかし、この時点でタイピングするパスワードは、クライアント側でのみ使われ、ネットワークには流れない。あくまでも、生パスワードをネットワークに流さないのが非対称鍵のメリットなのだ。いちいちパスフレーズを入力したくない場合は、各クライアントソフトに付属している「認証エージェント」ソフトを使う手がある。

鍵の配置とパーミション調整

上の手順で /home/hoge/.ssh/ ディレクトリに hoge_rsa (プライベートキー) と hoge_rsa.pub (パブリックキー) の鍵ペアができたはず。便宜上別のマシン上で作った場合は、分かりやすいようにパブリックキーの最後のコメント部分 (赤字) を書き換えておくことをお勧めする。この部分は認証には影響しないコメントなので、クライアントマシンのホスト名に合わせて書き換えておこう。

ssh-rsa oa8w/3oj:oiazps....poujaosje= hoge@host.domain.cxm

念を押すが、鍵の持ち主はあくまでもクライアントだ。便宜上 Linux サーバ上で作成した場合には、混乱を避けるために hoge_rsa, hoge_rsa.pub とも本来のクライアントのほうへコピーし、サーバ上の秘密鍵 (hoge_rsa) は削除しておく。

次に、公開鍵 /home/hoge/.ssh/hoge_rsa.pub の内容を、サーバ側の同ディレクトリの authorized_keys というファイル (公開鍵を羅列するためのファイル) に加える。手作業でやってもいいが、最近の RedHat系 Linux ディストリビューションの openssh-clients パッケージには、ssh-copy-id というツール (シェルスクリプト) が付属している。

[ssh-copy-id でやる場合]

ssh-copy-id は、サーバへ ssh 接続し、サーバ側のホームディレクトリに適切なパーミションで .ssh/ ディレクトリを作り authorized_keys ファイルに公開鍵を書き加えるところまでを一気にやってくれる。この時、サーバへの接続はプレーンパスワード認証で行われるので、後々パブリックキー認証しか使わないつもりでも、この作業の段階では、サーバの sshd_configPasswordAuthenticationyes にしておく必要がある。クライアント側のユーザ名とサーバ側のユーザ名が異なる場合は、SERVER のところを USER@SERVER にすればいい。コマンドはクライアント上で実行する;

hoge$ cd ~/.ssh
hoge$ ssh-copy-id -i hoge_rsa.pub SERVER

[手作業でやる場合]

Linux クライアント自体の上でキーを生成した場合は、サーバ側のホームディレクトリ下に .ssh/ ディレクトリを作成し、hoge_rsa.pub を一旦そこへコピーしておく。
そして、

hoge$ cat hoge_rsa.pub >> authorized_keys
hoge$ rm hoge_rsa.pub   (もう要らないので捨てる)

サーバ側ファイルのパーミションを整える;

hoge$ chmod 700 /home/hoge/.ssh            (755でも可)
hoge$ chmod 600 /home/hoge/.ssh/authorized_keys  (644でも可)

クライアント側の調整はそれぞれの OS、ソフト毎に説明する。

Windowsクライアント to Linuxサーバ

Windows で使えるフリーの SSH クライアントアプリケーションの中から、 WinSCP, UTF-8 TeraTerm Pro with TTSSH2 について書いておく。

WinSCP

WinSCP は、グラフィカルインターフェース上で簡単にファイルのやりとりができる SFTP/SCP クライアントプログラム。使い心地は FTP とほとんど変わらず、パーミションの変更はもちろん、サーバ側のファイルをテキストエディタで覗いたり、直接編集したり (一旦ローカルのテンポラリに落とすわけだが)、およそ必要とされるファイル操作はすべて行える。簡易型 (パスワードプロンプトに答えるなどのインタラクティブなやりとりはできない) ながらターミナルも付属している。

WinSCPパブリックキー認証を使う確実な方法は、 Linux 上で作成したプライベートキーを、WinSCP 付属ユーティリティの PuTTYgen でインポートするやり方だ。

メニュー Conversions > Import key で、OpenSSH のプライベートキーを指定し、パスフレーズをタイプすると、読み込まれてこの図のような状態になる。そして Save private key ボタンを押すと、PuTTY 固有のフォーマットに変換して保存される (保存名を仮に hoge_rsa.ppk としよう)。これで第一段階は完了だ。

そうしたら、WinSCP を起動し、ブックマークのようなものに設定を登録していく。まず セッション グループを左図のようにする。秘密鍵欄は、パスワード欄を空にしないと使用可能にならない。プロトコル選択は、真ん中の SFTPの代替を許可 がいいだろう。サーバで SFTP がサポートされていれば SFTP が、そうでなければ SCP が利用される。

SSH グループの 認証 タブは、最初のプロンプトにパスワードで応答 のチェックを外す。このタブのそれ以外の項目は筆者もまだテストが充分でない。

実際にどういう接続が成されているかは、接続してから、メニュー コマンド > サーバ・プロトコル情報 で確認できるし、もちろんサーバ側のログでも読み取ることができる (その際はサーバの /etc/ssh/sshd_configLogLevel= を上げておくとより詳しく分かる)。

キー認証エージェントの使用

WinSCP には pageant というキー認証エージェントが付属している。 pageant は起動するとタスクトレーに常駐し、パスーフレーズをいちいち入力する手間を省いてくれる。使い方は説明するまでもないだろう。機能的には Linux ssh クライアントの ssh-agent に非常に近いようだ。

UTF-8 TeraTerm Pro with TTSSH2

UTF-8 TeraTerm Pro with TTSSH2 は、ターミナルソフト TeraTerm を拡張したもので、telnet や シリアルに加えて SSH 接続もできる。かなり以前から、オリジナルの TeraTermTTSSH という拡張ライブラリを加えることで SSH 接続は可能だったが、そちらはプロトコル 1 にしか対応していなかった。 TTSSH2 は単体でダウンロードすることもできるが、UTF-8 TeraTerm でしか動かない点に注意。古い TeraTerm も使いたい場合には、別ディレクトリにインストールすれば問題ない。

UTF-8 TeraTermパブリックキー認証を使うには、ちょっとコツが要る。やり方はふたつある。

接続の都度、認証ファイルを選ぶ方法

TeraTerm 立ち上げ後に出る新規コネクションダイアログで接続先ホストと SSH バージョンを入力して OK すると、次にこの認証画面になる。こちらのやり方の場合、プライベートキーは必ず id_rsa という名前 (DSA鍵なら id_dsa) で置いておかなくてはならない。他の名前では、 Private key file ボタンで選択できず、ファイル名を直接タイプしたとしても読み込みエラーとなる。認証画面の入力箇所はこんな感じ。

マクロを使う方法

こちらの場合は、キーファイル自体の名前は必ずしも id_rsa である必要はない。ただし、ロングファイルネームを使ったフォルダに置くとうまくいかない。まず、 UTF-8 TeraTerm をインストールしたディレクトリに、次のようなマクロファイル (ssh2hoge.ttl としよう) を用意する。 "connect" マクロコマンドに "keyfile=" が与えられた場合には、 "passwd=" はプライベートキーをローカル上で読み解くためのパスフレーズだと解釈される。

hostname = '192.168.1.4'
username = 'hoge'
keyfile = 'D:\SSH\hoge_rsa'
passphrase = 'aiueokakikukeko'

msg = hostname
strconcat msg ':22 /ssh /2 /auth=publickey /user='
strconcat msg username
strconcat msg ' /passwd='
strconcat msg passphrase
strconcat msg ' /keyfile='
strconcat msg keyfile

connect msg

そうしたら UTF-8 TeraTerm を起動し、メニュー Control > Macrossh2hoge.ttl を選べば接続完了だ。

Linuxクライアント to Linuxサーバ

つまり OpenSSH クライアント ssh から OpenSSH サーバ sshd へ接続する場合。

SSH クライアントの設定

グローバルな設定ファイルは /etc/ssh/ssh_config 。ここで設定した内容は、ssh にコマンドラインで指定したり (優先順位 1)、各ユーザの ~/.ssh/config (優先順位 2) でオーバーライドできる。デフォルトから変更したいディレクティブは少々しかなく、ほぼそのままで使える。

鍵の配置

クライアント側の自分の ~/.ssh ディレクトリに、秘密鍵 (前述の鍵生成例では hoge_rsa) を id_rsa の名前で置いておくのが最も標準的なやり方。パーミションは以下のように。

~/.ssh/      700  (または 755)
      id_rsa 600  (これは必ず 600)

サーバへの接続は、ssh なら;

hoge$ ssh remote_user@server_name

または、

hoge$ ssh -l remote_user server_name

とコマンドして、秘密鍵を読むためのパスフレーズを入力すれば、サーバ側へログインできる。 SFTP したいなら;

hoge$ sftp remote_user@server_name

で、 FTP そっくりのインタラクティブセッションが始まる。

ともに、クライアント側でログオンしているユーザとサーバ側のユーザが同じなら`remote_user@' や `-l remote_user' は省略できる。また、他の SSH サーバや他のユーザへログインする機会があって、秘密鍵を複数使い分けたい場合があるが、その際は、それらの鍵を id_rsa 以外のファイル名で貯えておき -i another_rsa でファイル指定すれば使える (下記の「エージェント」を使ったほうがもっと楽)。

キー認証エージェントの使用

RedHat系の SSH クライアントパッケージ openssh-clients には、ssh-agent というキー認証エージェントが付属している。これは、認証に使いたいプライベートキーファイルをメモリ上に保持する。パスフレーズの入力はこの読み込み時だけで済み、以後、ssh が認証を要求した際には、本来 ssh が行うはずの認証処理自体を ssh-agent が肩代わりし、結果だけを ssh に返す (よって、プライベートキーそのものがローカルじゅうに晒されることはない)。 ssh-agent は、 X window セッションを開始する度に /etc/X11/xinit/xinitrc-common スクリプト内から呼び出され、バックグラウンドに常駐する (NOTE参照)。その際 ssh-agent/tmp/ssh-xxxxxx/agent.<ppid> に UNIX ドメインソケットを開き、以後同じXセッション上で開くすべてのウィンドウがその「クライアント」になるのだが、ソケットファイルは X を 開始したユーザにしか読めないパーミションになっているため、鍵が他のユーザに使われることはないそうだ (ssh-agent の man より)。そのソケットと通信できるのは X セッションをログオフするまでであり、同じユーザでも、一旦 X をログオフしたらさっきの ssh-agent とはもう通信できない。

NOTE: Fedora Core 4 以降、起動の仕組みが少し変わった。今のところ分かっているのは xdm (グラフィカルログイン) 使用時についてだけだが、 /etc/X11/xinit/xinitrc-common の中では $SSH_AGENT という変数を定義するだけであり、実際の ssh-agent 起動処理は /etc/X11/xinit/Xsession で行われるようになった。 xinitrc-commonXsession の中でインクルードして読まれる。

プライベートキーを ssh-agent に読み込ませるには、これまた別のバイナリである ssh-add というプログラムを使用する。

hoge$ ssh-add private_key_file

すると、そのキーに対するパスフレーズを訊かれるのでタイプする。キーはいくつでも追加で読み込むことができる。オプションで指定できる操作としては;

などがある。

ssh-agent の問題点

※ Fedora Core 3 あたりまでの問題であり、最近のディストリビューションでは解消されているようだ。

前述したように、 ssh-agent は X セッションを開始する度に起動する。そのため、 X のログオフ/ログオンを繰り返すと ssh-agent プロセスがその数だけ起動したままになり、どんどん溜まっていってしまうのだ。ひとつの対処法としては、各ユーザのホームディレクトリにある .bash_logout に次のようなコマンドを追加する:

SSHA_PID=$(ps x |awk '/ssh-agent/ && !/awk/ {print $1}')
[ -z "$SSHA_PID" ] || kill -TERM $SSHA_PID

これで、そのユーザがマシンから (「Xセッションから」ではない) ログアウトする際に、それまでに溜まったそのユーザ名義の ssh-agent が全部終了できる。ただしこれは xdm を使っていない (つまりシステムの起動 init レベルが 3) の時だけ有効な手段で、ランレベル 5 の場合には通用しない。 X グラフィカルログインを使っている人は /etc/X11/xdm/TakeConsole に同様の仕掛けをすれば良さそうだが、今のところ成功していない。