ntp と OSX における ntpd

会社の勉強会で発表した内容をそのまま転載 ところどころ足りない部分があるのはご愛嬌

Network Time Protocol についての簡単なまとめ、ntp の実装である ntpd が OSX においてどのように起動され、動いているのかを見ていく。


目次

  • RTC
  • NTP
    • stratum
    • 誤差の測定方法
    • ドリフト
    • 2036年問題
  • OSX の ntpd をみてみる
    • /usr/libexec/ntpd-wrapper
    • /usr/sbin/ntpd
    • ntp.conf
      • restrict
      • server
      • peer
  • OSX の ntpd を GUI から操作する
  • 国内の ntp サーバー

RTC

Real Time Clock

コンピューターに内蔵されている時計。 一般的に、主電源とは別の電力源に接続されていて、コンピューターの電源を落としても駆動し続ける。

NTP

Network Time Protocol

RTC のズレを修正するためのプロトコルUDP の 123番で動作する。

stratum

正確な時刻を持っているのはGPS原子時計。 ntpサーバーは、これらに対し階層的に接続し、時刻を同期している。

その階層構造を stratum と呼んでる。

時刻源を stratum0 とし、 時刻源からの距離により stratum([1-9]|1[0-6]) が割り当てられる。 16階層が、最下層になってる。

stratum1 のサーバーは、GPS原子時計に、stratum2 以下のサーバーは stratum1 のサーバーと時刻を同期する。

階層が深くなるごとに、サーバーへの接続回数が増えるため誤差が増えるが、一般的にはレイテンシによる誤差の方が大きい。

誤差の計測方法

ここで言っている"誤差"とは、レイテンシのこと。 そのため、ntpでは誤差を計測するために、以下のな計算を行う。

δ = {(4) - (1)} - {(3) - (2)} 

(4) - (1) = クライアントが要求を送信してから帰ってくるまでの時間
(3) - (2) = ntpサーバー内での処理にかかる時間

|------------|                | --------- |
|           (1) -----------> (2)          |
| クライアント |                | ntpサーバー |
|           (4) <----------- (3)          |
|------------|                | --------- |

ドリフト

(調べる)

2036年問題

ntp の時刻の基準点は、1991-01-01 00:00:00

32ビットの unsigned int で時刻を扱っているため、42億9496万7295秒までしか測定できない。

RFCによると、ntp の timestamp format は 64ビット数値型で、始めの32ビットで整数部分を、終わりの32ビットで小数部分を表す。

そのため、 2036-02-07 06:28:15 の次の秒で桁あふれしてしまう。 これに対処するため、ntp では、最上位ビットが0の場合、2036年 ~ 2104年であることにしている。 0番目のビットが初めてたつのが、1968年。以後の68年間0番目のビットは1のままになっている。

時計の基準点や往復時間を計算するために、NTPで使われている方式が、クライアントがローンチされる前の34年に及ぶクライアントのサーバー時間を必要としている。UNIX時間が1970年を起点としていて、すでに34年以上経過しているので、(このRFCは2006年に策定された)この起点をなるべく近い位置で含むのが、ファームフェアやCPUチップに対して良い選択になる。

The arithmetic calculation used by NTP to determine the clock offset and roundtrip delay require the client time to be within 34 years of the server time before the client is launched. As the time since the Unix base 1970 is now more than 34 years, means must be available to initialize the clock at a date closer to the present, either with a time-of-year (TOY) chip or from firmware.

うまく訳せない


OSX の ntpd をみてみる

OSX の ntpd の設定をさらってみる

/usr/libexec/ntpd-wrapper

PC の電源を落とし、プロセスを一度全て終了させる。 その後、電源を入れ、ntp プロセスを見てみる。

-% ps aux | grep ntp
root              378   0.0  0.0  2444636    964   ??  Ss   10:14PM   0:00.00 /bin/sh /usr/libexec/ntpd-wrapper

お、/usr/libexec/ntpd-wrapper というシェルスクリプトが呼ばれているみたい。 中身を見てみる。

-% cat /usr/libexec/ntpd-wrapper
#!/bin/sh

PATH=/usr/sbin:/usr/bin:/bin
TIMEOUT=30
KEY=State:/Network/Global/DNS
DNS=/var/run/resolv.conf
# sentinel to special case DNS readiness at boot
LOG=/var/run/sntp.log

ipconfig waitall

