Mono Works

チラシのすきま

パスフレーズ未設定と引き換えに制約付けて、ご安全にSSH

前回は、パスフレーズを設定したSSH接続を rsyncと組み合わせてセキュアな同期を実現しました。これに対して、今回は、あえてパスフレーズを設定しないけど、安全性を高める方法をご紹介します。

2018-08-01-constrained-ssh01

実行コマンドの制約

実行コマンドの制約とは、パスフレーズを設定していないペア鍵に対して、特定のコマンドだけを実行するよう制約を設けることで、万が一鍵が盗まれたとしても、特定のコマンド以外は受け付けないようにするものです。

具体的には、rsyncコマンドをSSH接続で実行する場合、ローカル側でrsyncを実行すると、リモート側でもrsyncが実行され、2つのrsyncコマンドが通信することで同期がおこなわれます。この機能を利用して、特定のコマンドのみを実行するよう、公開鍵(authorized_keys)に制約を設定して、安全性を高めます。

ここから先は、具体的な手順を紹介していきますが、今回の作業は、前回の記事にしたがって、既にパスフレーズを設定したSSH鍵を導入している前提で記事を書いているので、あしからず。また、環境変数の例も前回と同じです。

パスフレーズなしの公開鍵と秘密鍵をローカルに生成

前回生成したパスフレーズ付きの鍵とは別に、rsync自動実行用にパスフレーズをしていない鍵ペアを作成します。デフォルトのファイル名ではなく、その利用用途が分かるようなファイル名にします。なお、ファイル名の指定には、-fオプションを使います。

cd ~/.ssh
# -fオプションの後ろにファイル名を指定して鍵を生成
ssh-keygen -t ecdsa -b 384 -C "rsyncHomePC" -f id_ecdsa_for_rsync
# パスフレーズを空のまま鍵を作成

# 秘密鍵(id_ecdsa_for_rsync)と公開鍵(id_ecdsa_for_rsync.pub)の生成を確認
ls -l
-rw------- 1 yourId yourId 288 Jul 30 23:23 id_ecdsa_for_rsync
-rw-r--r-- 1 yourId yourId 216 Jul 30 23:23 id_ecdsa_for_rsync.pub

ちなみに、同じフォルダ内のknown_hostsは、接続したことのあるサーバのSSHサーバ証明書が格納されているファイルです。

パスフレーズなしの公開鍵をサーバにアップロード

生成したパスフレーズなしの公開鍵(id_ecdsa_for_rsync.pub)をscpコマンドでアップロード。ここでは、authorized_keysを上書きしないように、ファイル名は変更せずにアップロードします。

scp /home/yourId/.ssh/id_ecdsa_for_rsync.pub hogeId@hogehoge.sakura.ne.jp:/home/hogehoge/.ssh
# パスフレーズを入力してEnter
id_ecdsa_for_rsync.pub                                    100%  222     0.2KB/s   00:00

既存の公開鍵にパスフレーズなしの公開鍵を追加

既に設置している公開鍵(authorized_keys)にパスフレーズなしの公開鍵(id_ecdsa_for_rsync.pub)の内容を追加します。

# SSHでログイン
$ ssh hogeId@hogehoge.sakura.ne.jp
# パスフレーズを入力してEnter
Welcome to FreeBSD!

% # ログイン成功

# 公開鍵(authorized_keys)にパスフレーズなしの公開鍵(id_ecdsa_for_rsync.pub)の内容を追加
% cat ~/.ssh/id_ecdsa_for_rsync.pub >> ~/.ssh/authorized_keys

# ちゃんと追加されたか確認
% cat ~/.ssh/authorized_keys

ecdsa-sha2-nistp384 《省略》 HomePC
ecdsa-sha2-nistp384 《省略》 rsyncHomePC # <-- 追加されている

# id_ecdsa_for_rsync.pubを削除
% rm -f ~/.ssh/id_ecdsa_for_rsync.pub

# このまま次の作業へ
%

指定したコマンドが実行されるか確認

テスト用に ls コマンドを記述

指定したコマンドがちゃんと実行されるか確認するため、authorized_keys に追加した鍵の前に command="ls"を追記します。ここではリモートで書き換えてますが、ローカルで書き換えたものをアップロードしても大丈夫です。

# 前の作業の続き
# authorized_keysにテストコマンドを設定
% vi ~/.ssh/authorized_keys

# viで追加した鍵の手前にcommand="ls" を挿入して保存
ecdsa-sha2-nistp384 《省略》 HomePC
command="ls" ecdsa-sha2-nistp384 《省略》 rsyncHomePC # <-- 追加した行の先頭にcommandを挿入
~
~
~

