SSH CA認証 (ホスト認証編)

公開日: : 最終更新日:2020/04/07 SECURITY, SSH ,

ホスト認証

以前の投稿でSSH CA認証まとめとしてSSH CA認証のユーザ認証についてみていきましたが、ここではホスト側の認証についてみていきます。

概要

SSHでの認証では、接続先が接続元を検証するユーザ認証の他、接続元が接続先を検証するホスト認証があります。
ホスト認証はユーザ認証と比較して蔑ろにされがちですが、ユーザ側とサーバ側双方の信頼が確立されて初めて接続が安心できます。

CA認証については以前ユーザ側を扱いましたが、ホスト側についてもCA認証の方式を採用することで旨みがあります。

ということで、ここではホスト側でのCA認証についてみていきます。

公開鍵認証方式でのホスト認証

ここではあまり詳細は書きませんが、ユーザがあるホストにSSHした際、公開鍵認証方式でのホスト認証では以下のようなことが行われます。

  1. ホスト側ではホスト認証用のキーペア(秘密鍵+公開鍵)を持っており、公開鍵をユーザに送る
  2. ユーザは「~/.ssh/known_hosts」を参照し、接続しようとしているホスト名と公開鍵が登録済みか確認する
    • ホストがすでに登録済みであり、それに対応する公開鍵とホストから送られた公開鍵を照合
      • 同一である場合OK
      • 異なる場合NG
    • ホストが未登録の場合、送られたホスト公開鍵のFingerPringが表示され、新たにknown_hostsに登録して受け入れるかどうか確認される
      • 受け入れる場合known_hostsに新たに登録してOK
      • 受け入れない場合そのままNG
  3. 最後にホストは秘密鍵を、ユーザはホストから受け取った公開鍵をそれぞれ用いて署名検証(チャレンジレスポンス検証)

2. でのホスト公開鍵の検証のところがキモになるわけですが、この検証に用いられるユーザ側のknown_hostsの管理はかなりしんどいものとなります。
ましてやクラウド環境とかだと同一ホスト名でインスタンスを作り直すことなんかしょっちゅうでその都度各ユーザのknown_hostsの更新が必要となります。(サーバのキーペアが常に一意なら普遍ですが、それはそれでサーバ鍵の管理の必要が新たに出てきますし、普通都度サーバキーペアは再生成するものです)

公開鍵認証あるあるパターン

ということで上記に挙げたように、known_hostsのメンテのエグさから、大抵以下のパターンに落ち着くでしょう。

とりあえず受け入れちゃえ

ホスト未登録の場合

$ ssh -A <接続先ホスト>
The authenticity of host '<接続先ホスト> (<no hostip for proxy command>)' can't be established.
RSA key fingerprint is SHA256:3bf8MTEIsyc...
Are you sure you want to continue connecting (yes/no)? 

# とりあえずYES
yes

ホストの鍵が変わった場合

$ ssh -A <接続先ホスト>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!  @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
...
Offending ECDSA key in ~/.ssh/known_hosts:18
...

# known_hostsから消してからもう一回っと
$ ssh-keygen -R <接続先ホスト>

無視しちゃえ

# 無視オプションで接続
$ ssh -o 'StrictHostKeyChecking no' <接続先ホスト>

… と、もはや邪魔にしかなってない??みたいな。。結局しょっちゅう警告に遭遇するのでオオカミ少年状態な。。。


CA認証方式でのホスト認証

次に本題の、CA認証の処理フローを見てみます。流れは以下の図のようになります。

HostはOSインストール時に何らかの初期スクリプトなどで認証用キーペアが設置されるものとして、ここではScriptsToolとしておいておきます。

SSH CAホスト認証 概観

それでは順に見ていきます。
まず事前準備として認証局(CA)では署名用キーペアを生成しておきます。

  1. Host認証用キーペア(Host秘密鍵+Host公開鍵)を生成します。初期実行スクリプトなどでキーペアを生成し、そのうちのHost公開鍵をCA秘密鍵で署名し、Host証明書を発行します。
  2. Host秘密鍵とHost証明書をHostに設置します。(通常/etc/ssh/配下)
  3. CA公開鍵をユーザ側に登録します。(~/.ssh/known_hosts)
  4. 3までで下準備は完了。ユーザは該当HostにSSHリクエストします。
  5. リクエストを受けたHostは、Host証明書をユーザに渡し、ユーザはCA公開鍵を用いて検証します。
  6. 最後は公開鍵認証と同様、Host側はHost秘密鍵を、ユーザ側はHost証明書(Host公開鍵)で署名検証処理を行います。

