NTP は、ネットワークを経由してコンピュータの時間を同期するためのプロトコル。通信は UDP プロトコルの 123 番どうしで行う。そして、NTP サーバデーモンの標準が ntpd だ。マシン自体の時計を合わせるだけなら、 NTP パッケージに含まれる ntpdate を使ってもいいが、オフィシャルドキュメントによると、 ntpdate はエラーハンドリングが「いい加減」なので、ntpd を -q オプションで使ったほうが良いようだ。
UNIX, Linux はサーバ運用を主眼として作られているので、時間が急に変わってしまっては問題が生じることが多い。そのため、ntpd は、マシンのクロックが違っていたからといって、いきなり何十分も遅らせたり進めたりはしない。連続性が失われないよう 「1 秒の長さ」 を実際よりも長くしたり短くしたりすることによって、徐々に補正していこうとする (一概に言えない - 後述 デーモン起動オプション の -x オプション参照)。そこは、所詮クライアントOSの域を出ない WINDOWS の時間補正とは大きく異なる点だ。設定オプションによっては WINDOWS のようにガバッと合わせることも可能だが、某かのサーバとして運用中の Linux マシンでは「ガバッ」は避けなければならない。
NTP パッケージは仕様がコロコロ変わるしドキュメントも読みにくく、設定ディレクティブ用の語彙が適切さを欠いているなどの点で、筆者が最も嫌いなサーバソフトのひとつだ。例えば、以前は ntp-keygen という名前だった認証用キー作成ユーティリティが、 4.1.x で ntp-genkeys という名前に変わり、 4.2 で再び ntp-keygen に戻ったりした。しかもコマンドオプションまで変わっていたりする。PC及びカーネルのクロックについての概略は、The Clock Mini-HOWTO でつかめる - 日本語訳は JF に上がっている。インストールについては説明を省く。
| /etc/ntp.conf | メインの設定ファイル |
| /etc/sysconfig/ntpd | RedHat系で起動オプションを記述しておくファイル |
| /etc/ntp/keys | 認証に使われるキーファイル。このファイルはシンボリックリンクで、実体は /etc/ntp/ntpkey_MD5key_HOSTNAME.num または、NTP 4.2.4 でキーを暗号化してある時は /etc/ntp/crypto/ 下の同名ファイル |
他にもあるが、ホームサーバなど一般使用で必要なのはこれだけ。認証ファイルのパスはディストリビューションによっても違う。 デフォルトでインストールされた主設定ファイルに記述があるはずなので確認していただきたい。
| ntp-keygen | ntpd 用の暗号キーを作成するプログラム |
| ntpstat | NTP稼働状態の概略を表示する |
| ntpdate | ホスト自身のクロックを時間合わせするクライアントプログラム |
| ntpdc | ntpd の状態を見たり、設定を変更するためのインターフェース |
| ntpq | 現在の優先NTPサーバがどれかなど、NTPサーバの稼働状況の詳細を問い合わせる |
| ntptime | クロック関連のカーネル変数値を表示する |
| tickadj | カーネルの「1秒」が「何マイクロ秒」にあたるか表示、微調整する |
| ntptrace | 指定したタイムサーバがどういった上位サーバから時間を得ているか、stratum 1 まで遡って調べる |
インストールの仕方やディストリビューションによって、一部なかったりするかもしれない。
ntpd の起動オプションには、主に、以下のものがある。この他は滅多に使う必要がないか、主設定ファイルで指定すれば良い。
| -a | 認証機構を有効にする (デフォルト)。主設定ファイルで指定すれば良い |
| -A | 認証機構を無効にする。やめておいたほうがいい (理由は後述) |
| 主設定ファイルの場所を指定 | |
| -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 | ntpd を user 権限で動かす (当然 ntp ユーザはあらかじめ作成してないと駄目)。このオプションは古いオフィシャルドキュメントにはなかったが、少なくとも RedHat 7.x 以降と Fedora 付属の ntpd には存在する。また、或るバージョンの ntpd では大文字の -U だったり、`-u ntp:ntp' という具合に UID と GID が指定できたりと仕様がバラバラなので、使う前に一度 man で確認した方がいい |
| -i /dir | ntpd が自らを /dir へ chroot する。詳しくは「ntpdをchrootする」を参照 |
| -I iface | [4.2.4のみ] リッスンするインターフェイスを限定する。`-I eth0 -I lo' のように複数回使用可能。4.2.2 には、逆にリッスンしない IP を指定する -L というオプションがあるようだが、仕様が無計画にコロコロ変わってあんまりアホらしいので無視 |
多くの動作オプションは主設定ファイル内で設定できるので、起動時にオプションとして渡すとすれば "-u ntp" と、どうしてもというならデバグオプションくらい。一般的には、起動スクリプトで指定するのだろうが、RedHat 系では /etc/sysconfig/ntpd ファイルで OPTIONS 変数に書いておくと rcスクリプトがこのファイルをインクルードして、中の変数を読み取ってくれる。ただし -x オプションだけは、 ntpd に直接渡す時とはちょっと異なり、sysconfig/ntpd ファイルから渡すと step-tickers 動作を行う。
メインの設定ファイルは、どこの公開 NTP サーバに時間を合わせるかはもちろん、どの範囲のクライアントにこのサーバの参照を許すかなど、セキュリティ面でも非常に重要な規定を行う。ntpd は、時間を合わせられる こともできる。たかが時間合わせと侮るなかれ、大幅にクロックを狂わせれば、サーバ上のサービスをダウンさせるのも簡単だ。さらに、ntpdc という「両刃の剣」とも言える付属ユーティリティを使えば、 ntpd の設定をリモートで随時変更することも可能なのだ。設定例は下記、それから要点を説明する。ここで述べるのはディレクティブの一部に過ぎないが、通常はこれだけで事足りる。
tinker step 2 stepout 300 panic 1800 restrict default ignore restrict 127.0.0.1 restrict 192.168.0.1 restrict 210.173.160.57 noquery nomodify notrap restrict 202.224.32.4 noquery nomodify notrap restrict 192.168.0.0 mask 255.255.255.0 noquery nomodify driftfile /var/lib/ntp/drift # ntp2.jst.mfeed.ad.jp server 210.173.160.57 maxpoll 11 # ntp.asahi-net.or.jp server 202.224.32.4 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 サーバには、このように自分で構築するサーバも含めて、stratum (ストレータム=階級) というものが必ずある。stratum の数字が小さいほど、その NTP サーバは階級が高い。stratum 1 のサーバは、我々が時間合わせに使ってはいけない。そうした上位階級 NTP サーバは、それ自身で電波時計や原子時計などの基準デバイスを備え、次の階級のサーバから時間合わせのために参照される。下々の有象無象がいちいち参照したら、starum 1 サーバに無用な負荷をかけてしまう。よって、我々が通常使うのは stratum 2 の NTP サーバだ。公開されているサーバは、ネットの検索エンジンで「NTP サーバ 公開」などとして検索すれば出てくるだろう。自分の加入しているプロバイダが NTP サーバを公開しているのならば、上記の例に見られるように、それを使うのも手。NTP サーバとそのサブネットを構築する上で要となる、その他の鉄則を以下に挙げておく:
server コマンドは、参照する NTP サーバの指定に使う。NTPv4 プロトコルでやりとりされるデータは、世界標準時における 1900 年 1 月 1 日 00:00 からの経過時間 (秒) なので、NTP サーバが日本にあろうがアメリカにあろうが基本的には関係ない。ただし、パケットを要求してからこちらに届くまでのタイムラグは、正確な時間補正に影響を与えるので、経路コストの低いサーバを参照したほうが良いとされている。ただ、ntpd は、stratum はもちろん、参照するクロックのジッター (時間の刻みの微妙な揺らぎ) や、到達に要するタイムラグなど、様々な要素を総合評価しているので、複数のサーバを指定した場合 (普通はそうする) には、メインとして参照するサーバが逐次選択しなおされる。そうした評価をこちらの意向や都合で変えるのが、例に見られる prefer というキーワード。「なるべくならこれをつかってよ」という意味だ。サーバ指定時には、DNS名よりも、ずばりの IPアドレスで指定するほうが、DNS 名前解決によるタイムラグがない分、良いとされている。
サーバに対して時間確認を行う頻度のことを、ポールインターバル (poll interval) と呼ぶ。ポールインターバルは、ntpd では動的に変化していく。これは、最小 (minpoll) と最大 (maxpoll) で規定され、デフォルトでは、ローカルの時計が安定しないうちは 64 秒毎、それから次第に、128 秒、256 秒と間隔が長くなり、最終的には最大ポールインターバルである 1024 秒 (デフォルトの場合) に落ち着く。これらふたつの値は server コマンドのオプションとして "minpoll num " または "maxpoll num " あるいはその両方を指定して、変更することもできる。間違えやすいのは、この num が文字通りの秒数ではないという点だ。num は指数で、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] とも呼ばれる) だ。自分のハードウェアクロックを追加登録しているのは、万が一、他の参照サーバが全部無応答だった場合の「押さえ」。 fudge コマンドは本来、ハードウェア的な基準時計から時刻を読み込む際に使うコマンドだが、筆者は別途電波時計などのデバイスを接続した経験はない。興味のある人は Reference Clock Options を読んでみるといいだろう。
server コマンドでローカルクロックを指定しないほうがいい、とするドキュメントも多く見られる。Linux はどうやら、他の参照クロックをすぐに切り捨ててローカルクロックを優先同期先に選んでしまう傾向があるからだ。筆者も最近では `server 127.0.0.1' を書かないようにしている。
なお、server に似たコマンドに peer というものがある。筆者は使う機会がまだないが、server が一方的に「自分のローカルクロックを相手に合わせる」参照の仕方であるのに対し、peer は相手と自分で互いにローカルクロックを合わせ合う シンメトリック-アクティブモード での相互参照を行う。
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' の指定だ。
keys から始まり、コメントアウトした行を含む4行は、認証の設定だ。ntpd の認証機構は、いくつかの使われ方をする。どのサーバを参照サーバとして信用するか、この NTP サーバのコントロールを誰にどのような認証方式とパスワードで許可するかなどだ。そもそも、ローカルな NTP サーバで、参照させる際に認証を求めたり、参照する上位サーバを見るときに信用性をいちいち検討することはまずないだろうし、それには認証に使うキーを上位サーバからもらわなければならず、現実的に不可能だ。
ntpd は、認証機構そのものを "disable auth" (あるいは "authenticate no" でも可 ?) で無効化することもできる。しかし、参照に認証を使わないからといって認証機構を切ってしまうのは、大きなリスクとなる。オフィシャルドキュメントが不親切なのでいろいろと実験してみたが、"disable auth" した場合、クライアントとしてこのサーバを参照することを許している LAN 内のマシンから、 ntpdc ユーティリティでほぼ自由に設定をいじれてしまうのだ。 ntpdc コマンドは、サーバの設定を変更するようなコマンドをそのセッションで初めて発行した際に、必ずプライベートキーID とパスワードを求めてくる。しかし、認証機構を根こそぎ無効にしてあると、プロンプトは「儀礼的」に出すものの、 restrict コマンドで nomodify (後述) が指定してあっても、見当外れの ID とパスワードを入力しても設定が変更できてしまった。よって、時間の問い合わせに認証を使うつもりがなくても、後述するプライベートキーは作成し、この部分でキーファイルを指定 (keys ディレクティブ) するべきだ。そこまでやっておけば restrict nomodify の設定も間違いなく機能してくれる。
コメントアウトしてある 3 行だが、これらは ntpdc ユーティリティや ntpq を使って設定を変更したい場合の記述。まず、プライベートキーを使うためには、後述の keys ファイルに記述した 16 個のキーのうち、どれを「有効なもの」と認めるかを "trustedkey num num ..." で指定する必要がある。それから、有効と認めたキーのうちからどれかを、ntpdc ユーティリティ用は requestkey コマンドで、ntpq ユーティリティ用は controlkey コマンドで指定しておく。このふたつの記述がない場合、ntpd は 「ntpq と ntpdc による設定変更は一切させない」と解釈する。つまり、コンソールマシンから入力されたキーIDとパスワードは常に間違いであるという扱いになる。
説明が前後するが、例の keys の前にある "crypto pw secret" のことを付け加えておかなくてはならない。これは、ホストキーなどを暗号化する機能に関するもので、ntp-4.2.2 (?) から追加された。このディレクティブは ntp-keygen でキーを暗号化して作成してある時、その読み取りパスワードを ntpd に教えてやる。ただし、セキュリティ上、この文言はパーミションビットを絞り込んだ別ファイルに書いておき、 includefile 命令句 (例でコメントアウトしてあるところ) で読み込ませるのが普通だ。
restrict コマンドは、アクセスの restriction (制限) を規定するコマンド。書式は:
restrict {host|default} [mask netmask] [parameter] [parameter] ...
平たく言えば、「パケットの送信元が host にマッチしたら parameter を適用せよ」という構文だ。host は、アドレスでも、DNS や /etc/hosts での名前でも良い。例に挙げたアクセス制限セクションの1行目は、以降のマッチに当てはまらないアドレスだった場合の規定動作を default という特別なアドレスを使って指定している。主なパラメータには以下のものがある。
| ignore | すべての NTP パケットに答えない |
| noquery | サーバの設定変更や状態の確認/変更に使用される NTP モード 6 (ntpq で使用) および 7 (ntpdc で使用) のパケットは受け付けない。時間の問い合わせには影響なし。なお、これらのパケットも UDP の 123 番ポートを使用する点に変わりはない |
| 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 | discard コマンドで指定した閾値を超えた頻度の問い合わせに対して、参照サービスの提供を拒絶する。モード 6/7 つまり ntpq 及び ntpdc のパケットはこの規制の対象とならない。discard コマンドは検証したことがないのでオフィシャルドキュメントを参照されたし |
| limited (旧) |
ntpd は、ひとつのネットワークセグメントから同時に問い合わせできるクライアントの数を制限することができ、この制限パラメータを付けた host から問い合わせがあると、そのクライアントは接続数にカウントされる。「同時に」とはいっても、1度問い合わせがあるとそのクライアントは一定時間「アクティブ」なものとして記録に蓄積されるので、すぐに勘定からはずされるわけではない。蓄積時間は、別途 clientperiod コマンドで指定もでき (デフォルトは 3600 秒)、クライアントの「同時」接続台数は clientlimit コマンドで指定できる (デフォルトは 3 台)。その後、 clientperiod と clientlimit コマンドは廃止された? |
| kod | "Kiss of Death" の頭文字。通常、discard コマンドによって問い合わせ頻度閾値が設定してあると、それを犯した問い合わせパケットを破棄するだけだが、その上で kod の指定してあるクライアントには、キス・オブ・デス パケットが送られる。KoD は NTPプロトコルのパケットフォーマットのひとつで、クライアントに対して「もう問い合わせをやめてくれ」という意向を伝えるもの。KoD を受け取った NTPクライアントは、「断られた」ことを示すビットを立て、そのサーバへはもう問い合わせをしなくなる決まりになっている。KoD パケットの送信自体、最大 1パケット/秒 に制限されており、それ以上の頻度で送られてきた失礼な問い合わせパケットはただ単に破棄される。この仕組みによってビットの立ってしまったクライアントと当該サーバとの通信を再び可能にするには、クライアントとサーバ両方の ntpd を再起動しなければならないらしい。discard コマンドは検証したことがないのでオフィシャルドキュメントを参照されたし |
| noserve | ntpq 及び ntpdc のパケットだけを受け入れ、時間参照サービスは提供しない。つまり noquery の逆 |
"restrict host " だけが指定してあってパラメータのないエントリは「制限なし」の意味となる。パラメータは常に、規制を強化する方向に働き、ひとつの restrict に複数のパラメータを指定すると、いずれかのパラメータが他のパラメータの効果を打ち消すことはなく、いわば制限ビットの上乗せ上乗せになっていくようだ。ただし、古いバージョンのドキュメントでは複数時の動作が曖昧だったので、まだ NTP 4.0.x や 4.1.x を使っているサーバでは、複数指定は避けたほうがいいと思う。ただし、例えば limited か notrust と、noquery か nomodify とを組み合わせるなど、役割系統の異なるパラメータ同士なら構わないかもしれない。
例の中の restrict セクション 4行目と 5行目は、参照に使う外部の公開 NTP サーバを、参照だけに使い、こちらの設定を変えようとしたり無用な状態問い合わせを行おうとする要求を受け付けないように、 NTP パケットのモード 6 と 7 を「受けず答えず変更も拒絶する」という設定 (noquery nomodify notrap)。そして最後の行は、サーバの置いてある LAN 内からの時間問い合わせに答えられるよう、mask キーワードを使用して 192.168.0.0/24、つまり 192.168.0.0 - 192.168.0.255 のアドレス範囲に少し緩めの規制を施している (notrap を追加しても参照が成り立たないわけではない)。
restrict コマンド行がこのように複数ある場合の ntpd の評価順序は、やや不気味だ。ntp.conf ファイルに書いてある順番ではない。ntpd は、まず、host のアドレスがより限定的具体的なものほど優先するカタチでソートを行い、その順番で評価していくのだ。例で言えば、127.0.0.1, 192.168.0.1, 202.224.32.4 などは、マスクは暗黙に 255.255.255.255 なので同順で、最も限定的具体的なアドレスといえる。次が 192.168.0.0/255.255.255.0 。そして、数字に直すと 0.0.0.0/0.0.0.0 である default が、評価順位では最低になる。そうして最初にヒットした行が適用される。
なお、不正なパケットを、こうしたアプリケーションレベルに達する以前に水際でせき止めるために、ファイヤーウォールを設定するべきだ。外部から送られたパケットは送信元を詐称しているかもしれない。ファイヤーウォール専用のマシンを立てるに越したことはないが、サーバ自体の中にパケットフィルタを構築するだけでもかなりのセキュリティアップになる。