2007/03/05

NTP認証: ユニキャスト・公開鍵認証篇

NTP認証シリーズの第四回。今回は、ユニキャスト・公開鍵認証。

まずは、ドキュメントを読んでみる。FC5パッケージntpがインストールされていれば、/usr/share/doc/ntp-*にドキュメントが存在するので、それをfirefoxなりlynxなり好きなブラウザで。この中のkeygen.htmlに以下のような記述がある。
On each trusted host as root, change to the keys directory. To insure a fresh fileset, remove all ntpkey files. Then run ntp-keygen -T to generate keys and a trusted certificate.
つまりこうだ。信頼の基点(root)として信用されるホストにおいてはそれぞれ、次の三つを実行する。
  1. keysディレクトリに移動する。
  2. ファイル群を新しくするためにntpkeyファイルを削除する。
  3. 公開鍵・秘密鍵ペアと信頼された証明書を生成するため、ntp-keygen -Tコマンドを実行する
そうでないホストについては、どうだろう。
On all other hosts do the same, but leave off the -T flag to generate keys and nontrusted certificates.
つまり、それ以外のホストについては、-Tオプションをつけずに上の手順を実行せよ、ということだ。

ではやってみよう。これまで同様、認証を行わないユニキャストによる時刻同期ができている」ことを前提とする。

サーバ側
次のように実行する。
# cd /etc/ntp
# \rm ntpkey_*
# ntp-keygen -T
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 2 8       1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_ntpserver.localnet->ntpkey_RSAkey_ntpserver.localnet.3382096077
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
X509v3 Extended Key Usage: trustRoot
Generating new cert file and link
ntpkey_cert_ntpserver.localnet->ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
#
これで公開鍵・秘密鍵ペアと証明書ができているはずだ。
# ls -lF
total 16
-rw------- 1 root root 266 May 11  2006 keys.orig
lrwxrwxrwx 1 root root  48 Mar  6 00:07 ntpkey_cert_ntpserver.localnet -> ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
lrwxrwxrwx 1 root root  43 Mar  6 00:07 ntpkey_host_ntpserver.localnet -> ntpkey_RSAkey_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 629 Mar  6 00:07 ntpkey_RSAkey_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 620 Mar  6 00:07 ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 186 Oct 17 20:46 ntpservers
-rw-r--r-- 1 root root   0 May 11  2006 step-tickers
#

続いて、/etc/ntp.confに以下のような行を追加する。
crypto pw ntpserver.localnet randfile /etc/ntp/.rnd
ここで、pwに続くのは、かぎファイルのパスワードで、ntp-keygenコマンドに特別なオプションをつけなければ、gethostname()で得られるホスト名が使用される。これについては、第三回を参照のこと。次のrandfileに続くのは、ランダムシードファイルの場所。ランダムシードファイルの作成についても、前回を参照して欲しい。
最後に、ntpdを再起動する。
# service ntpd restart
Shutting down ntpd:                                        [  OK  ]
Starting ntpd:                                             [  OK  ]
#


クライアント側
まずは、サーバと同様、キーの作成を行う。ただし、-Tオプションを指定しない。
# cd /etc/ntp
# \rm ntpkey_*
# ntp-keygen
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 3 11      1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_ntpclient.localnet->ntpkey_RSAkey_ntpclient.localnet.3382098481
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
Generating new cert file and link
ntpkey_cert_ntpclient.localnet->ntpkey_RSA-MD5cert_ntpclient.localnet.3382098481
#

次に、/etc/ntp.confを次のように編集する。
server 192.168.55.133 autokey
crypto pw ntpclient.localnet randfile /etc/ntp/.rnd
ここで、192.168.55.133は、NTPサーバのアドレス。後はサーバと同じだ。
ここまでできたら、ntpdを再起動する。
# service ntpd restart
ntpd を停止中:                                             [  OK  ]
ntpd: 時間サーバと同期中:                                  [  OK  ]
ntpd を起動中:                                             [  OK  ]
#


確認
クライアントがサーバと同期したかどうかを確認する。当然、サーバがある時刻ソースに同期した後、さらにしばらくした後でないと確認できない。
# ntpq
ntpq> peers
remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntpserver.local 208.100.3.151    3 u   23   64  377    0.475  -250717  19.050
LOCAL(0)        LOCAL(0)        10 l   28   64  377    0.000    0.000   0.001
ntpq> associations

ind assID status  conf reach auth condition  last_event cnt
===========================================================
1 52124  f624   yes   yes   ok   sys.peer   reachable  2
2 52125  9024   yes   yes  none    reject   reachable  2
ntpq>


考察
さて、以上でサーバ=クライアント間の時刻同期は成った。だが不可解な点が残る。サーバ=クライアント間で一体何を認証しているのか、ということだ。
X.509公開鍵認証基盤(PKI: Public Key Infrastructure)では、検証者が信頼の基点となる認証局(CA: Certificate Authority)を選び、これらのCAの証明書を予め安全な方法で入手する。検証者は、ある証明書を受け取ったとき、以下の手順でその証明書を検証する。まず、その証明書を発行したCA、そのCAの証明書を発行したCA、…と証明書のパスを辿る。これらの証明書パス中のいずれかの証明書が、信頼の基点となるCAの証明書の集合の内のいずれかと一致すれば、その証明書を信用するに足る、と判断する(というのは乱暴な説明だが、ここはこのくらいで許しといてくれ)
今回の場合、NTPサーバ側もNTPクライアント側も、信頼の基点となる認証局を設定しなかった。とすると本来、どんな証明書を受け取っても、信頼しない、と判断しなければならないはずだ。しかし、実際には「auth: ok」となっている。

サーバ側の鍵および証明書を発行するとき、ntp-keygenコマンドに-Tオプションを付加した。これで何が変わるかというと、証明書中に証明書エクステンション(X509v3 extensions)にcriticalでない拡張鍵用途フィールド(X509v3 Extended Key Usage)が追加され、これに「Trust Root」が指定されていることだけのようだ。実際、-Tオプションをつけずにサーバ側で鍵・証明書を生成すると、クライアント側は時刻同期しないようだ。

以上のことから考えると、現状のntpdでは、サーバ側で-Tを付けているかつけていないかを認証しているに過ぎない。まあ、途中で鍵や証明書が変更されたらそれに気付くのかもしれない(ちゃんとAutokeyのドキュメントを読めば解るのかもしれないが、まだ読めてません…)が、せいぜいその程度だ。実装の問題じゃないかと思うのだが…

ドキュメントkeygen.htmlを読むと次のように書いてある。
As mentioned on the Autonomous Authentication page, the default TC identity scheme is vulnerable to a middleman attack.
もともと脆弱性があるんだから、使うなということだろうか?

第一回:『NTP認証: ユニキャスト・共通鍵認証篇
第二回:『NTP認証: ブロードキャスト・共通鍵認証篇
第三回:『NTP認証: ntp-keygenコマンドとX.509証明書
第四回:『NTP認証: ユニキャスト・公開鍵認証篇
第五回:『NTP認証: マルチキャスト・共通鍵認証篇