と処理は以上になります。以前ユーザ認証を扱いましたが、ほぼユーザとHostの立場が逆になっただけですね。

SSH CA ユーザ認証

CA認証の詳細

Host側での設定

CAでのHost証明書発行時の詳細についてみていきます。Host証明書は各種言語のSSH系ライブラリ等でも発行可能ですが、ここではCLIでのssh-keygenコマンドについて扱います。署名は下記コマンドで行います。

$ ssh-keygen -s <CA秘密鍵> -I <キーID> -z <シリアル> -h -n <プリンシパル> -V <有効期限> <署名対象のHost公開鍵>

基本的にはユーザ認証の場合とほぼ同じですが、若干異なります。

hHost証明書用オプション。Host認証の場合は必須です。
nプリンシパル指定オプション。ユーザ認証の場合はユーザ名や任意の文字列を指定しましたが、Host認証ではこのプリシパルにホスト名を指定することで、その指定したホストのみで有効な証明書とすることができます。
指定なしの場合は任意のホストで有効となります。
もちろんワイルドカード指定も可能。

上記で発行された証明書、ならびにHost秘密鍵を/etc/ssh/sshd_configに指定します。

HostKey <Host秘密鍵のパス>
HostCertificate <証明書のパス>

以上で完了!

ユーザ側での設定

ユーザ側では、.ssh/known_hostsの設定が必要となります。
公開鍵認証の時のようにサーバ公開鍵を連ねていくのとは違い、基本的にCA公開鍵を指定するだけのStaticなものになり、管理が容易となります。

また、基本的にSSHリクエスト時に警告が出ないのが当たり前になるので、警告が出た時は何かおかしなことが起きてる?と警戒することができるんですね。

@cert-authority <principal(許可するホスト一覧)> <CA公開鍵>

これだけ。

@cert-authorityをプレフィックスにつけることで、この行はCA認証という意味づけがなされます。

もちろん複数行にわたって複数のCA公開鍵を指定することや、@cert-authorityプレフィックスなしの公開鍵認証時の「<hostname> <Host秘密鍵>」とのハイブリッドも可能です。

CAホスト認証を試してみる

以上を踏まえて、実際に試してみます。インスタンスを複数用意するのも面倒なので、1インスタンス(dev01.kontany.net)でCA, client, host全てまかないます。

ということでややこしくなるので一旦各役割ごとにディレクトリをきります。

事前準備

# ワークスペース作成
$ mkdir -p {ca,host}
 
# host用のキーペア作成
$ ssh-kaygen -f host/hostkey
 
# CA用のキーペア作成
$ ssh-kaygen -f ca/cakey

Host側設定

Host(ログイン先)では、CAによってHost公開鍵を署名してもらいます。

# 今回localhostからlocalhostへの接続のため、principalにはlocalhostと自身のホスト名を指定しておきます。
ssh-keygen -s ca/cakey -I test-hostcert -z 1 -h -n localhost,dev01.kontany.net -V +365d host/hostkey.pub

Signed host key host/hostkey.pub: id "test-hostcert" serial 1 for localhost,dev01.kontany.net valid from 2016-03-03T03:31:00 to 2017-03-02T03:32:45


# 生成された証明書の中身を確認。localhost,dev01.kontany.netで有効なサーバ証明書が生成されているのがわかる
$ ssh-keygen -L -f host/hostkey-cert.pub
host/hostkey-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com host certificate
        Public key: RSA-CERT 6d:bc:2c:75:9d:0d:9c:cc:60:f4:c8:b5:ad:05:4c:78
        Signing CA: RSA 53:58:74:1b:98:7d:96:42:b0:eb:65:33:d7:02:bd:06
        Key ID: "test-hostcert"
        Serial: 1
        Valid: from 2016-03-03T03:31:00 to 2017-03-02T03:32:45
        Principals:
                localhost
                dev01.kontany.net
        Critical Options: (none)
        Extensions: (none)

上記で生成したHost証明書、およびHost秘密鍵を適当な所に設置し、sshd_configに指定します。

$ sudo cp host/{hostkey,hostkey-cert.pub} /etc/ssh/


