はじめに

こんにちは。 KMC OB の nojima です。 最近は東京で社会人をやってます。

この記事はKMCアドベントカレンダー2013の13日目の記事です。 昨日の記事はnon117さんの ssh_config でした。

今日は authorized_keys について書きたいと思います。

認証

最近は乗っ取ったPCを使って Bitcoin をひたすら採掘するのが流行っているそうです。 怖い世の中ですね。

ところで、SSH でサーバにアクセスできるようにしていると、結構頻繁に不審なユーザ(というかボット)からのログイン試行があります。 当然、このようなログインは絶対に成功させてはいけません。 逆に言うと、サーバに SSH ログインするためには、自分がそのサーバの正当なユーザであることを証明しなければなりません。 自分が自分であることを証明するための仕組みを認証と呼びます。

最もありふれた認証方法は、パスワード認証です。 ユーザは事前にサーバに秘密のパスワードを保存しておき、ログイン時にも同じパスワードをサーバに対して送信することで認証を行うという、なんの変哲もない認証です。 シンプルで便利な方法なのですが、パスワード認証にはいくつか問題があります。

これらの問題は、パスワードではなく、鍵対を使って認証することで解決できます。 鍵対というのは、公開鍵と秘密鍵のペアで、…… と書こうと思っていたら既に possum さんが記事に書いてありました。 possum さんに記事では、通信の暗号化に公開鍵と秘密鍵を使うという話でしたが、認証にも鍵対を使うことができます。

これを、

というふうに使います。 これにより、前述したパスワード認証の問題が解決されています。

ということで、前置きが長くなりましたがこの公開鍵を保存しておくためのファイルが今回紹介する authorized_keys です。 また、単に公開鍵を保存しておくだけでなく、実行するコマンドを制限したり、環境変数を設定したりすることもできます。

authorized_keys の基本的な使い方

まずは、公開鍵と秘密鍵のペアを用意しないことには始まりません。 Linux であれば ssh-keygen -t rsa を実行すると $HOME/.ssh/id_rsa に秘密鍵が、$HOME/.ssh/id_rsa.pub に公開鍵が生成されます。 この際にパスフレーズの指定が求められるので適当にパスフレーズを設定しましょう。 Windows では、例えば PuTTYgen を使って生成します。 PuTTYgen の使い方は適当にググってください。 「Public key for passing into OpenSSH authorized_keys2 file」と書いてあるところが公開鍵です。

公開鍵は次のような文字列です。(見やすくするために改行を入れていますが、実際は一行です。)

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiOfpFMlcQuHHJR1SE1MOyrf2ifW5C8WgC7yvkNPQ
yeqjP5j5KSkNHm0mB4jieDLY8pV5Cu2pnUTwaN+nxMZragHgPTZMFO9ebk5BpM08or32bhp0+CpOGe8
Q9xt2lh8hrQr3cPgJojJ/w1TY5mo6RAiVHIw+tsqw2cRFxCgAOoV/Cpn0QtCpm7uusCvWxc3E3UzzEu
pnUoxSEqSg5ZHyEtJt/HfARt4aNozyLN3HHBJ9n5+BeIA6H36ZJBOf3lKtm7r2zO6TWT5W+xNoOPEZj
Cb4cpYMoR9/RY5kHt5ni3XgIk86DRPH0CiGQfJgBAoUel5bqj62MmpsMLKHRP8cz ubuntu@www-2

これを、何らかの手段でログインしたいサーバの $HOME/.ssh/authorized_keys に書けば、鍵認証の準備完了です。 (パスワード認証などでログインできる場合は ssh-copy-id を使うのが便利です。) 使いたい公開鍵が複数ある場合は、1行にひとつずつ公開鍵を書いていけばOKです。

ログインするときは、以下のように秘密鍵の場所を指定すると鍵認証でログインを試みてくれます。

$ ssh -i ~/.ssh/id_rsa example.com

実は ~/.ssh/id_rsa はデフォルトで見てくれるので、~/.ssh/id_rsa を使う場合に限っては -i ... を省略して以下のように書くこともできます。

$ ssh example.com

Windows だと PuTTY の設定画面でそれっぽく設定すると鍵認証でログインできます。

コマンドの制限

サーバAからサーバBに定期的にファイルをバックアップすることを考えます。 具体的には、cron で定期的に rsync します。 このとき問題になるのが認証です。

これは嫌なので、「サーバBにはログインできるが、バックアップ以外のことができない」ような仕組みが欲しくなります。 実は、authorized_keys を使えば、公開鍵ごとに実行できるコマンドを制限することができます。 (正確には、SSHクライアントから渡されたコマンドを無視して authorized_keys に書かれたコマンドが実行されるという動作になる)

サーバAでは以下のようなスクリプトを cron で実行しているとします。

#!/bin/sh

rsync \
    --archive \
    --compress \
    --delete \
    --exclude=".ssh/" \
    --exclude=".vim_backup/" \
    --exclude=".gem/" \
    --exclude=".rbenv/" \
    --rsh="ssh -i /home/nojima/.ssh/backup_rsa" \
    /home/nojima \
    example.com:/path/to/backup

rsync は SSH した先で転送元から送られてきたデータを受け取るためのプロセスを起動します。 上のスクリプトを実行した場合は rsync --server -logDtprze.iLsf --delete . /path/to/backup というコマンドを実行するので、authorized_keys を使って実行可能なコマンドをこのコマンドだけに制限すれば、秘密鍵が流出してもバックアップ以外の悪さはできなくなります。 (rsync が転送先でどんなコマンドを実行しているのかは rsync に -vvv オプションをつければ知ることができます。)

コマンドを制限するには、以下のように、公開鍵(ssh-rsa AAAAB... の部分)の前に command="hogehoge" という形でコマンドを書けばよいです。

command="rsync --server -logDtprze.iLsf --delete . /path/to/backup" ssh-rsa AAAAB...

公開鍵ごとに command が指定できるという機能は、他にも応用ができます。 例えば、Git レポジトリ管理ツールである Gitolite では公開鍵とユーザを結びつけるために authorized_keys の command を利用しています。

Gitolite に公開鍵を登録すると、git ユーザの authorized_keys に以下のようなエントリが追加されます。

command="[path]/gl-auth-command tanaka",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA18S2t...
command="[path]/gl-auth-command suzuki",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXtCT...

このようにコマンドの中にユーザを表す引数が含まれているため、git ユーザとしてアクセスされても本当は誰がアクセスしてきたのか知ることができます。

おわりに

他にも authorized_keys を使えばいろいろできますが、眠たくなってきたので(現在1時15分)これで今回の僕の話はおしまいです。 より詳しいことは man sshd を参照ください。

明日は wacky さんが -D オプションと tsocks について書いてくれます。 お楽しみに。

参考