NTPオフィシャルサイト:
Home of the Network Time Protocol
オフィシャルDoc:
The Network Time Protocol (NTP) Distribution
Network Time Synchronization Research Project
The NTP Public Services Project

ntpd

NTP は、ネットワークを経由してコンピュータの時間を同期するためのプロトコル。通信は UDP プロトコルの 123 番どうしで行う。そして、NTP サーバデーモンの標準が ntpd だ。マシン自体の時計を合わせるだけなら、 NTP パッケージに含まれる ntpdate を使ってもいいが、オフィシャルドキュメントによると、 ntpdate はエラーハンドリングが「いい加減」なので、ntpd-q オプションで使ったほうが良いようだ。

UNIX, Linux はサーバ運用を主眼として作られているので、時間が急に変わってしまっては問題が生じることが多い。そのため、ntpd は、マシンのクロックが違っていたからといって、いきなり何十分も遅らせたり進めたりはしない。連続性が失われないよう 「1 秒の長さ」 を実際よりも長くしたり短くしたりすることによって、徐々に補正していこうとする (一概に言えない - 後述 デーモン起動オプション-x オプション参照)。そこは、所詮クライアントOSの域を出ない WINDOWS の時間補正とは大きく異なる点だ (※)。設定オプションによっては WINDOWS のようにガバッと合わせることも可能だが、某かのサーバとして運用中の Linux マシンでは「ガバッ」はなるべく避けなければならない。

※ Windows 2003/XP 以降の w32time は SNTP でなく NTP を実装しており、ntpd のようにクロックを徐々に調整する方式が標準になった。「Linux野郎のための WINDOWS 2003/XP/2008/2012 時刻同期解説」を参照のこと。

NTP パッケージは仕様がコロコロ変わるしドキュメントも読みにくく、設定ディレクティブ用の語彙が適切さを欠いているなどの点で、筆者が最も嫌いなサーバソフトのひとつだ。例えば、以前は ntp-keygen という名前だった認証用キー作成ユーティリティが、 4.1.x で ntp-genkeys という名前に変わり、 4.2 で再び ntp-keygen に戻ったりした。しかもコマンドオプションまで変わっていたりする。PC及びカーネルのクロックについての概略は、The Clock Mini-HOWTO でつかめる - 日本語訳は JF に上がっている。インストールについては説明を省く。

Table of Contents

設定ファイル一覧

/etc/ntp.conf メインの設定ファイル
/etc/sysconfig/ntpd RedHat系で起動オプションを記述しておくファイル
/etc/sysconfig/ntpdate RedHat系で ntpdate の起動オプションを記述しておくファイル
/etc/ntp/keys 認証に使われる対称鍵ファイル。このファイルはシンボリックリンクで、実体は /etc/ntp/ntpkey_MD5key_hostname.timestamp または、NTP 4.2.4 でキーを暗号化してある時は /etc/ntp/crypto/ 下の同名ファイル
/etc/ntp/step-tickers 簡易的に時刻同期を行う非デーモン型のツール ntpdate が参照するファイル。同期のために参照するタイムサーバを書いておく

他にもあるが、一般的な使用で必要なのはこれだけ。認証ファイルのパスはディストリビューションによっても違う。 デフォルトでインストールされた主設定ファイルに記述があるはずなので確認していただきたい。

付属ユーティリティ一覧

ntp-keygen ntpd 用の暗号キーを作成するプログラム
ntpstat NTP稼働状態の概略を表示する
ntpdate 非デーモン型の時刻合わせクライアントプログラム
ntpdc ntpd の状態を見たり、設定を変更するためのインターフェース
ntpq 現在の優先NTPサーバがどれかなど、NTPサーバの稼働状況の詳細を問い合わせる
ntptime クロック関連のカーネル変数値を表示する
tickadj カーネルの「1秒」が「何マイクロ秒」にあたるか表示、微調整する
ntptrace 指定したタイムサーバがどういった上位サーバから時間を得ているか、stratum 1 まで遡って調べる

インストールの仕方やディストリビューションによって、一部なかったりするかもしれない。

設定

デーモン起動オプション

ntpd の起動オプションには、主に、以下のものがある。この他は滅多に使う必要がないか、主設定ファイルで指定すれば良い。

