時刻同期

ntpdのこまったところ

  • 0.0.0.0:123をbind(2)する

後述のようにACLをかけられるとはいえ、INADDR_ANYは気持ち悪い気がします。また、FreeBSDのJail環境など、見えているNIC全てにbind(2)されると困る場合もあるでしょう。

  • ACLの書き方が分かりづらい

nomodify/notrap/noquery/nopeerなどキーワードがたくさんで分かりづらいです。うっかりmonlistのようなリクエストに応答するような設定にしてしまいそうです。

他の実装: OpenNTPD

http://www.openntpd.org/

いいところ: 0.0.0.0:123をbindしない

デフォルトでは、NTPサーバーとして指定されたホストとconnect(2)するだけです。このとき発信元UDPポート番号は123固定ではなく、ランダムなポート番号が選択されます。
設定ファイルで明示的に

listen on 192.0.2.123
listen on 2001:db8::beef::123

と指定すると、そのローカルアドレスをbind(2)してNTPリクエストに答えるようになります。ただし細かいACLは記述できないようなので、より細かいアドレス単位で制限するにはOSのパケットフィルタなどを利用することになると思われます。

いいところ: セキュアな実装

OpenSSHと同様に、特権が必要な最小限の操作を行うプロセスと、そのほかの仕事を行う(一般ユーザー権限で動作するchrootされた)プロセスに分離されています。

またclient.cやOpenCon 2004でのプレゼンテーションを読むと分かるのですが、リクエストのTransmit Timestampフィールド(64ビット)に(暗号学的に安全で)ランダムな値をクッキーとして格納してクライアント側でも保存しておき、応答を受信したときに照合して応答が偽装されていないことを確認しています。RFC 958では、リクエストのTransmit TimestampフィールドはレスポンスのOriginate Timestampフィールドにコピーされることになっています。このアイディアは、応答の偽装を防ぐほかに、クライアントの現在時刻が外に漏れないという効果もあります。

こまったところ: ポータブル版がメンテナンスされていない

OpenNTPD 4.4は2008年11月にリリースされましたが、OpenBSD以外でも動作するポータブル版は、2014年9月現在でもOpenNTPD 3.9p1となっています。

公式サイトに「ポータブル版は古くなっており、メンテナーを必要としてる」と記載されている状態です。
DebianFreeBSDなど、ディストリビューションのメンテナーがメンテナンスしているものを利用するのがよいと思われます。数年前にポータブル版の差分をOpenNTPD 4.4に適用してちょっといじったものを手元でエージング試験(という名の放置)していました*1が、最近のDebianで提供されているパッケージはもう少し最近のものをベースにしているようです。OpenNTPD 3.9p1では存在しなかった機能としてntpd.driftファイルが作成されるようになりました。

ちなみにポータブル版は、他のプラットフォームで提供されていない関数(arc4random(3)、strlcpy(3)など)の実装を追加し、いくつか#ifdefマクロを追加した形となっています。移植性を確保するという点において、(別のチームが開発している)OpenSSLは、各種規格に準拠したプラットフォームをエミュレーションした上で開発するようなイメージ(個人の感想です)ですが、OpenNTPDやOpenSSHはOpenBSDという実在のプラットフォーム上で開発を行い、そこに存在しない・挙動の異なる箇所だけをポータブル版に実装するようなイメージ(個人の感想です)です。

こまったところ: ntpqのようなコマンドがない

ntpdではntpq -pコマンドでピアの一覧と状態を調べることができますが、OpenNTPDにはこのようなコマンドがありません。ピアがvalidになった/invalidになったときにsyslogにメッセージを出力するだけです。SIGINFOシグナルを送ると、各ピアがvalidか否かをsyslogに出力することはできます*2が、ntpq -pコマンドのようにoffsetやjitterなどは得られないようです。monlistリクエストもサポートしていません。

こまったところ: 機能的な制限がある

ブロードキャストNTPには対応していないようです。また、NTP Authentication(共通鍵暗号公開鍵暗号を用いてNTPメッセージを認証する機能)にも対応していないようです。どちらも使ったことがないのであまり困っていないのですが。
ntp.orgの説明によると、マイクロ秒単位の精度を得られることを設計上のゴールとしていないと書いてあるのですが、adjtimex(2)などを呼び出しているあたりのコードを読めていないので、よくわかりません。

他の実装: Chrony

http://chrony.tuxfamily.org/

インストールして

chronyc sources -v

コマンドを実行して、ntpq -pより見た目が豪華なのを確認した程度であまり触れていません。そのうち書くかも。

まとめ

0.0.0.0:123をntpdがbind(2)する件でお困りの方で、マイクロ秒単位の時刻同期を必要としない方は、OpenNTPDを使うと幸せになれるかもしれません。

*1:ポータブル版やDebianのパッチなどあちこちからコードを拝借したためライセンスが不明確になってしまった、ということもあります

*2:2014/9/19追記: SIGINFOがないので、Debianのパッケージではサポートされていません。SIGUSR1を代わりに使えばよい?