【NTP入門 第3回】NTPの仕組み ― stratum、4つのタイムスタンプ、offsetとdelay、時刻源の選び方、slewとstep、pool

NTP サーバー
スポンサーリンク
スポンサーリンク

「NTPサーバーは冗長化のために2台参照しています。これで安心ですよね?」
「時刻が5分ずれていたので、手で合わせました」

どちらも、よくある運用です。でも実は、2台では誤った時刻を見分けられず、稼働中に時刻を一気に戻すとサービスが誤動作するおそれがあります。

第2回では、NTPが配る時刻(UTC)を見ました。第3回では、NTPがネットワーク越しにどうやって時刻のずれを測り、どう直すのかを扱います。ここが分かると、第4回以降の設定の意味がすぐ分かります。


NTPとは

NTP(Network Time Protocol)は、ネットワーク越しに時刻を合わせるプロトコルで、UDP 123番を使います。1985年のRFC 958に始まり、今は2010年のNTPv4(RFC 5905)が基準です。

NTPはUDP 123で時刻はUTCとし、①基準時計からstratum 1、2、3と階層で配る、②クライアントとサーバーの間のT1〜T4で往復時間を差し引く、③A+2ms・B+3ms・C+2ms・D+900msのうち多数派を選び時計を少しずつ合わせる、の3つがそろって時刻がそろうことを示す図

要点は3つあります。

  1. 正確な時刻源から階層(stratum)をたどって時刻を配る
  2. 4つのタイムスタンプで往復の通信時間を測って差し引き、ずれを計算する
  3. 複数のサーバーの答えを比べて外れ値を除き、時計を急に動かさず少しずつ直す
  • やり取りする時刻は常にUTCで、タイムゾーンや夏時間の情報は含まず、うるう秒は予告(LI)だけを伝える
  • 精度の目安は、インターネット越しで数十ms以内、LAN内で1ms未満
  • 統計処理を省いた簡易版のSNTPもあり、systemd-timesyncdや多くの機器が使う。実装はntpd、chrony、Windows Timeなど

stratumの階層

NTPの時刻は、正確な時刻源から木のような階層(stratum)をたどって配られます。

GNSS受信機や原子時計のstratum 0からstratum 1、社内NTPのstratum 2、PC・サーバー・ルーターのstratum 3へ時刻が配られ、上位を失ったサーバーはstratum 16(非同期)を名乗り、下位はそこから受け取れないことを示す図
  • GNSS受信機や原子時計などの基準時計を、慣例でstratum 0と呼ぶ。それに直結したNTPサーバーがstratum 1。そこから時刻をもらうサーバーは2、その下は3と、段ごとに1つ増える
  • 同期できるのはstratum 15までで、16は「同期していない」ことを示す値。16からは時刻を受け取れない。上位を失ったサーバーは16を名乗るので、16は同期できていない合図
  • stratumは段数で、精度の順位ではない。LAN内のstratum 2が、遠くのstratum 1より正確なこともある
  • パケットのstratum 0は「不明・無効」で、アクセス制限などを伝えるKiss-o’-Deathに使う

4つのタイムスタンプ

NTPの核心は、4つのタイムスタンプで「時計のずれ」と「通信にかかった時間」を分けて求めることです。

クライアントが要求を送った時刻T1と応答を受けた時刻T4、サーバーが要求を受けた時刻T2と応答を送った時刻T3を記録し、T4−T1が往復全体、T3−T2がサーバー内の時間で、delay=(T4−T1)−(T3−T2)、offset=((T2−T1)+(T3−T4))÷2で求め、パケットではT1をOrigin、T2をReceive、T3をTransmitと呼びT4は載らないことを示す図
  • クライアントは要求を送るときに、自分の時計の時刻T1を記録する
  • サーバーは要求を受けた時刻T2と、応答を送る時刻T3を自分の時計で記録し、応答に入れて返す
  • クライアントは応答を受けた時刻T4を記録する