-a 認証機構を有効にする (デフォルト)。主設定ファイルで指定すれば良い
-A 認証機構を無効にする。やめておいたほうがいい (理由は後述)
-c conf_file 主設定ファイルの場所を指定
-d num デバグモード。num の数字が高いほど冗長
-g ntpd は通常、参照した NTP サーバと現在のカーネルクロックの差異が 1000秒 より大きい場合には、メッセージを吐いて exit する。マザーボードやカーネルの異常の可能性があるからだ。この差異の閾値を ntpd では `panic threshold' と呼ぶ。そのチェックを無効にするのがこのオプション。ただし、異常を無視するのは 1回だけで、次にまた 1000秒を超える差異があった場合にはやはり exit する。マシンを純然たるクライアント用途で使っている場合を除いては、-g オプションの使用は控えたほうがいい。狂いが大きい場合には、`ntpdate -b -v server ' でカーネルクロックを強制的に修正し、 `hwclock --systohc' でハードウェアクロックをカーネルクロックに合わせてから ntpd を起動するのが常套手段。なお、-g 起動オプションの代わりに、設定ファイルの tinker panic ディレクティブで panic閾値調整することもできる
-f drift ファイルのパスを指定。 drift ファイルとは、参照時計と現在のカーネルクロックとのずれを記録するファイル。通常は主設定ファイルでディレクティブによって指定する
-l ログの出力先を指定。デフォルトでは syslog デーモンに渡す
-x ntpd の動作にはふたつのモードがある。slew モードと step モードだ。slew モードでは、 1 秒あたり最大で 0.5ms (0.0005 秒) づつ徐々に時間を合わせ、連続性を重視する。step モードでは、不連続に時間を一気に進める (または遅らせる)。 デフォルトでは、時間のずれが 128 ms (0.128 秒) よりも小さかった場合には slew 動作を行い、128 ms 以上ずれた状態が 300秒以上続くと step モードに切り替わる。動作切替の閾値を ntpd では `step threshold'、それがどれだけ長く続いたら動作を切り替えるかの閾値を `stepout threshold' と呼ぶ。-x オプションを指定すると、step閾値が 600 秒という非常に大きな値に変わり、 ntpd は (実質的に) 専ら slew モードで動作することになる。-x オプションは一見、時間の連続性を保つという点で好ましいように思えるが、slew モードでは 10 秒の狂いを調整するのに 20000 秒 (= 10 / 0.0005) つまり 5 時間半もかかってしまうということを頭に置いておかなくてはならない。なお、起動時に -x オプションを与える代わりに、設定ファイルの tinker ディレクティブを使えば step閾値stepout閾値を任意の値に設定することもできる
-q 時間合わせが済み次第 ntpd は exit する。 ntpd をデーモンとしてではなく ntpdate 的に使うわけだ。 cron などでスケジューリングする時に -g オプションと組み合わせて使用することが多い
-u user ntpduser 権限で動かす。当然 user ユーザはあらかじめ作成しておかないと駄目。或るバージョンの ntpd では大文字の -U だったり、`-u ntp:ntp' という具合に UID と GID が指定できたりと仕様が何度か変わってきているので、使う前に一度 man で確認した方がいい
-i /dir ntpd が自らを /dirchroot する。詳しくは「ntpdをchrootする」を参照
-I iface [4.2.4のみ] リッスンするインターフェイスを限定する。`-I eth0 -I lo' のように複数回使用可能。4.2.2 には、逆にリッスンしない IP を指定する -L というオプションがあるようだが、仕様が無計画にコロコロ変わってあんまりアホらしいので無視
-4 名前解決の際に、IPv4 アドレスへの解決のみ試みる。OSとして IPv6 が殺してある時は指定した方がよい
-6 名前解決の際に、IPv6 アドレスへの解決のみ試みる

多くの動作オプションは主設定ファイル内で設定できるので、起動時にオプションとして渡すとすれば -u, -4, -i などといった程度。一般的には、起動スクリプトで指定するのだろうが、RedHat系では /etc/sysconfig/ntpd ファイルで OPTIONS 変数に書いておくと、rcスクリプトがこのファイルをインクルードして ntpd の起動引数に加えてくれる。ただし -x オプションだけは、 ntpd に直接渡す時とはちょっと異なり、sysconfig/ntpd ファイルから渡すと step-tickers 動作を行う仕掛けがされている。

主設定ファイル /etc/ntp.conf

メインの設定ファイルは、どこのタイムソースサーバに時間を合わせるかはもちろん、どの範囲のクライアントにこのサーバの参照を許すかなど、セキュリティ面でも非常に重要な規定を行う。ntpd は、時間を合わせられる こともできる。たかが時間合わせと侮るなかれ、大幅にクロックを狂わせれば、サーバ上のサービスをダウンさせるのも簡単だ。さらに、ntpdc という「両刃の剣」とも言える付属ユーティリティを使えば、 ntpd の設定をリモートで随時変更することも可能なのだ。設定例は下記、それから要点を説明する。ここで述べるのはディレクティブの一部に過ぎないが、通常はこれだけで事足りる。

tinker step 2 stepout 300 panic 1800
tos orphan 6
disable monitor
 
restrict default ignore
restrict 127.0.0.0 mask 255.0.0.0
restrict 192.168.0.1
restrict 210.173.160.57 noquery nomodify notrap nopeer
restrict 133.40.41.134 noquery nomodify notrap nopeer
restrict 192.168.0.0 mask 255.255.255.0 noquery nomodify nopeer
 
driftfile /var/lib/ntp/drift
 
# ntp2.jst.mfeed.ad.jp
server 210.173.160.57 maxpoll 11
 
# one of s2csntp.miz.nao.ac.jp
server 133.40.41.134 prefer maxpoll 11
 
# local clock
#server 127.127.1.0
#fudge 127.127.1.0 stratum 10
 
crypto pw secret
# includefile /etc/ntp/crypto/pw
 