# sshd_configに2行を追記
$ sudo sh -c 'echo "HostKey /etc/ssh/hostkey" >> /etc/ssh/sshd_config'
$ sudo sh -c 'echo "HostCertificate /etc/ssh/hostkey-cert.pub" >> /etc/ssh/sshd_config'

んで最後に反映でサーバ側は設定完了!

# シンタックスチェック(ミスって反映すると追い出されるので注意)
sudo sshd -t

# 反映
$ sudo service sshd restart
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

クライアント側設定

クライアント側はknown_hostsを設置するだけ

# 確認のため、既存のknown_hostsをリネームしておく
mv ~/.ssh/known_hosts ~/.ssh/known_hosts.bak

# 新たにCA公開鍵が指定されたものを設置.許可するprincipalにはlocalhostとワイルドカードを利用しkontany.netサブドメインを指定してみる
echo "@cert-authority localhost,*.kontany.net $(cat ca/cakey.pub)" > ~/.ssh/known_hosts

以上でもろもろ設定完了。それでは実際にSSHしてみてWorningなど出ないか確認してみます。

# debugオプションをつけて確認
ssh dev01.kontany.net -vvv
...
debug1: Server host key: RSA-CERT 6d:bc:2c:75:9d:0d:9c:cc:60:f4:c8:b5:ad:05:4c:78
debug3: load_hostkeys: loading entries for host "dev01.kontany.net" from file "/home/testuser/.ssh/known_hosts"
debug3: load_hostkeys: found ca key type RSA in file /home/testuser/.ssh/known_hosts:1
debug3: load_hostkeys: loaded 1 keys
debug1: Host 'dev01.kontany.net' is known and matches the RSA-CERT host certificate.
debug1: Found CA key in /home/testuser/.ssh/known_hosts:1
...

特にWorning等なくログイン完了. localhost指定に関しても同様
$ ssh localhost -vvv


debugログからも正常に検証が行われているのがわかります。


まとめ

SSH CA認証でのホスト検証についてみていきました。

このところVMやコンテナ化などでホストをガンガン焼き直すのは茶飯事でその都度known_hostsを更新して意味のある運用を行うのは無理があります。

CA認証を使うことでknown_hostsがstaticに管理できて現実的な運用ができるのはよさそうですね。

CA認証でのユーザ検証の時と同様にCAの管理が要求されるので個人利用レベルだとコストに見合うものが得られるか微妙ですが重要なシステムを持ってる組織とかだとこれくらいは頑張ってもいいんじゃないの、という感じです。(公開鍵認証でのホスト検証はあってないようなもんな気がしてます。)

数年間塩漬けになってた記事のひとつ書き上げ完了なり。
(disられまくってるWordPressのGutenbergを試してみたかったのもあるがめっちゃ使いやすいじゃん、、と思ったらやっぱりいろいろ粗が。。。納得しますた)

参考

GoogleAdsense

関連記事

openssh

SSH CA認証まとめ

SSHでの接続を、CA認証でやってみる。 備忘録として残しておくの。。。 概要 Open-SSH

記事を読む

hydra

クラックツールHydraでベーシック認証を突破してみる

kali linuxにデフォルトでインストールされているツール「Hydra」を利用して、ベーシック認

記事を読む

android_secure

【Android】代表的な脆弱性まとめ ~ファイルアクセス権について~

近年、スマートフォンの普及に伴い、Android, iPhone, WindowsPhone? ユー

記事を読む

john the ripper

パスワードクラックツール JOHN THE RIPPER 使い方まとめ

パスワードクラッキングツールである「JOHN THE RIPPER」の使い方を備忘録としてまとめてお

記事を読む

GoogleAdsense

Message

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

GoogleAdsense

SSH CA HOST CERT IMG
SSH CA認証 (ホスト認証編)

ホスト認証 以前の投稿でSSH CA認証まとめとしてSSH C

openssh
SSH CA認証まとめ

SSHでの接続を、CA認証でやってみる。 備忘録として残しておくの。

node_cookie
【Node.js】 Cookieの取り扱いまとめ

最近流行りのNode.jsですが、Cookieに関して、いくつ

hydra
クラックツールHydraでベーシック認証を突破してみる

kali linuxにデフォルトでインストールされているツール「Hyd

john the ripper
パスワードクラックツール JOHN THE RIPPER 使い方まとめ

パスワードクラッキングツールである「JOHN THE RIPPER」の

→もっと見る

PAGE TOP ↑