cronやプログラムでssh越しrsyncを利用するときにカナリ便利なオプション

1. 始めに

同期が必要な場面って結構ある。ローカルのディレクトリ間の同期はもちろん、特にインターネット越しの同期が必要になることって結構ある。

そんなときには決まってrsyncの出番だ。ファイルの変更を検知し、よしなに同期してくれる。そんな頼もしいrsync。枯れたソフトウェアなのでホスティングを借りたときにftpだけじゃなくてsshとrsyncが付いてきたりもする。すでに広まっているからすごく便利。

で、さて、そんな便利なrsyncなんだけれどcronなどで定期的、自動的にrsyncを実行するときにはチョットした問題があったりする。

その問題とは二点。一つはパスワード無しで認証を通す必要があること。もう一つはフィンガープリントと呼ばれるsshのホストの正当性を確かめる確認が出ること、だ。

この問題はどちらも、プログラムやcronなどプロンプト(よろしいですか?[y/n]的なアレ)を処理できない端末でrsyncを利用する際に解決しなければいけない問題。

前者のパスワード無しで認証を通すためにはsshの公開鍵認証を利用する。コレに関しては文献がいろいろとあるので参照されたし。

rsyncとsshで別のマシンにバックアップ

rsync over ssh を使ってバックアップ

さて、今回は二つ目の問題点、フィンガープリントのプロンプトを越えるためのオプションについて考える。環境としてsshクライアントとしてOpenSSHを想定している。他だとうごかないかも。

2. sshのfingerprint

sshにはfingerprintと呼ばれるホストの正当性を確認する仕組みがある。fingerprint(フィンガープリント)というのは指紋。sshを提供しているホストはすべて一意(という前提)のfingerprintハッシュがある。これはsshを提供するサーバでsshd(sshサーバ)を初回起動した際に自動的にランダムに生成される。生成はRSAとかの公開鍵暗号で用いられる方法で作成される。秘密鍵はサーバに一般には読み取り不可で保存されてる。

サーバごとに異なったfingerprintハッシュがあり、クライアントは初回接続時に接続しようとしているサーバのfingerprintを取得する。そして接続対象のホストがユーザの意図したホストかどうかを確認することができる。

これはハッキング防止のためにある措置。ハッキングとしてあり得る話としてはip(or mac)偽装で接続サーバになりすましsshで受付を開始し、パスフレーズを抜き出す、というところだろうか。近年のように平和ボケしちゃいそうな状況だとなかなかお目にかかれないけれども。

今まで接続したことの無いホストにsshで接続しようとするとfingerprintが表示され、本当に接続しますか?と聞かれる。

キャプチャ

内容が正しければyesと入力する。これでサーバのアドレスとfingerprintが手元に保存される。次回接続時からはこのような確認は出ず、手元にあるknown_hostsと呼ばれるfingerprintの一覧が入ったファイルからfingerprintが一致するか確認し、自動的に接続する。

またもし対象のサーバのfingerprintが違った場合、接続できない。先のように成りすまされる、というケースは少ないだろうが、対象ホストのOSを入れ直したときなんかは一度手元のfingerprintを消して再度つなぎに行く必要がある。

さて、この「初回起動時にfingerprintの正当性について聞かれる」プロンプトがrsyncでは問題になる。

3. プロンプトに応答できないrsync

sshの接続では初回接続時にfingerprintの確認が行われる。手動でsshを接続するのであればyesと入力するだけで手元のknown_hostsにfinger printが追加され、次回からはプロンプトなしに接続することができた。

でもrsyncでのssh接続だとこういったプロンプトに応答することができない。

良くある解決方法としては、rsyncを実行したいユーザで手動にてssh接続を行っておく、という方法だ。こうしておけば該当ユーザのknown_hostsにサーバのfingerprintが保存され二度と聞かれる事はない。

でもこの解決方法が使えない場合がある。それはrsyncを一般ユーザではなく専用の特殊なユーザで行う場合だ。例えばnobodyであるとか、httpd、www-dataといったwebからの動作でうごかしたりする場合などは一般ユーザ権限ではrsyncを動かすことができない。

こういったユーザであったとしても一定の条件下であれば問題は無い。条件というのは、「該当ユーザでログインできること」、「該当ユーザのホームディレクトリが存在すること」である。

レンタルサーバなどであるとhttpdなどをうごかしているユーザでログインすることは難しいだろう。またFreeBSDなんかだとapacheユーザのホームディレクトリは/nonexistent/という値だったりして困る。ホームディレクトリを作ってしまうという無理矢理な解決方法もあるけれどあまり気持ちの良い物では無い。

ということで、このfingerprintの確認を行わないようにできないか、と思って調べてみた。

4. 意外と情報の少ないsshのfingerprintを確認しないオプション

で、早速fingerprintを確認しないようにググってみたんだけれどコレがまた情報が少ない。以前どこかで質問したこともあるけれど答えを得られなかったり。

Linux Commando: How to disable SSH host key checking

というわけで、fingerprintを確認しないようにするオプションはsshで二つ。

<br /><br />StrictHostKeyChecking=no<br />UserKnownHostsFile=/dev/null<br /><br />

この二つを-oで渡せば良い。それぞれのオプションは、fingerprintの正当性を確認しない、対象ホストのfingerprint保存先を/dev/null(破棄)する、というオプションだ。これでrsyncでfingerprint認証を通す準備ができた。

sshだけだと下記のようになる。

<br /><br />ssh -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no sshhost.example.com<br /><br />

以上でfingerprintに対する準備はおしまい。

注意としてfingerpintによる認証を通さないのでセキュリティリスクを負うことになってしまう。今回は/dev/nullにしたけれど、該当ユーザから読み出せる位置にknown_hostsのファイルを置いてやってそれをUserKnownHostsFileとして渡してやる方が無難な気もする。

ついで公開鍵認証についてのオプションも与えてやる。sshではパスフレーズ無しで認証を掛けることができるようなる。この時の秘密鍵について、オプションを与えて指定することでホームディレクトリが無いユーザでも公開鍵認証を通るようにしてやる。

公開鍵を指定するオプションは-i。下記のようになる。

<br /><br />ssh -i /usr/local/etc/ssh/key.rsa<br /><br />

秘密鍵のパーミッション、所有者については厳重に取り扱うように。

5. 終わりに

以上をまとめると、sshを使ったrsyncをプロンプト無しで運用するには以下のような感じでいける。

<br /><br />shell&gt; rsync -e "ssh -o 'UserKnownHostsFile=/dev/null'<br /><br />-o 'StrictHostKeyChecking=no' -i /usr/local/etc/ssh/key.rsa"<br /><br />/path/to/local example.com:/path/to/remote<br /><br />

こんな感じで書いておけばcronのユーザをnobodyとかにしてもおk。phpの中で走らせるのもいける。

最後に、以上の方法だとセキュリティを下げることになるので運用には細心の注意を払われたし。

「cronやプログラムでssh越しrsyncを利用するときにカナリ便利なオプション」への2件のフィードバック

  1. 参考にさせて頂きました。ありがとうございます。

    1点だけ指摘があります。
    「–i」 の 「–」がハイフンではないような…

  2. takeさんこんにちは!
    ホントですね!コピペしたら2バイト文字になってしまってますね〜。見た目だと分からないのですが半角カナのハイフンを入れてしまってましたね!

    ご指摘ありがとうございますー!

コメントを残す