keys /etc/ntp/keys
# trustedkey 1 998
# requestkey 998
# controlkey 998

NTP サーバ環境構築のポイント

NTP サーバには、このように自分で構築するサーバも含めて、stratum (ストレータム=階級) というものが必ずある。stratum の数字が小さいほど、その NTP サーバは階級が高い。stratum 1 のサーバは、我々が時間合わせに使ってはいけない(NICTなど例外もある)。そうした上位階級 NTP サーバは、それ自身で電波時計や原子時計などの基準デバイスを備え、次の階級のサーバから時間合わせのために参照される。下々の有象無象がいちいち参照したら、starum 1 サーバに無用な負荷をかけてしまう。よって、我々が通常使うのは stratum 2 の NTP サーバだ。公開されているサーバは、ネットの検索エンジンで「NTP サーバ 公開」などとして検索すれば出てくるだろう。自分の加入しているプロバイダが NTP サーバを公開しているのならば、それを使うのも手。NTP サーバとそのサブネットを構築する上で要となる、その他の鉄則を以下に挙げておく:

server ディレクティブ

server コマンドは、参照する NTP サーバの指定に使う。NTPv4 プロトコルでやりとりされるデータは、世界標準時における 1900 年 1 月 1 日 00:00 からの経過時間 (秒) なので、NTP サーバが日本にあろうがアメリカにあろうが基本的には関係ない。ただし、パケットを要求してからこちらに届くまでのタイムラグは、正確な時間補正に影響を与えるので、経路コストの低いサーバを参照したほうが良いとされている。ただ、ntpd は、stratum はもちろん、参照するクロックのジッター (時間の刻みの微妙な揺らぎ) や、到達に要するタイムラグなど、様々な要素を総合評価しているので、複数のサーバを指定した場合 (普通はそうする) には、メインとして参照するサーバ (これを System Peer と呼ぶ) が逐次選択しなおされる。そうした評価をこちらの意向や都合で変えるもののひとつが、例に見られる prefer というキーワード。「なるべくならこれをつかってよ」という意味だ(※)。

※ さらに、候補選定でなるべく生き残らせる true というキーワードもある。

サーバに対して時間確認を行う頻度のことを、ポールインターバル (poll interval) と呼ぶ。ポールインターバルは、ntpd では動的に変化していく。これは、最小 (minpoll) と最大 (maxpoll) で規定され、デフォルトでは、ローカルの時計が安定しないうちは 64 秒毎、それから次第に、128 秒、256 秒と間隔が長くなり、最終的には最大ポールインターバルである 1024 秒 (デフォルトの場合) に落ち着く。これらふたつの値は server コマンドのオプションとして "minpoll num " または "maxpoll num " あるいはその両方を指定して、変更することもできる。間違えやすいのは、この num が文字通りの秒数ではないという点だ。num は 2を基底とする指数、つまり 2n の n にあたるもの (ビット数とも言える)。maxpoll のデフォルト値は 10 (1024秒) で、指定可能な最大値は 17 (約36時間25分)。minpoll のデフォルトは 6 (64秒) で、指定できる最小値は 4 (16秒) となっている。例では maxpoll を 30分くらいにしたいと思い、num を 11 (約34分) に設定している。また、minpoll を 30 秒くらいにしたいなら num には 5 (32秒) を指定する。

!! ここでは使用例を示すために maxpoll を使っているだけで、34分に変更するのが必ずしも最適というわけではない。

server コマンドで、もうひとつ、127.127.1.0 (127.127.1.1 でもいいようだ) を書いている(ただしコメントアウト)。これは、自分のマシンのマザーボード上のクロック (ハードウェアクロックとかリアルタイムクロック [RTC] とも呼ばれる) だ。自分のハードウェアクロックを server として追加登録すると、万が一、他の参照サーバが全部不合格だった場合の「押さえ」となる。 fudge コマンドは、本来、ハードウェア的な基準時計から時刻を読み込む際に使うコマンドだが、筆者は別途電波時計などのデバイスを接続した経験はない。興味のある人は Reference Clock Options を読んでみるといいだろう。

ただし、ntp-4.2.2 以降では、fudgeserver で RTC を指定することの代替として orphan という仕組みが導入されたので、そちらを使った方がいい。詳しくは tos の項を参照。