(T4−T1)は往復全体、(T3−T2)はサーバー内で待った時間なので、その差が純粋な往復の通信時間(delay)です。行きと帰りの時間が等しいと仮定すると、時計のずれ(offset)は、行きの差(T2−T1)と帰りの差(T3−T4)の平均で求まります。

delayは同じ時計どうしの差なので、時計のずれに左右されないのがポイントです。


offsetとdelayの計算

具体的な数字で計算してみましょう。

記号意味記録する時計例(10:00:00 以降の秒)
T1クライアントが要求を送った時刻クライアント0.050
T2サーバーが要求を受けた時刻サーバー0.110
T3サーバーが応答を送った時刻サーバー0.111
T4クライアントが応答を受けた時刻クライアント0.071
offset = ((T2 − T1) + (T3 − T4)) / 2
       = ((0.110 − 0.050) + (0.111 − 0.071)) / 2
       = (0.060 + 0.040) / 2 = +0.050 秒   … 50ms遅れ
delay  = (T4 − T1) − (T3 − T2)
       = (0.071 − 0.050) − (0.111 − 0.110)
       = 0.021 − 0.001 = 0.020 秒          … 往復の通信時間は20ms
クライアントの時計が実際より50ms遅れ、片道10msのときT1=.050、T2=.110、T3=.111、T4=.071となることと、行き15ms・帰り5msに偏るとoffsetが55msと計算されて5msの誤差が出ることを示す図
  • 例は、クライアントの時計が50ms遅れ、片道10ms、サーバーの処理1msの場合。offsetが正なら、クライアントの時計を進める
  • 計算は行きと帰りが同じ時間だと仮定している。行き15ms・帰り5msのように偏ると、offsetは55msと計算され、5ms(偏りの半分)の誤差が出る
  • 片道の偏りは測れないが、誤差は最大でもdelayの半分に収まる。だからdelayの小さいサーバーほど信頼できる

root delayとroot dispersion

offsetとdelayは、直接やり取りしたサーバーとの間の値です。そのサーバーも上位の遅延や誤差を引き継ぐため、NTPは基準時計までの累積値をパケットで下へ伝えます。

stratum 1、stratum 2、クライアントと段を下るごとに、上位から引き継いだdelayとdispersionに自分の区間の分が加わって棒が長くなり、root distance=root delay÷2+root dispersionが最悪のずれの上限になることと、jitterはroot dispersionとは別の値であることを示す図
  • root delay:基準時計までの往復遅延の合計
  • root dispersion:累積した誤差の最大見積もり。測定の誤差に、次の測定までに時計がずれうる量(RFC 5905は15ppmを想定)を足していく値で、段を下るごとに増える。測定値のばらつきはjitterという別の統計
  • クライアントは、root delayの半分とroot dispersionの和(root distance)を最悪のずれの上限とみなし、大きすぎるサーバーは使わない(上限はRFC 5905で1秒、chronyの既定で3秒)

下の段ほど、受け取る時刻の確からしさは下がります。


時刻源の選び方

クライアントは複数のサーバーに問い合わせ、次の手順で使う時刻を決めます。

各サーバーのoffset±root distanceの区間を並べ、A・B・Cが重なる範囲をtruechimer、外れたDをfalsetickerとして除外することと、クロックフィルター、選択(intersection)、クラスタリング、結合(combine)の順に1つのoffsetを決めることを示す図
  1. クロックフィルター:サーバーごとに、直近8回の測定からdelayが最小の(混雑の影響が少ない)ものを選ぶ
  2. 選択(intersection)アルゴリズム:各サーバーのoffsetを「offset ± root distance」の区間として並べ、過半数の区間が重なる範囲を探す。範囲に入るサーバーがtruechimer、外れるサーバーがfalsetickerで、後者は除かれる
  3. クラスタリング:ばらつきの大きいものを減らす
  4. 結合(combine):重み付けして1つのoffsetを決める

つまり多数決で時刻を決めるので、過半数が正しい限り、壊れた時計や偽のサーバーを除けます。chronyも考え方は同じです(第4回)。


何台の時刻源を使うか