# ログアウト
% exit

テストします

パスフレーズなしの秘密鍵(id_ecdsa_for_rsync)を使って SSH接続して、lsが実行されて、コネクションが切断されたら成功です。

ssh -i ~/.ssh/id_ecdsa_for_rsync hogeId@hogehoge.sakura.ne.jp
# lsが実行され、コネクションが切断されたら成功
Connection to hogehoge.sakura.ne.jp closed.

実際に使用する rysncコマンドを確認

リモート先で実行されるrysncのコマンドを確認するには、実行したいコマンドに -vv オプションを追加したものを実行します。あと、パスフレーズなしの秘密鍵を使ってSSH接続するためのオプション(-e "ssh -i /home/yourId/.ssh/id_ecdsa_for_rsync")を付けるのも忘れずに。

# 通常のrsyncコマンドに -vv コマンドを追加して実行
$ rsync -vv -avz --update --delete --exclude='.htaccess' --chmod=D0755,F0644 -e "ssh -i /home/yourId/.ssh/id_ecdsa_for_rsync" /mnt/《自分なりのPath》/public/ hogeId@hogehoge.sakura.ne.jp:/home/hogeId/www/

# すると、このようにリモート先で実行されるコマンドが確認できます
opening connection using: ssh -i /home/yourId/.ssh/id_ecdsa_for_rsync -l hogeId hogehoge.sakura.ne.jp rsync --server -vvvulogDtprze.iLsfx --delete . /home/hogeId/www/  (12 args)protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(176) [sender=3.1.1]
[sender] _exit_cleanup(code=2, file=compat.c, line=176): about to call exit(2)

rsync --server から /home/hogeId/www/までの -vv オプションを除いた部分がリモート先で実行されるコマンドになります。この部分をcommand=""制約に入れることになります。(当然、本番のコマンドも -vv オプションを外したものを実行します)

command="rsync --server -vulogDtprze.iLsfx --delete . /home/hogeId/www/"

実行コマンドの制約を記載

テストでcommand="ls"と記述していた部分を先ほどのコマンド制約に書き換えて、設定したrsyncコマンドを実行します。問題なければ、パスフレーズなしで同期が完了するはずです。

これで、設定したrsyncコマンドで実行した場合はパスフレーズなしで同期がおこなわれ、その他のSSH接続時にはパスフレーズを入力してログインできるようになります。

その他の制約を追加

先の 実行コマンドの制約を含め、公開鍵(authorized_keys)に対して使用できるオプションが man sshdAUTHORIZED_KEYS FILE FORMATに書かれています。その中から、今回は、下記のオプションを付けて、もう少し安全性を高めることにしました。

  • 接続元ホストの指定(from="《接続元アドレス》")
  • ポートフォワーディング禁止(no-port-forwarding)
  • X11(画面)転送の禁止(no-X11-forwarding)
  • 仮想端末の割り当てを禁止(no-pty)
  • 認証エージェントの転送禁止(no-agent-forwarding)

先ほど追加したコマンド制約の前(後ろでも可)に追加のオプションを記述します。オプションが複数ある場合はカンマで区切り、各オプションの間には、二重引用符で囲まれた部分を除き、スペースを入れないようにします。

最終的な公開鍵(authorized_keys)の内容がこちら。

ecdsa-sha2-nistp384 《省略》 HomePC # パスフレーズありの鍵
from="《接続元アドレス》",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,command="rsync --server -vulogDtprze.iLsfx --delete . /home/hogeId/www/" ecdsa-sha2-nistp384 《省略》 rsyncHomePC # パスフレーズなしの鍵

rsyncの実行

そして、最終的なrsyncコマンドの内容がこちら。

    rsync -avz --update --delete --exclude='.htaccess' --chmod=D0755,F0644 -e "ssh -i /home/yourId/.ssh/id_ecdsa_for_rsync" ${HUGO_DIR}/public/ hogeId@hogehoge.sakura.ne.jp:/home/hogeId/www/

おしまい

コメント

コメントなどありましたら、GitHubのディスカッションへお願いします。(書き込みには、GitHubのアカウントが必要です)
執筆者
"ぽぽろんち" @pporoch
pporoch120
Mono Worksの中の人。好きなことをつらつらと書き留めてます。
ギターを始めてから 練習動画をYouTubeにアップしてます。ご笑納ください。
"DQX@ぬここ(UD487-754)、コツメ(NO078-818)"
採用案内