server コマンドでローカルクロックを指定しないほうがいい、とするドキュメントも多く見られる。Linux はどうやら、他の参照クロックをすぐに切り捨ててローカルクロックを優先同期先に選んでしまう傾向があるからだ。筆者も最近では `server 127.127.1.0' を書くことはほぼない。

pool ディレクティブ

ntp.jst.mfeed.ad.jp や s2csntp.miz.nao.ac.jp など、DNSラウンドロビンによって特定またはランダムな実ホストを返してくるサイトを利用するためのもの。左記に挙げたサイトはどちらも、DNSで牽いた時に、1回のクエリで 3つの IPアドレスを返してくる。これを

pool ntp.jst.mfeed.ad.jp

のように指定すると、牽かれたうちの 1つの IPアドレスしか ntpd のタイムソース候補に登録されない "server ..." とは違い、3つの IP全てが登録される。ただし、Automatic Server Discovery 機構 (オフィシャルDoc) が一枚噛むということの他には、動作にはほとんど違いはない。指定するのは DNSラウンドロビンのタイムサーバだけとは限らず、通常の単一ホストを追加で pool 指定することもできる。

pool ディレクティブは複数回使うことができ、そうすると、ntpd に登録されるリストは全ての pool 指定サイトからリゾルブされたホストの総和となる。重複したIPは自動的に除外される。ntpd によるサンプリング評価で不合格となったホストを除き、既定では最大 10ホストが System Peer 候補に残る (tosディレクティブmaxclock オプションで変更可能)。

タイムサーバを pool ディレクティブだけで指定している場合、/etc/ntp/step-tickers が空だと、ntpdate サービスは失敗する。init.d/ntpdate スクリプト (RHEL/CentOS6の場合。EL7では /usr/libexec/ntpdate-wrapper) は、step-tickersファイルが空と分かると、ntp.conf から "server" または "peer" で始まる行だけを抽出して ntpdate コマンドの引数にしているからだ。とはいえ、そのためだけに ntp.confpoolserver を併記しておくのも ntpd の動作上きもち悪い。pool を活用する時は、ntp.conf で指定している pool サイトのうちのひとつ (リゾルブ後のサーバ 1つか2つでも可) を step-tickers に書いておくのがよい。

peer ディレクティブ

peer ディレクティブは、server ディレクティブによって指定してある時刻参照先サーバが全てダウンした時の、バックアップタイムサーバを指定するためにある。NTP の用語ではこれを、シンメトリック (Symmetric) モードという。peer だけ指定して serverpool を指定しない設定は通常あり得ない。通常の参照先が1つでも生き残っている間は、peer指定の参照先は時刻参照には使用されない。シンメトリックモードを組むタイムサーバは、それぞれ異なったタイムソースを参照していないとあまり意味がない。

例えば、LAN内の NTP トポロジーの頂点に、同じ階層 (stratum) のNTPサーバA とNTPサーバB が立ててあるとする。この時、サーバA とサーバB を互いにシンメトリックピアにしておけば、サーバA の参照している外部のNTPサーバが全てダウンしたとしても、サーバA はサーバB に時刻を同期して、自機の時刻を正常にキープすることができる。また、逆の局面ではサーバA がサーバB を助けてやれる。それだけでなく、(NTPの Association Management ページによると) 生き残った健常なシンメトリックピアは、他のピアの時刻提供能力喪失を検知でき、クライアントへの時刻提供の責務を迅速に引き受けることができるというメリットもあるらしい。このように互いに相手を peer にしている状態を、シンメトリック-アクティブ モードと呼ぶ。それに対して、サーバB の設定ファイルにはサーバA が peer指定されておらず、サーバA が一方的に peer を張っている状態を シンメトリック-パッシブ モードという。

peer の基本的な記述法は、前記 server ディレクティブとほぼ共通。前出の ntp.conf をベースにすると、シンメトリック-アクティブ モードの場合のサーバA (192.168.0.1) とサーバB (192.168.0.2) それぞれの主設定ファイルは以下のようになる。

サーバA (192.168.0.1)
tinker step 2 stepout 300 panic 1800
tos orphan 6
disable monitor
 
restrict default ignore
restrict 127.0.0.0 mask 255.0.0.0
restrict 192.168.0.1
restrict 192.168.0.2 noquery nomodify
restrict 210.173.160.57 noquery nomodify notrap nopeer
restrict 133.40.41.134 noquery nomodify notrap nopeer
restrict 192.168.0.0 mask 255.255.255.0 noquery nomodify nopeer
 
driftfile /var/lib/ntp/drift
 
# Symmetric Peer
peer 192.168.0.2 key 8 minpoll 6 maxpoll 6 true
 
# ntp2.jst.mfeed.ad.jp
server 210.173.160.57 maxpoll 11
 
# one of s2csntp.miz.nao.ac.jp
server 133.40.41.134 prefer maxpoll 11
 
# local clock
#server 127.127.1.0
#fudge 127.127.1.0 stratum 10
 
crypto pw secret
# includefile /etc/ntp/crypto/pw
 
keys /etc/ntp/keys
trustedkey 8 998
# requestkey 998
# controlkey 998
サーバB (192.168.0.2)
tinker step 2 stepout 300 panic 1800
tos orphan 6
disable monitor
 
restrict default ignore
restrict 127.0.0.0 mask 255.0.0.0
restrict 192.168.0.2
restrict 192.168.0.1 noquery nomodify
restrict 210.173.160.27 noquery nomodify notrap nopeer
restrict 210.173.160.87 noquery nomodify notrap nopeer
restrict 192.168.0.0 mask 255.255.255.0 noquery nomodify nopeer
 
driftfile /var/lib/ntp/drift
 
# Symmetric Peer
peer 192.168.0.1 key 8 minpoll 6 maxpoll 6 true
 
# ntp1.jst.mfeed.ad.jp
server 210.173.160.27 maxpoll 11
 
# ntp3.jst.mfeed.ad.jp
server 210.173.160.87 maxpoll 11
 
# local clock
#server 127.127.1.0
#fudge 127.127.1.0 stratum 10
 
crypto pw secret
# includefile /etc/ntp/crypto/pw
 
keys /etc/ntp/keys
trustedkey 8 999
# requestkey 999
# controlkey 999

アクセス制限:

peer指定:

trustedkey指定:

テスト&デバグ方法

ピア両方の主設定ファイルと対称鍵ファイルを整備後、ntpd をリスタートして、外部参照クロックの選定が終わる頃を見計らって ntpq ツールで状態を確認する。

root# ntpq
ntpq> lpeers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 192.168.0.2     210.173.160.27   3 u   46   64  376    0.919  -306.72  12.189  <--st=16やoffset=0は異常
*133.40.41.134   133.243.238.244  2 u   30   64  377   10.162   19.916  42.331
 
ntpq> assoc
ind assID status  conf reach auth condition  last_event cnt
===========================================================
  1 55276  f014   yes   yes   ok     reject   reachable  1  <--reach=yesでauth=okであれば正常
  2 55277  9614   yes   yes  none  sys.peer   reachable  1
 
ntpq> pstatus 55276
assID=55276 status=f014 reach, conf, auth, 1 event, event_reach, <--reach、authがあること。状態コードが eで始まるのは変
srcadr=192.168.0.2, srcport=123, dstadr=192.168.0.1,
dstport=123, leap=00, stratum=3, precision=-23, rootdelay=10.437,
rootdispersion=586.502, refid=210.173.160.27, reach=036, unreach=0, <--(以下略)

ここで試しに、カーネルファイヤーウォール iptables を使って外部クロックサーバを参照不能にしてみる。

root# iptables -A OUTPUT -p udp -d 133.40.41.134 --dport 123 \
 -j REJECT --reject-with icmp-host-unreachable

暫く後、状態の推移を観察してみる。

ntpq> pstatus 55276
assID=55276 status=f414 reach, conf, auth, sel_candidat, 1 event, event_reach, <--候補に格上げされた
srcadr=192.168.0.2, srcport=123, dstadr=192.168.0.1,
dstport=123, leap=00, stratum=3, precision=-23, rootdelay=10.452,
rootdispersion=365.265, refid=210.173.160.27, reach=376, unreach=0,
 
ntpq> assoc
ind assID status  conf reach auth condition  last_event cnt
===========================================================
  1 55276  f414   yes   yes   ok   candidat   reachable  1  <--候補になっている
  2 55277  8623   yes   yes  none  sys.peer  lost reach  2  <--外部サーバは通信不可だがまだ優先参照先のまま
 
ntpq> lpeers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*192.168.0.2     210.173.160.27   3 u   28   64  377    0.029  -322.55   1.115  <--さらに暫く後、遂に優先参照先に
 133.40.41.134   133.243.238.244  2 u  909   64    0   10.037   -9.161   0.000
 
ntpq> pstatus 55276
assID=55276 status=f614 reach, conf, auth, sel_sys.peer, 1 event, event_reach,  <--優先参照先になっている
srcadr=192.168.0.2, srcport=123, dstadr=192.168.0.1,
dstport=123, leap=00, stratum=3, precision=-23, rootdelay=10.315,
rootdispersion=324.524, refid=210.173.160.27, reach=376, unreach=0,

実験が終わったら、ファイヤーウォールを元に戻すのを忘れずに。

root# iptables -D OUTPUT -p udp -d 133.40.41.134 --dport 123 \
 -j REJECT --reject-with icmp-host-unreachable

tinker ディレクティブ

ntpd の時刻合わせアルゴリズムを調整する場合に指定する。書くなら、設定ファイルの一番最初に書かなければならない。上の例は、「参照クロックと 2秒以上ずれた状態が 300 秒以上続いたら slew モードから step モードへ動作を切替え、1800秒以上のずれが 2回続いたらデーモンを停止する」を意味する。既定動作では、ずれが 0.128秒以上の状態が 300秒以上続いた時に step モードに切り替わり、1000秒以上のずれが 2回連続して認められた時に停止する。ただし、上の例はあくまでも例であって、お勧めというわけではないので念のため。

step閾値は、0 に設定すると、ntpd は決して step モードへ移行しなくなる。panic閾値を 0 にすると、どんなに時間のずれた参照クロックにでも時刻を合わせる。stepout閾値は、マニュアルによると、他の動作にも影響を与えるので 300秒より小さくしてはならないとされている。tinker ディレクティブを書く時は 3つのオプションをセットで書かなければならないわけではない (そもそも tinker のオプションは他にもっとある)。サーバの設定ガイドなどでしばしば見かけるのは `tinker panic 0' の指定だ。