冒頭の「2台参照しているから安心」は、ここで崩れます。

台数1台がおかしくなったとき評価
1台誤りがそのまま伝わる。止まれば同期できない避ける
2台食い違っても、どちらが正しいか決められない。1台止まると1台と同じ1台と大差ない
3台1台の誤りは多数決で除ける。1台止まると2台と同じ状態最低限
4台以上1台が止まっても、残る3台で1台の誤りを除ける推奨(RFC 8633)
1台では誤りがそのまま伝わり、2台ではどちらが正しいか決められず、3台なら誤りを除け、4台なら1台が停止しても誤りを除けることを示す図
  • RFC 8633(BCP 223)は、正確な時刻を保ちたいなら「独立した多様な時刻源を少なくとも4つ」使うべき(SHOULD)としている
  • 前提は、過半数が正しいこと。多数決があるから、正しくない時刻源が混じっても同期を続けられる
  • 同じ上位を参照する4台は、独立ではない(第7回)

ポイント
多数決は3台から成り立ち、4台で1台の停止にも耐える。2台は冗長のつもりで、実は1台と大差ない。


時刻の直し方:slewとstep

ずれを見つけた後の直し方は2通りあります。

slewは進む速さを変えて徐々に0へ近づけ、ntpd(500ppm)なら1秒のずれに約33分、chrony既定(83,333ppm)なら約12秒かかり、stepは時刻を一気に書き換えるためその瞬間に時刻が1秒戻ることを示すグラフ
  • slew(スルー):時計の進む速さを少し変え、時間をかけて徐々に合わせる。時刻が飛んだり戻ったりしないので安全。ただし速さには上限があり、ntpd(RFC 5905の参考実装)では500ppm(1秒あたり最大0.5ms)。この速さでは1秒のずれを直すのに約2,000秒(約33分)かかる。chronyは既定で最大83,333ppm(12分の1)まで速められる
  • step(ステップ):時刻を一気に書き換える。すぐ合うが、時刻が戻るとログの順序が崩れ、タイマーやデータベースが誤動作するおそれがある

基本は、起動直後だけstep、稼働中はslewです。冒頭の「5分ずれていたので手で合わせた」は、稼働中のサービスに対するstepになるので、影響を考えてから行います(第10回)。

直し方の閾値

実装は、ずれの大きさでslew・step・異常(直さない)を切り替えます。

項目RFC 5905・ntpdchrony
slew の最大の速さ500ppm既定 83,333ppm(maxslewrate で変更)
step する条件128ms を超えるずれが stepout(900秒)続いたら(起動直後はすぐ)makestep 1 3 なら、最初の3回の更新で1秒を超えたときだけ。指定がなければ step しない
panic(異常とみなす)1000秒を超えたら終了。-g で起動時の1回だけ許す既定ではなし。maxchange で設定できる
step を抑える-x で step の閾値を600秒に広げるmakestep を書かない
手動で一度だけ合わせるntpdate(旧)、ntpd -gqchronyd -q、chronyc makestep
ntpdはずれが128msまではslew、128msを超えるずれがstepoutの900秒続けばstep、1000秒を超えるとpanicで直さないことと、chronyは最大83,333ppmのslewで、1秒を超えるときは起動後の最初の3回の更新だけstepし、panicは既定でないことを示す図

panicの1000秒は約17分です。仮想マシンのスナップショットからの復元やRTCの電池切れで大きくずれると、同期が止まったり直らなかったりします。Windows Timeにも、大きなずれを直さない閾値(MaxPosPhaseCorrectionなど)があります(第5回)。


ポーリング間隔

