多くのLinux/Unix系サーバーではSSHでリモートログインしサーバー管理をするというパターンになっているかと思いますが、その際のSSHはパスワード認証が用いられていることが多いと思います。
これはもっとも手軽な認証方ですが、パスワードの総当り攻撃なんかを受けて看破される可能性があります。
そこでよりセキュリティをより高めるため、SSHでの公開鍵認証の設定を行ってみました。
SSHの公開鍵認証って?
公開鍵認証方式(公開鍵暗号を用いた認証方式)というのは、公開鍵(暗号するための鍵)と秘密鍵(複合するための鍵)の2つの鍵を用いて認証を行う方法です。
公開鍵は広く一般に知られて良いもので、その鍵を使ってデータを暗号化します。
暗号化されたデータは、その公開鍵とペアで作った秘密鍵でしか複合できません。
なので、秘匿性の高いデータをやり取りしたい場合、まずデータを受け取りたい側(クライアント)の公開鍵を使って、データを送信する側(サーバー)がそのデータを暗号化し、クライアントに送信します。
そして、クライアントは送られてきた暗号化データを自分の秘密鍵を使って複合して読み取るわけです。
たとえその暗号化された秘匿データが他人に渡って、秘密鍵を知りえない限り複合できません。(厳密に言えば複合できる可能性が極めて低い)
秘密鍵が複合鍵となっている特性上、必ず受信側の公開鍵を使うことになります。
SSHで公開鍵認証を行う場合、クライアント側で公開鍵と秘密鍵を作成し、公開鍵をSSHで接続するサーバー側に渡しておきます。
クライアントからSSHの接続要求をすると、サーバー側はクライアントの公開鍵を使って、暗号化したデータを送ります。
クライアントは、その送られてきた暗号化データを自分の秘密鍵を使って複合化し、サーバー側に送りなおし、サーバー側では送ったデータとクライアントから返されたデータが一致するかで認証を行います。
サーバー側から暗号化した質問の答えを正確に答えられるということは、その公開鍵とペアの秘密鍵を持っているから安全なやつだ、という判断で認証しているわけですね。
サーバー側の公開鍵認証設定
※ 公開鍵暗号の方式は、RSAとDSAがありますが、ここではRSAをベースに書いています。
まず、サーバー側で公開鍵認証が行えるようになっているかを確認します。
確認するのは、下記の3つのオプションです。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
上記が設定されているか(デフォルトでもyesなのでコメントアウトされててもOK)を確認します。
設定を変更した場合は、sshdデーモンを再起動しておきます。
Windowsクライアント(TeraTerm)を使った鍵作成と認証
次に、クライアント側の設定で、公開鍵と秘密鍵を作ります。
TeraTermには公開鍵・秘密鍵の作成機能があるため、その機能を使えば簡単に鍵の作成が行えます。
TeraTermを起動した後に[設定] → [SSHキー生成] メニューを開きます。
キーの種類がRSAになっていることを確認し、「生成」ボタンを押します。
次に「キーのパスフレーズ」「パスフレーズの確認」欄に適当なパスフレーズを入力し「公開鍵の保存」「秘密鍵の保存」ボタンを1度ずつ押し、鍵を保存します。
秘密鍵は失うと認証できなくなりますし、盗まれると他のホストからログインされてしまう可能性がありますので安全な場所に保管しておきます。
※ パスフレーズを忘れると秘密鍵が読めなくなりますので注意しましょう。
これで鍵ができましたので、次に公開鍵(id_rsa.pub)をサーバーに保存します。
ログインするユーザーのホームディレクトリに.sshというディレクトリがあるかと思うので(ない場合は一度SSH接続すれば作成されます)、そのディレクトリ以下にそのまま保存します。
保存した後は、権限を700に変更しておきます。
$ chmod 700 id_rsa.pub
次に保存した公開鍵をauthorized_keysファイルへも追記しておきます。
authorized_keysファイルは、サーバー側のSSHの設定ファイルのAuthorizedKeysFileオプションのパスに保存し、権限を644に変更します。(デフォルトだと同じ.sshディレクトリ)
$ cat id_rsa.pub >> authorized_keys
$ chmod 644 authorized_keys
※ それぞれのファイルは、接続するユーザーの所有者・グループになっている 必要があります。
もし複数の公開鍵を登録したい場合は、同じファイルに鍵情報を追記していきます。
これで、設定が完了したので、クライアントから接続してみましょう。
TeraTermを立ち上げ、公開鍵を設定したサーバーを指定します。
.sshディレクトリにに公開鍵を設定したユーザー名と鍵を生成した際のパスフレーズを入力し、「RSA/DSA鍵を使う」をチェックし、保存した秘密鍵を指定します。
そして接続を押せば、公開鍵認証方式でログインできます。
実際にサーバー側のログ(/var/log/secure)を見てみると
May 14 21:59:36 localhost sshd[2185]: Accepted publickey for hoge from 192.168.0.100 port 2034 ssh2
May 14 21:59:36 localhost sshd[2185]: pam_unix(sshd:session): session opened for user hoge by (uid=0)
というようにpublickey(公開鍵認証)でログインしている 情報があるかと思います。
Linuxクライアントを使った鍵作成と認証
次は、Linuxクライアントから認証を行ってみます。
基本的には同じような設定をすることになるのですが、鍵の作成やコマンドラインからの接続方法などはWindowsと異なりますので。
まず、鍵の作成からですが、これはssh-keygenコマンドを使って作成します。
$ ssh-keygen -t rsa -C "hoge@192.168.0.100"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hoge/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hoge/.ssh/id_rsa.
Your public key has been saved in /home/hoge/.ssh/id_rsa.pub.
The key fingerprint is:
65:ad:a7:e0:85:5a:b5:85:9e:0d:5b:61:bc:ca:25:cc hoge@192.168.0.100
鍵を作成するユーザーと実際に接続するユーザーが同一であれば、最後の「-C」オプションは必要ありませんが、異なる場合は接続するユーザー名とIP(またはホスト名)を指定して実行します。
途中キーの保存場所とパスフレーズが聞かれるので適切なものを指定しておきます。
鍵の作成場所は最後に表示される(上記の場合は、/home/hoge/.ssh/)ので、より適当な場所があれば移動させて安全に管理するようにしましょう。
これより先のサーバー側への公開鍵の設定は、先ほどのWindowsの場合と同様です。
公開鍵(id_rsa.pub)をサーバー側のログインするユーザー(鍵を作成したユーザー、または鍵を作成する際にコメントに入れたユーザー)の.sshディレクトリ以下に保存しておきます。
これで設定が完了したので、実際に接続してみます。
$ ssh -l hoge -i .ssh/id_rsa 192.168.0.100
Enter passphrase for key '.ssh/id_rsa':
「-i」オプションを付け、秘密鍵のパスを指定します。
実行後は、パスフレーズが求められるので鍵を作成した際に指定したものを入力します。
SSHのセキュリティの考察
ここからは若干雑談ベースで。
サーバーがSSHのどういった認証方式が利用可能なのかは、デバッグモードのオプションをつけて実行してみるとわかったりします。
$ ssh -v hogehost
- snip -
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /home/hoge/.ssh/identity
debug1: Offering public key: /home/hoge/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Offering public key: /home/hoge/.ssh/id_dsa
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: keyboard-interactive
Password:
多くの情報が出てきますが、その中の「Authentications that can continue:」という行に、このサーバーで認証可能な方式が表示されます。
publickeyは公開鍵認証方式、passwordはパスワード認証、keyboard-interactiveはチャレンジ・レスポンス認証 が許可されているということがわかります。
なので、パスワードの総当り攻撃とかは、そのサーバーがパスワード認証が許可されているかどうかが事前にわかるので効率的に行えたりすることもわかります。
じゃあ、そういうの受け付けなくするために、公開鍵認証だけ許可するようにするということもできます。
- パスワード認証とチャレンジ・レスポンス認証を許可しない設定
PasswordAuthentication no
ChallengeResponseAuthentication no
これで、実際に接続してみたら
$ ssh -v hogehost
- snip -
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Trying private key: /home/hoge/.ssh/identity
debug1: Offering public key: /home/hoge/.ssh/id_rsa
debug1: Authentications that can continue: publickey
debug1: Offering public key: /home/hoge/.ssh/id_dsa
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
Permission denied (publickey).
debug1: Calling cleanup 0x8062d60(0x0)
というように、公開鍵がサーバー側に登録されていない限り、いきなり接続を拒否られたりします。
この状態だと秘密鍵を持つPCからだけしか接続できなくなり、安全だということになりますが、その秘密鍵をなくしたり、PCが飛んだりしたら接続の方法がなくなってしまいます。
パスワード認証は、個人を特定して認証する方式ですが、公開鍵認証はホストを特定して認証する方式 になりますので、そのホストの管理が重要になってきます。
もちろん鍵をバックアップしておくということは必要ですが、秘匿性の高い鍵情報を分散させすぎると鍵が漏洩するリスクも高まってきます。
なので、このような鍵認証はあまり個人が管理するサーバーには向かない方式なのかと思います。
その個人がいなくなったり、鍵を紛失したらどうしようもなくなります。
複数人の管理者がいるなら、他の管理者に再登録してもらうことも可能ですが、1人だと代替案が何もなくなってしまうリスクがあるからです。
あとは、SSHの設定だけで考えるのではなく、N/Wによる制限(TCP Wrappers、iptablesとか)とか、以前に書いた「超制限付きユーザーの作り方
」のようにほとんど何もできないユーザーを作って、そいつをログイン専用ユーザーにする とか、そんな対策も重要になってくるかなと思います。