tos ディレクティブ

tos は、ntpd のタイムソース選定に関する動作を変更するためのディレクティブ。オフィシャルドキュメントに曰く "滅多に触ることはないが、そこにツマミがあると回す誘惑に耐えきれない輩も..." と。パラメータは幾つもあるが、変更することがあるのは以下の項目くらいだ。複数のパラメータを変更したい時は、ひとつの tos 行で、

tos orphan 6 maxclock 5

といった具合に書く。

orphan

ntp-4.2.2 以降では、fudge で RTC を指定することの代替として、orphan という仕組みが導入された。これを上記例 2行目のように tos コマンドで指定しておくと、他の参照サーバが全部駄目になった時にも NTPクライアントに時刻を提供し続けることができる。よって、純然たる NTPクライアントntp.conf に書いても無意味だ。orphan を使う時は "server 127.127.1.0" はもちろん "fudge 127.127.1.0" も書かない。orphan の引数は stratum で、"tos orphan 6" とすると、stratum 1 以上 5 以下のタイムソースが参照できているうちは orphan モードに切り替わらない。support.ntp.org の OrphanMode によると、参照ソースの想定される最悪の stratum + 2 の値にするのが妥当とされている。また、ntpd の起動直後や短時間の一時的なネットワークトラブルなどで orphan モードにころころ切り替わることのないよう、既定では 300秒 (=5分) の猶予期間が設けられている(※)。