$ chronyc -n sources          (抜粋)
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 198.51.100.122                2   9   377   280  +5426us[+5452us] +/-  112ms
^+ 198.51.100.123                2  10   377   254  +5100us[+5100us] +/-  112ms
PS> w32tm /query /peers       (抜粋)
ピア: ntp.example.jp,0x8
状態: アクティブ
階層: 2 (二次参照 - (S)NTP で同期)
ピアポーリング間隔: 10 (1024s)
ホストポーリング間隔: 10 (1024s)
  • 問い合わせの間隔は2のべき乗の秒で表し、minpoll〜maxpollの範囲で自動で調整する。chrony・ntpdの既定は6〜10(64〜1024秒)。上の例のPoll 9は512秒、10は1024秒
  • 同期が安定すると間隔を延ばして相手の負荷を下げ、ずれや揺らぎが大きいと縮める
  • Reachは、直近8回の応答の有無を8ビットで表した値(8進数)。377なら8回すべて成功、0なら届いていない
  • 公開サーバーに対してminpollを小さくしない(NTP Poolの利用条件)。短い間隔は、LAN内の自社のサーバーに限る

動作モード

値モード使いどころ注意
3・4クライアント・サーバー下位が上位に問い合わせる。ほとんどの構成はこれ基本の形
1・2symmetric active・passive同じ階層のサーバー同士で互いに時刻を補い合う(peer)認証なしの passive は危険。chrony は passive 側の自動応答に非対応
5broadcastLAN 内にまとめて配る往復を測れず遅延を補正しにくい。なりすましに弱い。chrony は受信側に非対応
6制御メッセージntpq による状態の問い合わせ外部に開けない(第8回)
7実装独自(ntpd の ntpdc)旧来の管理用monlist が増幅攻撃に悪用された(第8回)
クライアント・サーバー(mode 3・4)はクライアントが要求しサーバーが応答し、symmetric(mode 1・2)は同じ階層のサーバーAとBが互いに補い合い、broadcast(mode 5)はサーバーが端末へ送るだけなので往復を測れないことを示す図

NTPでは、通信相手との関係をassociation(アソシエーション)と呼び、モードはその種類です。ntpdには、マルチキャストで相手を探すmanycastもあります。RFC 9769(2025年)は、送信後の正確な時刻を次のパケットで伝えるinterleavedモードを定めました。

一方通行の配り方(broadcast)では、通信時間を差し引けません。基本はクライアント・サーバーと覚えておきましょう。


NTPv4と関連するRFC

RFC(年)内容位置づけ
RFC 5905(2010)NTPv4 の本体。SNTP も含む(RFC 1305・4330 を廃止)現在の基準
RFC 7822(2016)拡張フィールドの扱いNTS の土台
RFC 8573(2019)対称鍵の認証を AES-CMAC に。MD5 は非推奨第8回
RFC 8633(2019)NTP のベストプラクティス(BCP 223)設計の指針(第7回)
RFC 8915(2020)NTS(Network Time Security)第8回
RFC 9109(2021)クライアントの送信元ポートをランダムにするなりすまし対策
RFC 9748・9769(2025)レジストリの修正、interleaved モードRFC 5905 を更新

RFC 5905は廃止されておらず、上のRFCで更新されながら使われています(2026年9月時点)。NTPv5はInternet-Draft(draft-ietf-ntp-ntpv5-09、2026年7月)の段階で、クライアント・サーバーのモードだけに絞る方針です。RFC 9523(2024年)は、時刻をずらす攻撃を見つける補助の仕組みKhronosを定めています。


NTPパケットの主な項目

項目大きさ意味ntp.nict.jp の応答の例
LI・VN・Mode2・3・3ビットうるう秒の予告、版、モード0・4・4(予告なし、v4、サーバー)
Stratum8ビット階層。0 は Kiss-o’-Death、16 は非同期1
Poll・Precision各8ビット問い合わせ間隔、時計の精度(2のべき乗の秒)Precision −20(約1μs)
Root Delay・Root Dispersion各32ビット基準時計までの往復遅延、累積誤差の見積もり0・0(基準時計に直結)
Reference ID32ビットstratum 1 は時刻源の名前、2以上は上位の IPv4 アドレス(IPv6 はハッシュ)NICT
Reference Timestamp64ビット最後に時計を合わせた時刻—
Origin・Receive・Transmit各64ビットT1・T2・T3T2−T1 ≒ 2.7ms、T3−T2 ≒ 0.001ms
NTPパケットのヘッダーは、LI・VN・Mode・Stratum・Poll・Precision、Root Delay、Root Dispersion、Reference ID、Reference Timestamp、Origin Timestamp=T1、Receive Timestamp=T2、Transmit Timestamp=T3の計48バイトで、後ろに拡張フィールドやMACを付けられ、半分はT1〜T3の3つのタイムスタンプであることを示す図
  • ヘッダーは48バイトで、後ろに拡張フィールド(NTSなど)やMACを付けられる。T4はパケットに入らず、受信時に記録する
  • 例は、2026年9月26日にntp.nict.jpへ問い合わせた値(offset −0.7ms、delay 6.9ms)
  • 中身はchronyc ntpdata(root)やw32tm /query /status /verboseで見られる

