OpenSSH ホストベース認証あれこれ。 | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

簡単に言えば、SSHの通信の際に接続もとのホストを限定しておいてパスワードなしにログインさせる事を可能にする認証方式です。

通常の運用で接続する際は、パスワード認証を行っておいた方が無難ですが例えば、rsyncと組み合わせてバックアップを取るなどバッチ処理系のスクリプトと組み合わせると運用面でメリットが色々あります。


設定方法は下記の通り


クライアント側(ホストベースで接続する側)の設定


SSHの設定ファイル(ssh_config )を編集


場所は、ディストリビューションやインストール方法(ソースorパッケージ)で異なります。
「 /usr/local/etc/ssh_config 」や「 /etc/ssh/ssh_config 」など


エディタで設定ファイルに下記の行を追記


EnableSSHKeysign yes
Host hogehoge*
HostbasedAuthentication yes
PreferredAuthentications hostbased,publickey,keyboard-interactive,password
UsePrivilegedPort yes

「Host hogehoge*」の箇所がホストベース認証で接続する先のホスト名になります。

「*」は任意の文字列。つまりホスト名が「hogehoge01」でも「hogehoge-foo」でもよい事になります。

「Host *」と書くと全てのホストに対してホストベース認証が優先的に行われます。


「PreferredAuthentications」は、認証方式の優先度です。前に書くほど優先的になりそれが失敗した場合は、次の認証方式で接続されます。


keybooard-interactiveとpasswordはどちらも対話式でパスワードを入力するものですが、その違いはこちら


サーバー側(ホストベースで接続される側)の設定


1. SSHデーモンの設定(sshd_config )ファイルを編集


場所は、ssh_configと同様の場所


下記の箇所のコメントを解除するか追記する


HostbasedAuthentication yes
IgnoreRhosts no


2. 編集後にSSHデーモン(sshd)の再起動を行う


例えば、自動起動スクリプトを利用して


/etc/init.d/sshd restart



3. ホストベース認証を許可したいユーザー(hogeuser)の.shostsファイルを編集


su - hogeuser
vi .shosts

.shostsファイルは、そのユーザーのホームディレクトリ直下に配置します。

.shostsファイルの内容は、ホストベースで接続してくるホスト名とそのユーザーを記載します。

(ユーザー名は省略可能です)


hogehost hogeuser
192.168.0.100

上記だと「hogehost」のホスト名から「hogeuser」のユーザーによるホストベース認証を許可します。

また、「192.168.0.100」のIPからも同様です。


ファイルを作成した後は、パーミッションをそのユーザーだけしか閲覧できない様に変更しておきます。


chmod 600 .shosts

※ これをしておかないとエラーが出る場合があります。

  (下部のうまくいかない時は・・・」参照)



4. クライアント側(ホストベース認証で接続する側)に対してSSH接続


クライアント側の公開鍵をサーバー側に保持しておくために、一度サーバー側からクライアント側にSSH接続をおこなっておきます。


ssh hogehost

これでホームディレクトリ直下の「.ssh」ディレクトリ以下に「known_hosts」というファイルができ、その中に「hogehosts」の公開鍵が埋め込まれます。


初めてそのホストに対してSSH接続した際は、その公開鍵を登録してよいかどうかの確認メッセージが表示されます。

クライアント側の公開鍵が変わった場合は、この「known_hosts」ファイルを消すか、その中の該当のホスト名の公開鍵が書かれている行を消せばよいです。


これで準備が完了です。

クライアント側から、指定のユーザー(.shostsファイルを作成したユーザー)でSSH接続するとパスワード要求なしで接続できるはずです。



□ うまくいかない時は・・・


まず、SSHをデバックモードで接続してみましょう。


ssh -vvv hogehost

接続の際のログが端末に表示されているはずです。

この中で問題になっていそうな箇所を特定しましょう。


- Remote: Bad file modes for /XXXX/XXXXX/.shosts というメッセージが出る


表記の通り、.shostsファイルのパーミッションが悪いと言うメッセージです。


.shostsのパーミッションを、そのユーザーだけしか読めないように変更しておきます。

(「サーバー側の設定」の3.を参照)



- rootユーザーでホストベース認証が行えない


サーバー側の設定ファイル(sshd_config)内で、下記の記述が無いか確認します。