※ 猶予時間は tos コマンドのパラメータ "orphanwait SEC" で変更できるらしいが、実装されたのは 4.2.7 (?)からで、CentOS 7 の ntp-4.2.6p5 では検証できない。

maxclock

pool ディレクティブでタイムソースリストに登録されるホストが多数の場合に System Peer 候補として残すホストの上限数。既定は 10。正確でない、遅延が大きいなど他の選定基準で落選しているホスト (ntpq コマンド出力の先頭記号の説明参照) は勘定に入らない。

アクセス制限 (restrict)

restrict コマンドは、アクセスの restriction (制限) を規定するコマンド。書式は:

restrict {host|default} [mask netmask] [parameter] [parameter] ...

平たく言えば、「パケットの送信元が host にマッチしたら parameter を適用せよ」という構文だ。host 部は、アドレスでも、DNS や /etc/hosts での名前でも良い。例に挙げたアクセス制限セクションの1行目は、以降のマッチに当てはまらないアドレスだった場合の規定動作を default という特別なホスト部を使って指定している。主なパラメータには以下のものがある。support.ntp.org の AccessRestrictions が要点を突いていて分かりやすい。

ntp-4.2.7p22 で、ホスト部のキーワードに source というものも追加された。後述のコラム参照。

ignore すべての NTP パケットに答えない
noquery サーバの設定変更や状態の確認/変更に使用される NTP モード 6 (ntpq で使用) および 7 (ntpdc で使用) のパケットは受け付けない。時間の問い合わせには影響なし。なお、これらのパケットも UDP の 123 番ポートを使用する点に変わりはない。restrict による方法以外で、特に危険な一部のコマンドだけを無効にするやり方もある(※1)
nomodify noquery のモードに当てはまるパケットが送られ、実際に設定や状態が変更されるようなコマンドが来た場合には拒否する。noquery よりは規制が若干緩いことになる。時間の問い合わせには影響なし
notrap host に対して、こちらの NTP内部情報 (設定変数や時間の参照源などの情報) を提供しない。そうした情報の伝達に使われるのは NTP モード 6 のサブセットで、 `control message trap service' と呼ばれる。 ntpq に返答を返さなくなるが、時間の問い合わせには影響なし。 noquery との差異が分かりづらいが、 noquery は「要求を受け取らない」であるのに対し、 notrap は「返答を返さない」ということのようだ
notrust NTP Ver.4.2 以降と 4.1 以前とでは働きが大きく異なる。バージョン 4.1 まででは、「時間の参照源としては使わない (信用しない) が、その他の面では制限なし」の意。かたや NTP 4.2 からは、「参照源としてだけでなくクライアントとしても信用しない。ただし暗号認証によって信頼関係が証明されればその限りでない」という意味となり、サーバ側でこれを指定された host やサブネット (クライアント) からは、そのサーバを時間参照することさえできなくなる
limited ntpd のレートリミット(※2) を超えた頻度の問い合わせに対して、参照サービスの提供を拒絶する。モード 6/7 つまり ntpq 及び ntpdc のパケットはこの規制の対象とならない。limited を指定した restrict セクションがひとつでもあると "disable monitor" は無効(つまり monitor機能有効) になることに注意
limited
(旧)
ntpd は、ひとつのネットワークセグメントから同時に問い合わせできるクライアントの数を制限することができ、この制限パラメータを付けた host から問い合わせがあると、そのクライアントは接続数にカウントされる。「同時に」とはいっても、1度問い合わせがあるとそのクライアントは一定時間「アクティブ」なものとして記録に蓄積されるので、すぐに勘定からはずされるわけではない。蓄積時間は、別途 clientperiod コマンドで指定もでき (デフォルトは 3600 秒)、クライアントの「同時」接続台数は clientlimit コマンドで指定できる (デフォルトは 3 台)。その後、 clientperiodclientlimit コマンドは廃止された?
kod "Kiss of Death" の頭文字。通常、ntpd のレートリミットを犯した問い合わせパケットは破棄されるだけだが、kod の指定してあるクライアントに対しては、破棄するとともに キス・オブ・デス パケットが送られる。KoD は NTPプロトコルのパケットフォーマットのひとつで、クライアントに対して「もう問い合わせをやめてくれ」という意向を伝えるもの。KoD を受け取った NTPクライアントは、「断られた」ことを示すビットを立て、そのサーバへはもう問い合わせをしなくなる決まりになっている。KoD パケットの送信自体、最大 1パケット/秒 (送信元アドレス毎) に制限されており、それ以上の頻度で送られてきた失礼な問い合わせパケットはただ単に破棄される。この仕組みによってビットの立ってしまったクライアントと当該サーバとの通信を再び可能にするには、クライアントとサーバ両方の ntpd を再起動しなければならないらしい。kod を指定する場合は limited も指定されていないと機能しない点に注意
noserve ntpq 及び ntpdc のパケットだけを受け入れ、時間参照サービスは提供しない。つまり noquery の逆
nopeer シンメトリック-アクティブモード締結の申し出 (NTP モード 1 のパケット) を受け付けない

※1 CVE-2013-5211 で、ntpdcmonlist コマンドを悪用し、細工をしたリクエストを送ることによって、リクエスト送信元とは別のコンピュータへリクエストの数10から数100倍の量のパケットを送りつけることができる脆弱性が見つかった。support.ntp.org の Security Notice に目を通すと、それ以外にも、「対策: ntpd.conf に restrict ... noquery を記述」と書かれている脆弱性が幾つもある。対策のひとつとして、RHEL/CentOS 7 では、デフォルトの ntpd.conf
disable monitor
が書かれるようになった。disable/enable コマンドは ntpd の特定の機能をグローバルに無効化/有効化するもので、monitor を指定すると ntpqmonstats および mrulist コマンド (ともに ntp-4.2.7 以降にしかないが) と、ntpdcmonlist コマンドなど、統計(statistics)系の一部の機能を無効化するようだ。外部ホストに対するアクセス制限に結果的に noquery が含まれていれば規制は "monitor" にも増して厳しいことになるのでその場合は不要だが、どうせ滅多に使わない機能なので "disable monitor" を書いておくのは悪くない。

※2 ntpd のレートリミッターは、パケットの秒間隔と、トークンバケツフィルタ (水漏れバケツフィルタ) による平均頻度を併用したものらしい。discard ディレクティブで調整も可能で、既定の秒間隔は 2秒、トークンバケツの「水」は 1パケット毎に 23 (つまり 8) 増え 1秒毎に 1 減る、とオフィシャルドキュメントの Rate Management and the Kiss-o'-Death Packet に書かれているが、だから結局どう動作するのかが未だ読み取れずにいる。

"restrict host " だけが指定してあってパラメータのないエントリは「制限なし」の意味となる。パラメータは常に、規制を強化する方向に働き、ひとつの restrict に複数のパラメータを指定すると、いずれかのパラメータが他のパラメータの効果を打ち消すことはなく、いわば制限ビットの上乗せ上乗せになっていくようだ。ただし、古いバージョンのドキュメントでは複数時の動作が曖昧だったので、まだ NTP 4.0.x や 4.1.x を使っているサーバでは、複数指定は避けたほうがいいと思う。ただし、例えば limitednotrust と、noquerynomodify とを組み合わせるなど、役割系統の異なるパラメータ同士なら構わないかもしれない。

の中の restrict セクション 4行目と 5行目は、参照に使う外部の公開 NTP サーバを、参照だけに使い、こちらの設定を変えようとしたり無用な状態問い合わせを行おうとする要求を受け付けないように、NTP パケットのモード 6 と 7 を「受けず答えず変更も拒絶」しシンメトリックモードも禁止している。そして最後の行は、サーバの置いてある LAN 内からの時間問い合わせに答えられるよう、mask キーワードを使用して 192.168.0.0/24、つまり 192.168.0.0 - 192.168.0.255 のアドレス範囲のクライアントに少し緩めの規制を施している (notrap を追加しても参照が成り立たないわけではない)。シンメトリック-アクティブ/パッシブモードを使用しないのなら、クライアントに対しては、より厳重にするため例のように nopeer を付加してもいい。

restrict コマンド行がこのように複数ある場合の ntpd の評価順序は、やや不気味だ。ntp.conf ファイルに書いてある順番ではない。ntpd は、まず、host のアドレスがより限定的具体的なものほど優先するカタチでソートを行い、その順番で評価していくのだ。例で言えば、192.168.0.1, 133.40.41.134 などは、マスクは暗黙に 255.255.255.255 なので同順で、最も限定的具体的なアドレスといえる。次が 192.168.0.0/255.255.255.0。その次は 127.0.0.0/255.0.0.0。そして、数字に直すと 0.0.0.0/0.0.0.0 である default が評価順位では最低になる。そうして最初にヒットした行が適用される。

なお、不正なパケットを、こうしたアプリケーションレベルに達する以前に水際でせき止めるために、ファイヤーウォールを設定するべきだ。外部から送られたパケットは送信元を詐称しているかもしれない。ファイヤーウォール専用のマシンを立てるに越したことはないが、サーバ自体の中にパケットフィルタを構築するだけでもかなりのセキュリティアップになる。

ntp.jst.mfeed.ad.jp 等のように DNSラウンドロビン で複数のIPアドレスを順不同で返してくる NTPタイムソースを利用する際には、注意が必要だ。"restrict ntp.jst.mfeed.ad.jp noquery ..." だけでは、IPアドレスに解決された後の実タイムサーバ全てまたは一部の参照がブロックされてしまう。このように書かなくてはならない。
restrict ntp1.jst.mfeed.ad.jp noquery nomodify notrap nopeer
restrict ntp2.jst.mfeed.ad.jp noquery nomodify notrap nopeer
restrict ntp3.jst.mfeed.ad.jp noquery nomodify notrap nopeer
pool ntp.jst.mfeed.ad.jp

restrict に指定するホストは、`dig ntp.jst.mfeed.ad.jp' を何度か発行してDNSサーバが返してくるIPをそのまま書いてもいいが、IPアドレスは変わることがあるので、それぞれを `dig -x 210.173.160.87' のように逆引きしてみてまともなホスト名が返ってくるようであれば、ホスト名で書いた方がより確実だ。