poolとiburst

サーバーの書き方は2つあります。

pool jp.pool.ntp.org iburstと書いたchronydが、DNSでjp.pool.ntp.orgのアドレスを引いて複数台を使い、応答しないアドレスを別のアドレスに入れ替えることと、iburstは通常64秒おきで同期まで数分かかるところを、起動直後だけ約2秒おきに8回送って数秒で同期することを示す図
  • serverは決まった1台を指定し、poolはDNS名から得た複数のアドレスのうち複数台(chronyの既定は最大4台)を使い、応答しなくなったサーバーを別のアドレスに入れ替える
  • NTP Pool Projectは、0〜3の番号付きの名前と、jp.pool.ntp.orgのような国別の名前を提供し、返すアドレスは1時間ごとに変わる(IPv6は2の付く名前だけ)。ただし運営はボランティアに支えられており、業務に重要な時刻を直接インターネットから取ることは勧められていない(第7回)
  • iburstは、起動直後や到達できなかったサーバーに、通常の1回の代わりに4〜8回を約2秒間隔で送る指定で、最初の同期を数分から数秒に縮める。常に続けて送るburstと違い、相手の負荷が増えるのは起動時だけ

考えてみよう

  1. T1=10:00:00.000、T2=10:00:00.130、T3=10:00:00.131、T4=10:00:00.041のとき、offsetとdelayはいくつですか。クライアントの時計は進んでいますか、遅れていますか。
  2. 社内のサーバーが参照しているNTPサーバーは何台ですか。2台なら、1台が誤った時刻を返したとき何が起きるでしょうか。
  3. 稼働中のデータベースサーバーの時計が5分ずれていました。slewで直すと、500ppmでは何日、83,333ppmでは何分かかりますか。stepで直すなら、何に気をつけますか。

ヒント:この記事のoffsetとdelayの式、台数の表、slewの速さ(500ppm=1秒あたり0.5ms)が手がかりです。1問目の答えはoffset+110ms、delay 40msです。


まとめ

  • NTPはUDP 123でUTCを配る。階層で配り、往復時間を引き、多数決で選んでゆっくり直す
  • stratumは段数。16は「非同期」で、そこからは受け取れない
  • offset=((T2−T1)+(T3−T4))÷2、delay=(T4−T1)−(T3−T2)。誤差は最大でもdelayの半分
  • 時刻源は多数決で選ぶ。2台では決められず、4台以上が推奨
  • 直し方はslew(徐々に)とstep(一気に)。起動直後だけstep、稼働中はslew
  • poolは複数台を入れ替え、iburstは起動時の同期を速める

次回は、Linuxのchronyの設定と、chronyc tracking・sourcesの読み方、仮想マシンの時刻を扱います。


連載「NTP入門」全11回

  1. なぜ時刻同期が必要か
  2. 時刻の基礎知識
  3. NTPの仕組み(この記事)
  4. Linuxの時刻同期(chrony)
  5. Windowsの時刻同期
  6. ネットワーク機器・仮想基盤
  7. 設計と推奨構成
  8. NTPのセキュリティ
  9. PTPと高精度同期
  10. 時刻同期のトラブルシュート
  11. 時刻同期の設計演習

コメント

タイトルとURLをコピーしました