if [[ ! -f ${LOG} ]]; then
    DEADLINE=$((SECONDS+TIMEOUT))
    for (( CURTIMEOUT=TIMEOUT; SECONDS < DEADLINE; CURTIMEOUT=DEADLINE-SECONDS )); do
        if scutil -w ${KEY} -t ${CURTIMEOUT}; then
            if [[ -f ${DNS} ]]; then
                        break;
            fi                  # else retry false alarms
        else
            logger -p daemon.err "$0: scutil key ${KEY} not present after ${TIMEOUT} seconds"
            break;
        fi
    done
fi

for server in $(awk '/^server/ {print $2}' /etc/ntp.conf); do
    if sntp -K /dev/null -s ${server} &> ${LOG}; then
        break
    else
        logger -p daemon.err -f ${LOG}
    fi
done

exec /usr/sbin/ntpd -c /private/etc/ntp-restrict.conf -n -g -p /var/run/ntpd.pid -f /var/db/ntp.drift

ちょっと見たことないコマンドが色々並んでて怖いが、最後に ntpd を実行していることははっきりわかる。

/usr/sbin/ntpd

少し時間が経った後に、もう一度プロセスを表示。

-% ps aux | grep ntp
root              184   0.0  0.0  2471152   1072   ??  Ss   10:26PM   0:00.07 /usr/sbin/ntpd -c /private/etc/ntp-restrict.conf -n -g -p /var/run/ntpd.pid -f /var/db/ntp.drift

今度は、ntpd が実行されていることがわかる。

コマンドのオプションを簡単に解説する

option effect
-c ntpd が参照する config ファイルを指定する
-n --nofork らしい。よくわからない。調べる
-g ntpd は普通、決められた threshold (デフォルト 1000s)を超えて時間がずれた時、プロセスが終了する。だが、このオプションを指定することで、1度だけどんな大きな時間のズレをも修正してくれる。2度目以降に起こると、普段通りプロセスが強制終了される
-p プロセスidを指定しているファイルを読み込む
-f ドリフトの精度を指定しているファイルを読み込む

という感じ。

ntp.conf

/private/etc/ntp-restrict.conf を見れば良さそう。

restrict

-% cat /private/etc/ntp-restrict.conf
# Access restrictions documented in ntp.conf(5) and
# http://support.ntp.org/bin/view/Support/AccessRestrictions
# Limit network machines to time queries only

restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

# localhost is unrestricted
restrict 127.0.0.1
restrict -6 ::1

includefile /private/etc/ntp.conf
includefile /private/etc/ntp_opendirectory.conf

restrict 文と includefile 文がある。 includefile はただファイルを読み込んでいるだけのようなので、restrictについて解説をする。

ファイルの始めにかいてあるように、restrict はアクセスコントロールを記述する文だと思われる。

AccessRestrictions ここには、設定の指針が描いてある。

Access Control Commands and Options ここに、詳細な説明が載っていたので、OSXのデフォルト設定を解読してみる。

restrict [-6] default kod nomodify notrap nopeer noquery

クエリって単語の意味が曖昧。調べる

option meaning
-6 ipv6 を使うかどうか
default address 0.0.0.0, mask 0.0.0.0 for IPv4 and address :: mask :: for IPv6
kod サーバーのリミットを超えるパケットが来た際、kiss-of-death というパケットを送信する。 limited オプションを含まない restrict の場合、KoD パケットは送信されない
nomodify ntpd の状態を変更するようなクエリは受け付けない
notrap mode 6調べる により提供されるメッセージコントロールを拒否する
nopeer ntp サーバー間の同期を取らないようにする
noquery クエリを受け付けない

ということでまず最初に、外部全てからのクエリを拒否するが、時間取得だけは許す、というような設定を当てている様子。

restrict (127.0.0.1|-6 ::1)

restrict をオプション無しで設定する場合、許可を表す。 なので、ローカルホストからの変更のみを許可する設定を当てている。

server

/private/etc/ntp-restrict.conf で、読み込まれているファイルが二つある。 一つ目の /private/etc/ntp.conf を見てみる

-% cat /private/etc/ntp.conf
server time.apple.com

お、ついにわかりやすそうなやつを見つけた! 多分これが、apple が提供している ntp サーバーだろう。 mac はデフォルトで apple の ntp サーバーを見に行っているようだ。

server 文は、ntp サーバーを一方的に参照することを表す。 そのためここで、time.apple.com を参照していることがわかる。

peer

もう一つの読み込まれているファイルをみる。

-% cat /private/etc/ntp_opendirectory.conf
# opendirectory peers

opendirectory peers とある。 peer(ピア)とは、ntp サーバーを同じ stratum の階層内で同期させることを言う。 そのため、OSX を ntp サーバーとして使わない場合は、設定する必要はない。

OSX の ntpd を GUI から操作する

今度追記 デモやる

国内のntpサーバー