mfeed や s2csntp.miz.nao.ac.jp は上記のように決まったホスト群から成り立っているので問題ないのだが、困るのは、NTP Pool プロジェクトのサイト (0.pool.ntp.org 等や asia. あるいは jp.pool.ntp.org など) のように、多数の候補の中から DNSクエリで返るホストを一定時間毎にランダムに変えてくるものを pool ディレクティブで参照する場合だ。実際のタイムソースIPはその時々に蓋を開けるまで分からないので、規制をあらかじめ具体的に書いておくことができない。これに対応すべく、restrict のホスト部のキーワードに、source というものが ntp-4.2.7p22 で追加された。"restrict source ..." で規制定義を作成しておくと、ホストが候補リストに登録された時に自動的に適用され、候補から外れると剥がされて default の規制に戻る。残念ながら、RHEL/CentOS 7 でもまだ ntp-4.2.6 なので使えず、検証できていない。ただし、使えたとしてもどのみち、default 規制を緩める必要があるのではないかという疑念があり、セキュリティの穴にならないか心配が残る。

対称鍵の指定

keys から始まる最後の4行は、認証に使う対称鍵(Symmetric Keys) の指定だ。ntpd の認証機構は、いくつかの使われ方をする。どのサーバを参照サーバとして信用するか、この NTP サーバのコントロールを誰にどのような認証方式とパスワードで許可するかなど。認証機構については次節で詳しく述べている。

