QA@IT

rsync によるバックアップを cron で回したい、しかしシェルへのアクセスは拒否したい

9509 PV

定時遠隔バックアップを設計しています。DBなどは個別に対応して、その他の一般のファイルはrsynccronで実施すればいいかなと思っています。

ところでrsyncなのでSSH接続するかと思いますが(あるいはするべきかとおもいますが)、cronなのでパスワードを入力することができません。そこでパスフレーズなし公開鍵による認証をすればよいのは分かりましたが、この秘密鍵が流出してしまうと、いきなりログインして任意のプログラムが実行できてしまうので、セキュリティリスクの面で不安になっています。

バックアップですから、当然ファイルアクセス権限は必要なのは分かります。しかしプログラムを実行できてしまうのは怖いので、そこをなんとか回避できないものでしょうか? またこの他にセキュリティ面で気をつけるべきことがありますでしょうか。

  • rsync version 3.0.9 protocol version 30
  • OpenSSH_5.9p1 Debian-5ubuntu1, OpenSSL 1.0.1 14 Mar 2012

を使っています。バックアップ元、先ともにUbuntuです。

回答

パスフレーズなしの SSH 公開鍵を利用して、いわゆる「rsync デーモン over SSH」を構成すればいいです。ほかの回答にあるような「バックアップ先のrsyncを実行するコマンドを調べる」必要はありません。

また、authorized_keys を適切に設定すれば、ほかの回答にある「秘密鍵が流出してしまうと、いきなりログインして任意のプログラムが実行できてしまう」こともありません。

以下、バックアップ先のホストを backup-host、そのホスト上のバックアップ用ユーザーを backup-user とします。

まずはバックアップ元のホストでパスフレーズなしの SSH 鍵ペアを作成します。
ここでは鍵ペアを ~/etc/backup/id_rsa.rsync* に保存することとします。:

$ mkdir -p -m 0755 ~/etc/backup
$ ssh-keygen -t rsa -N '' -f ~/etc/backup/id_rsa.rsync
...

バックアップ先 (backup-host) の SSH の公開鍵認証ログインを許可するファイル ~backup-user/.ssh/authorized_keys の内容を次のように設定します。公開鍵データは先ほど作成した鍵ペアの ~/etc/backup/id_rsa.rsync.pub ファイルの内容です。以下の設定例は改行されて表示されるかもしれませんが、実際は一行で記述してください:

command="/usr/bin/rsync --server --daemon --config=$HOME/etc/rsyncd.conf .",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty 公開鍵データ コメント

バックアップ先 (backup-host) の backup-user の rsync デーモンの設定ファイル ~backup-user/etc/rsyncd.conf の内容は次の通り:

[global]
## root など chroot(2) を実行できる権限があるなら yes に設定
use chroot = no

[backup-dir]
## バックアップ先ディレクトリ
path = /srv/backup
## 書き込みを許可、読み出しを禁止
read only = no
write only = yes

以上で設定は完了です。

バックアップは、バックアップ元ホストのバックアップ実行ユーザーで次のようにして実行します。ポイントは --rsh /usr/bin/ssh ... を指定して SSH の利用を明示する点と、転送先を rsync デーモンに接続するときの形式 [ユーザー名@]ホスト名::モジュール名 とする点です:

$ rsync \
    --archive \
    --hard-links \
    --delete \
    --rsh '/usr/bin/ssh -i $HOME/etc/backup/id_rsa.rsync' \
    /path/to/src \
    backup-user@backup-host::backup-dir

ACL もバックアップ対象なら --acls オプションを、EA (拡張属性) も対象なら --xattrs オプションを追加してください。

以上の構成手順は rsync の付属マニュアルか何かに記載されていたような記憶があるのですが、今探してみたところ、見当りませんでした。オンラインマニュアル rsync(1) の「USING RSYNC-DAEMON FEATURES VIA A REMOTE-SHELL CONNECTION」に少し記述されています。

編集 履歴 (4)

色々な要件があるかと思うので、この方法が満たされるかどうかはわからないのですが
rsyncを実行するユーザを限定し、同時にアクセス元IPも制限する方法が良いかと思います。
実際の方法としては /etc/security/access.conf を利用する事で可能です。
ただこの方法は既存のユーザも上記ファイルで扱うことになりますので、そのあたりの調整は必要かもしれません。

同期先でfuseが扱えるようなら、セッション張りっぱなしにはなりますが sshfs を利用することもできますね。

13:43 追加で。
元々の要件のrsyncという話では無くなるのですがsftpで問題ないなら、sshの設定でChrootDirectory と ForceCommandのオプション付けておくことでも、お望みの要件は叶えられそうです。

編集 履歴 (1)
  • 既に答え出ていたので、別の回答としてと先頭に書くのを忘れていました... -
  • なるほど。sftpのことは考慮から漏れていましたが、これも選択肢としてよさそうです。 -

