ssh の HashKnownHosts に追加する方法
HashKnownHosts を有効にしていると、 .ssh/known_hotss がハッシュ化される。
これにより、どのサーバーと通信していたか、関係性の秘匿が可能になる。
hash を使う known hosts のために嫌がらせなんじゃないかと最初は思うかもしれませんが、とても大事な機能です。
サーバーのホスト鍵の確認
takuya@:logs$ ssh-keygen -H -F github.com # Host github.com found: line 15 |1|Xs0rgP4k....=|0a/5z/h...DE= ecdsa-sha2-nistp256 AAAAE2....U2w0WZ2YB/++Tpockg=
HashKnownHostsとはなにか。
いままでのknown_hosts は、ホスト名|鍵
が確認されていた。しかし、これには接続履歴を見られるリスクが存在するので、HashKnownHosts
を用いて、接続済みホスト名をハッシュ化し秘匿するようになった。
一部では嫌われるが、すでにデフォルトで有効になっている。付き合うしか無い。
なぜHashKnownHostsを使うのか
ディスクを盗難された場合を考えましょう。ディスク盗難により、ssh秘密鍵が危殆化します。known_hostsも漏洩します。するとどうでしょう、known_hostsが今すぐ使えるサーバーのリストに早変わりです。漏洩した秘密鍵をがknown_hostsに掲載されているので簡単に接続できてしまいますね。.bash_historyを探さなくても接続可能なサーバの一覧が入手できます。
known_hostsや.bash_historyからプライバシー情報がダダ漏れです。この対策のためにHashKnownHostsを使ってファイルから情報漏洩を予防するんだと思います。
HashKnownHostsはこのために、ホスト名・IP・ポートをハッシュ化してknown_hostsに書き込んで使います。
HashKnownHostsへのホスト鍵の追加
HashKnownHostsなので、指定のハッシュ化を通さないとknown_hostsを追加できません。それは次の方法で行います。
HashKnownHostsを追加する方法
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
もしrsa 鍵だけでいいのなら
ssh-keyscan -H -t rsa github.com
HashKnownHostsに存在を調べる。
known_hosts に存在するかかどうかを確認する。一致するホスト名があるかどうかハッシュ値を調べる。
ssh-keygen
を使う。 ここまでで紹介した。ssh-keyscan
とにているので間違わないように注意する。
ssh-keygen -H -F github.com
HashKnownHostsから削除する
HashKnownHostsにすると~/.ssh/known_hostsを開いて手作業で編集ができない。そのため専用コマンドを使う。
ssh-keygen -R github.com
ファイルを分割しているときは
ssh-keygen -R github.com -f /path/to/known_hosts
重複を防いだ登録
ホスト公開鍵を新規で登録して重複を防ぐ。
if ! ssh-keygen -H -F github.com > /dev/null ; then ssh-keyscan -H -t rsa github.com >> ~/.ssh/known_hosts fi
もっと単純に
! ssh-keygen -H -F github.com > /dev/null || ssh-keyscan -H -t rsa github.com >> ~/.ssh/known_hosts
さらに関数に
function known_hosts_add(){ ! ssh-keygen -H -F $1 > /dev/null || ssh-keyscan -H -t rsa $1 >> ~/.ssh/known_hosts }
というわけで、known_hosts を管理する必要があります。
UserKnownHostsFile で、ホスト鍵ファイルを指定
known_hostsに書きすぎると自動化で困ります。そこでUserKnownHostsFileを使います。
冒頭に紹介した scan を使ってファイルを生成し、UserKnownHostsFileを使って接続します。
例えば次のようにします。
$ ssh-keyscan -H github.com >> ~/known_hosts.github $ ssh -o UserKnownHostsFile=~/known_hosts.github github.com
これは、.ssh/configに記載することもできます。
.ssh/config 例
Host github hostaname github.com UserKnownHostsFile ~/known_hosts.github, ~/.ssh/known_hosts
上記のようにknown_hostsを複数に分けてconfigに書いておくこともできます。
CI/CDなど自動化時にknown_hostsで困らないように
ssh接続で外部サーバーに操作するスクリプトを使って自動的デプロイ、cpuなどの稼働状況取得、CI/CDで自動化しているなどで困ります。ssh接続でKnownHostsに困らされると思います。ネットでみると StrictHostCheck をオフにしている人たちがかなりいます。
ちゃんと「鍵」を管理したほうが良いです。鍵は、セキュリティの基本なのです。もしssh -o StrictHostKeyChecking=no
で済ませていると書いてあれば、その持ち主はMITMを許してくれる優しいエンジニアだと思います。意識高い系のQiitaの凄優しいエンジニア君たちです
もし、CI/CD でデプロイをするのなら、-o UserKnownHostsFile=/path/to/file
でちゃんとホスト公開鍵の鍵束を信頼できる一覧としてプロジェクトに含めるべきだと思います。
たとえば、trabvis-ci では、信頼できるホスト名をci.yamlに掲載する方法が紹介されています。gitlab-ci では SSH_KNOWN_HOSTS 変数を使って登録する方法が紹介されています。
known_hostsをちゃんと管理しないとだめですね
known_hostsを甘く見ちゃいけません。平文秘密鍵ファイルと一緒に配置したらあきまへん。平文鍵ファイルを使うならHashKnownHostsをオフにするのは危険です。StrictHostKeyCheckingをオフにするのはMITMを許すので盗聴にたいしてあまりに危険です。
CheckHostIP をつけると便利
DNSでラウンドロビンをしてるとき、CheckHostIP=noをしておくと便利
~/.ssh/config
CheckHostIP=no
通常のknown_hostsの登録
ssh github.com
これだと、github.comのIPが変わったときに再登録が必要になる。
なぜなら、ホスト名+IPアドレス+ポート
をハッシュ化するからである。
このようなことが起きないように、CheckHostIP=noにするか手作業でknown_hostsを作るのがいいと思う。
UpdateHostKeys
ホスト鍵が変わったときにyes/noで自動でYESを答える機能。ホスト鍵が変わる=MITMとも言えるので、この設定は控えたほうがいいかもしれない。
ただし、自分の管理化でローカルサーバーとかならいいかもしれない。つまり、ホスト毎の設定であれば書いて構わないだろうが、グルーバルには書くなってことです。
参考資料
2022-02-18 追記
UpdateHostKeys/CheckHostIPについて追記。
# 2022/03/17
追記