ntpd は、認証機構そのものを "disable auth" (あるいは "authenticate no" でも可 ?) で無効化することもできる。しかし、参照に認証を使わないからといって認証機構を切ってしまうのは、大きなリスクとなる。オフィシャルドキュメントが不親切なのでいろいろと実験してみたが、"disable auth" した場合、クライアントとしてこのサーバを参照することを許している LAN 内のマシンから、 ntpdc ユーティリティでほぼ自由に設定をいじれてしまうのだ。 ntpdc コマンドは、サーバの設定を変更するようなコマンドをそのセッションで初めて発行した際に、必ずキーID とパスワードを求めてくる。しかし、認証機構を根こそぎ無効にしてあると、プロンプトは「儀礼的」に出すものの、 restrict コマンドで nomodify が指定してあっても、見当外れの ID とパスワードを入力しても設定が変更できてしまった。よって、特に積極的に認証を使うつもりがなくても、後述する対称鍵ファイルは作成し、キーファイルの指定 (keys ディレクティブ) はしておくべきだ。そこまでやっておけば restrict nomodify の設定も間違いなく機能してくれる。

コメントアウトしてある後の 3行は、ntpdc ユーティリティや ntpq を使って ntpd の設定を動的に変更したり、シンメトリックピアとの通信に認証を掛ける場合に使う。まず、対称鍵認証を使うためには、後述の 対称鍵ファイルに記述したキーのうち、使用候補にする全てのキーID を trustedkey に並べておく必要がある。その上で、ntpdc ユーティリティ用のキーID は requestkey ディレクティブで、ntpq ユーティリティ用は controlkey ディレクティブで指定する。このふたつの記述がない場合、ntpd は 「ntpqntpdc による設定変更は一切させない」と解釈する。つまり、コンソールマシンから入力されたキーIDとキーフレーズは常に間違いであるという扱いになる。ピアの対称鍵認証に使うキーID は、前述したように peer ディレクティブのパラメータで指定する。

説明が前後するが、keys の前にある "crypto pw secret " のことを付け加えておかなくてはならない。これは、ホスト秘密鍵などを暗号化する機能に関するもので、ntp-4.2.2 (?) から追加された。このディレクティブは ntp-keygen でキーを暗号化して作成してある時、その読み取りパスワードを ntpd に教えてやる。ただし、セキュリティ上、この文言はパーミションビットを絞り込んだ別ファイルに書いておき、 includefile 命令句 (例でコメントアウトしてあるところ) で読み込ませるのが普通だ。