様々な方法があると思いますが、authorized_keys の設定にて実行できるコマンドと接続元を制限する場合、下記の方法でできると思います。

rootアカウント用のssh設定を行う(必要な場合のみ)

ログインすると強制的に特定のコマンドが実行される場合にのみ root のログインを許可するよう /etc/ssh/sshd_config に下記設定を行う

#PermitRootLogin no
PermitRootLogin forced-commands-only

rsync用の鍵を作成する

ssh-keygen -t dsa -N "" -f /path/to/.ssh/rsync

バックアップ先のrsyncを実行するコマンドを調べる

rsync-vv オプションをつけて実行し、実際にリモートサーバで実行されるコマンドを調べる。

rsync -vv -az -e "ssh -i /path/to/.ssh/rsync" /path/to/backup/ hoge@remote.example.com:/path/to/backup/
opening connection using: ssh -i /path/to/.ssh/rsync -l hoge remote.example.com rsync --server -vvlogDtprze.iLsf . /path/to/backup/
Permission denied (publickey).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(605) [sender=3.0.9]

上記のような結果の場合は rsync --server -vvlogDtprze.iLsf . /path/to/backup/ を使う

リモートサーバの authorized_keys に設定追加する

鍵の情報を設定するとともに、commandに -vv オプションで調べたものを -vv をはずして指定し、fromには接続元を記述して、指定したホストからのみ接続するように設定

command="rsync --server -logDtprze.iLsf . /path/to/backup/",from="local.example.com",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dss AAA...

cronに設定する

crontab -e
0 0 * * * rsync -az -e "ssh -i /path/to/.ssh/rsync" /path/to/backup/ hoge@remote.example.com:/path/to/backup/
編集 履歴 (0)

authorized_keys については既に話が出ているので他におすすめのアクセス制限としては、以下のような方法があります。

  • /etc/hosts.allow, /etc/hosts.deny で tcp wrapper の制限をする。
    • 変更したときに sshd の再起動が不要なので、制限の追加削除がしやすいです。
    • IPv6 アドレスは「sshd: 127.0.0.1 [::1]」のように [] でくくって指定する必要があります。
  • sshd_config の AllowUsers で接続元も制限する。
    • AllowUsers root@10.11.12.13 のようにユーザーと IP アドレスをセットで書いて制限出来るので、バックアップ先のサーバーからのみ root で入れるように制限出来ます。
  • sshd_config の PermitRootLogin は一番緩くしても without-password にして yes にはしない。
    • forced-commands-only の方が良いのですが、コマンドごとに鍵を用意するのが面倒なときには without-password にしてしまっています。
  • ufw limit 22/tcp のように ufw の limit で連続の接続を制限する。
    • 普通の問題ない接続に影響が出る可能性があるので、問題があれば allow に戻す必要があります。
編集 履歴 (0)

この秘密鍵が流出してしまうと、いきなりログインして任意のプログラムが実行できてしまうので、セキュリティリスクの面で不安になっています。

というご心配でしたので、sshログインを許可するアクセス元IPアドレスを制限すると、秘密鍵が漏洩した場合のリスクが低減できると思います。

王道は、torusさんが回答している通り、公開鍵と組み合わせてコマンド制限ができるので、それを利用するのがよいと思います。しかし、これは、コマンド1つに公開鍵1つを用意しなければいけないので、要件を満たすにはかなり手間がかかるかもしれません。

とりあえず、アクセス元を制限するというのは有効な手段だと思います。

RHEL6/CentOS6の場合で申し訳ありませんが、
以下、手順。

・/etc/pam.d/ssh
以下の箇所に追記する。
account required pam_nologin.so
account required pam_access.so <<<<<<追記
account include system-auth

・/etc/ssh/sshd_config
UsePAM yes

・/etc/security/access.conf
例)grgrjnjnユーザのログインを、10.9.40.1からのみ許可して、それ以外からのログインは拒否する設定。

  • : grgrjnjn : ALL EXCEPT 10.9.40.1

・設定の反映
$ sudo /sbin/service sshd reload

参考)
http://d.hatena.ne.jp/grgrjnjn/20120531/1338439309

編集 履歴 (1)

rsync 以外のコマンドをコピー元のマシンで実行したくないということでしょうか? だとしたら、ためしてないですが、~/.ssh/authorized_keys で特定のコマンドしか実行できないように設定することができるので、これが使えるかもしれません。

command="rsync ..." ssh-dss XXXXXXXXXXXXX(公開鍵)

のように設定します。詳しくは SSHD マニュアルの「AUTHORIZED_KEYS ファイルの形式」 に形式が載っています。

検索してみるとこのページに具体的な方法が書いてありました。→ using rsync with ssh keys via authorized_keys and command="rsync ..." | ramblings.narrabilis.com

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。