NTPサーバの奇妙な振る舞いとNTPv5の標準化

NTPv5の標準化が進められています。

そこで、実験として世の中のパブリックNTPサーバにNTPv5パケットを送信してみました。NTPv5の議論は始まったばかりですので、世の中のNTPサーバはNTPv5には対応しているはずがありません。

しかし結果は、驚くことにversionフィールドに5が指定されたNTPv4形式のパケットを返すサーバが居ることがわかりました。NTPv5とNTPv4パケットはバージョンやモードなどの領域を除き互換性がないため、そのようなパケットは破棄するしかありません。

その他にも奇妙な振る舞いをするNTPサーバもいたので、紹介していきたいと思います。

記事の後半では、そのような状況でNTPv5の仕様ではいくつかの工夫が盛り込まれていますので、それについて紹介します。

NTPv5について基本的なところは以前紹介したとおりです。
asnokaze.hatenablog.com

(なお、NTPv5については議論が始まったばっかりですので、今後大きな変更があるかもしれません)

実験

約80のパブリックなNTPサーバに対して下記の4つのパケットを送信します。

  • NTPv4として正常なパケット
  • NTPv4形式だが、バージョンフィールドに5を指定したもの
  • NTPv4として正常なパケットであり、未定義の拡張フィールドを付加したもの
  • NTPv5パケット (draft-mlichvar-ntp-ntpv5-00)

これに対して、どのようなパケットが返ってくるか観測します。

NTPv4として正常なパケット

下記の通り、もちろん正常なパケットが返ってきます (一部、NTPv3を応答しますが、大丈夫です)

  • 10%: NTPv3のパケットが返ってくる
  • 90%: NTPv4のパケットが返ってくる
NTPv4形式だが、バージョンフィールドに5を指定したもの

先述したような、バージョンフィールドに5が指定されたNTPv4パケットが返ってきます。

  • 10%: NTPv3のパケットが返ってくる
  • 70%: NTPv4形式のパケットで、バージョンフィールドに5が指定されたものが返ってくる
  • 20%: 応答なし

例えば、ntpdは将来のバージョンの扱いに不備があるようです
https://github.com/ntp-project/ntp/blob/master-no-authorname/ntpd/ntp_proto.c#L583

NTPv4として正常なパケットであり、未定義の拡張フィールドを付加したもの

NTPv4は拡張フィールドを付加できます。未定義の拡張フィールドを付加したパケットを送ったときのレスポンスを確認します。

  • 75%: NTPv4パケットが返ってくる
  • 25%: 応答なし

(TLS1.3がそうしたように、拡張フィールドでバージョンネゴシエーションをする余地があるか確認したかったのですが、いくつかのサーバはパケットをドロップしてしまいます)

なお、1件だけでしたが、未定義の拡張フィールドを送ると、同じ拡張フィールドをつけて送り返してくるようなサーバもいました。

NTPv5パケット

NTPv5はNTPv4パケットと互換がないため、多くは不正なパケットとして破棄されますが、例のパケットが返ってくることもあります

  • 10%: NTPv4形式のパケットで、バージョンフィールドに5が指定されたものが返ってくる
  • 90%: 応答なし

NTPv5での工夫

不正な振る舞いをするサーバに対して、NTPv5の仕様ではいくつかの工夫が入ってます。

いくつか紹介します。なお、詳細については仕様を参照ください

不正なパケットの識別

NTPv5パケットを送った場合に、バージョン5が指定されたNTPv4が返ってくると、実装としては破棄するしかありません。

どのように、そのような不正なパケットを識別するのでしょうか。実は、NTPv5ではランダムなCookieをリクエスト時に送り、レスポンスにその値をつけて返すような仕様になっています。この仕組みはNTPv5から入ったものですので、Cookieフィールドを見れば不正なパケットを識別できます。

サポートバージョンの示し方

ドロップされてしまうかもしれないので、いきなりNTPv5パケットを送りつけることはできません。そこでクライアントは、NTPv4パケットを送りつつ自身はNTPv5にも対応していることをサーバに伝えたいです。もし、サーバがNTPv5に対応していれば、NTPv5のパケットで応答が返ってくることを期待できます。

新しくNTPv4の拡張フィールドを定義し、それを使ってサポートバージョンを示すことが出来るでしょう。しかし、未知の拡張フィールドはドロップされうるので機能しません。

そこで、比較的自由に使えるNTPv4の”Reference Timestamp”フィールドにシグナルを埋め込みます。具体的には 0x4E5450354E545035 ("NTP5NTP5" のASCII値)を指定します。時刻として 2077年9月29日 7時41分です。クライアントは、このようなNTPv4パケットを送信することで自身がNTPv5に対応している事を示します。
f:id:ASnoKaze:20201229013638p:plain

なお、このようなパケットを送っても、パケットがドロップされたりはしなさそうです。

未知の拡張仕様の扱い

今までNTPでは未知の拡張仕様の扱いは決まっていませんでしたが、NTPv5では無視する事がMUSTとなりました。

終わりに

TCPTLS、HTTPがそうであるように、プロトコルの新しいバージョン・新しい拡張機能は現在のインターネットで正しく機能しない例が見つかっていました。

NTPの次期バージョンも同様の問題を抱えています。

この問題は硬直化(ossification)と呼ばれ、プロトコルの標準化についてまわる問題でしょう。簡単にどうこうなる話ではありませんが、この記事によって僅かでもインターネットが良くなればなと思います。