PermitRootLogin no

この記述は、rootユーザーのSSH接続を許可しない設定です。

これを「yes」に変更すれば(変更後はsshdデーモンの再起動が必要)、接続できるようになりますがそもそもrootでホストベース認証など行わない方が無難です。


- 何故だかうまくいかない場合 其の一


クライアント側の設定で、接続するホスト名がちゃんと名前解決できるか確認してみましょう。

(/etc/hostsを見直すか、DNS登録されている内容を確認)


また、サーバー側でもクライアント側のホスト名がちゃんと名前解決できないと接続できません。

無難なのは、サーバー側とクライアント側で同一のホスト名は同一のIPを返すように記述しておく事です。

こちらも参考にしてみてください。Linux ネットワークの設定確認



- 何故だかうまく行かない場合 其の二


接続する際に指定しているホスト名が、クライアント側の設定ファイル(ssh_config)の「Host XXXXX」の箇所に記載したホスト名とイコールかを確認します。


/etc/hostsに書いたホスト名は、大文字でも小文字でも名前解決してくれますがssh_configの「Host XXXXX」に書いたホスト名は、その通りの記述でないとそもそもホストベース認証を行ってくれません。


例) ssh_config


Host HOGEHOGE*

と書いた場合、


$ ssh HOGEHOGE ・・・ ○

$ ssh hogehoge ・・・ ×



- 接続時に下記のエラーが出る場合


get_socket_address: getnameinfo 8 failed
userauth_hostbased: cannot get local ipaddr/name


詳しい原因は、不明なのですがNICが2枚刺さっている環境で、そのNICに対して同一セグメントのIPを割り振っている場合、NIC1の方に割り振ったIPアドレスを/etc/hostsで名前解決できない場合に起きました。


例) クライアント側の環境

NIC1 192.168.0.10

NIC2  192.168.0.11


の環境で


/etc/hostsに


192.168.0.11 hogehost


なんて書き方をしておき、ホストベース認証を行うとエラーが出る。


192.168.0.10 hogehost


にしておくとエラーが出ない。

※ サーバー側の/etc/hostsにも同様の記述が必要。


そもそもエラーの内容は、接続の際に呼ばれるgetnameinfo 関数内で「NI_NAMEREQD」というエラーが出ているため。

「getnameinfo 8 failed」の「8」と言う数字は、下記のファイルで定義されているようです。


netdb.h

define NI_NAMEREQD 8 /* Don't return numeric addresses. */


- デバッグモードで下記のメッセージが出る 其の一2007.01.16追記


debug1: No more client hostkeys for hostbased authentication.
debug2: we did not send a packet, disable method

「何故だかうまくいかない場合1」と同様にクライアント側とホスト側で正常に名前解決ができていない可能性があります。(または、クライアント側とホスト側で異なる名前解決をしてしまう)


多くの環境では、まずhostsファイルで名前解決されるように設定されているかと思いますのでhostsファイルの内容がクライアント・サーバー側双方で相違ないか確認してみます。

また、hostsファイルには一つのIPに対して複数のホスト名を指定できますが、一番左に書いたホスト名が正式なホスト名とみなされるため、実際に接続しに行く時に指定したホスト名とサーバー側で接続されたときに解決されるホスト名が異なってくる可能性があります。

(ホスト名だけで指定しても、実際はFQDNで解決されるなど)


ホストベース認証時には、接続ユーザーのホームディレクトリにある「.ssh」ディレクトリ内の「known_hosts」内に接続もとの鍵が登録されているかチェックを行いますが、この接続もとのホスト名が、サーバー側で解決されるホスト名と同一かもチェックしておく必要があります。

実際ホスト名だけで接続に行っても、サーバー側ではFQDNで接続元が解決されてしまったらこの「known_hosts」ファイル内に記述がなく接続できないと言う事になるからです。



- デバッグモードで下記のメッセージが出る 其の二2007.01.16追記


debug2: ssh_keysign called
debug1: permanently_drop_suid: XXX

※ XXXは接続したユーザーのUIDが入る


OpenSSHのバージョンを4.4p1にした時から出だしたエラーなのですが、このメッセージ自体は特に問題ないようです。

接続が成功しても出ますので。