RaspberryをNTPサーバーとして設定する（chrony）

# はじめに
ラズパイをNTPサーバーにするためのメモ。ほぼデフォルト設定。
chronyとは、RHEL7からntpdに代わって導入された時刻同期サーバー/クライアント。
設定メモであって、詳しくは書かないつもり。

# インストール
パッケージインストール。
```console
# apt -y install chrony
```
バージョン確認。
```console
# chronyd --version
chronyd (chrony) version 4.0 (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
```
インストールすると勝手に起動してくる。
```console
# systemctl status chrony
● chrony.service - chrony, an NTP client/server
     Loaded: loaded (/lib/systemd/system/chrony.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2024-01-06 13:11:02 JST; 29s ago
       Docs: man:chronyd(8)
             man:chronyc(1)
             man:chrony.conf(5)
    Process: 22078 ExecStart=/usr/sbin/chronyd $DAEMON_OPTS (code=exited, status=0/SUCCESS)
   Main PID: 22094 (chronyd)
      Tasks: 2 (limit: 1596)
        CPU: 197ms
     CGroup: /system.slice/chrony.service
             ├─22094 /usr/sbin/chronyd -F 1
             └─22095 /usr/sbin/chronyd -F 1
```
自動起動設定も最初から有効になっていた。
```console
# systemctl is-enabled chrony
enabled
```

# NTP同期状況を確認
NTPクライアントとしての動作確認。
オプションをつけないとドメインのあるものはドメインで、ないものはIPアドレスで表示する。
`chronyc -n sources`とするとドメインではなくIPアドレスで表示。
```console
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^+ time.gin.ntt.net              2   6    17    14  -7702us[-7021us] +/-   80ms
^* gotoky.hojmark.net            2   6    17    14   +159us[ +839us] +/-   55ms
^+ time.cloudflare.com           3   6    17    14  +3190us[+3870us] +/-   72ms
^+ time.cloudflare.com           3   6    17    15  +1934us[+2615us] +/-   68ms
```

バックアップを取って編集。
```console
# cp -p /etc/chrony/chrony.conf /etc/chrony/chrony.conf.org
# vi /etc/chrony/chrony.conf
```
```diff:/etc/chrony/chrony.conf
# Welcome to the chrony configuration file. See chrony.conf(5) for more
# information about usable directives.

# Include configuration files found in /etc/chrony/conf.d.
confdir /etc/chrony/conf.d

# Use Debian vendor zone.
+ pool ntp.nict.jp iburst
+ pool time.cloudflare.com iburst
+ pool time.aws.com iburst
+ pool time.google.com iburst
- pool 2.debian.pool.ntp.org iburst
+ #pool 2.debian.pool.ntp.org iburst

# Use time sources from DHCP.
sourcedir /run/chrony-dhcp

# Use NTP sources found in /etc/chrony/sources.d.
sourcedir /etc/chrony/sources.d

# This directive specify the location of the file containing ID/key pairs for
# NTP authentication.
keyfile /etc/chrony/chrony.keys

# This directive specify the file into which chronyd will store the rate
# information.
driftfile /var/lib/chrony/chrony.drift

# Save NTS keys and cookies.
ntsdumpdir /var/lib/chrony

# Uncomment the following line to turn logging on.
#log tracking measurements statistics

# Log files location.
logdir /var/log/chrony

# Stop bad estimates upsetting machine clock.
maxupdateskew 100.0

# This directive enables kernel synchronisation (every 11 minutes) of the
# real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
rtcsync

# Step the system clock instead of slewing it if the adjustment is larger than
# one second, but only in the first three clock updates.
makestep 1 3

# Get TAI-UTC offset and leap seconds from the system tz database.
# This directive must be commented out when using time sources serving
# leap-smeared time.
leapsectz right/UTC

+ # Allow NTP client access from local network.
+ allow 192.168.0.0/24
```

#### pool
NTP同期先のサーバー群を設定。
群、とあるように同じドメインで複数IPアドレスが存在する場合は、そのうち1つが同期ソースとして選定される。
- ntp.nict.jp(stratum1)
日本標準時を提供する独立行政法人情報通信研究機構 (NICT) が運営をする公開NTPサーバ
- それ以外は大手企業のNTPサーバーを選択

最も信頼性の高い時刻を持つサーバーをstratum0とし、そのサーバーの時刻と同期したサーバーをstratum1。stratum1を同期したサーバーをstratum2と、同期するにつれて数字が増えていく。

以下は、同期先サーバーを複数指定した場合の優先度設定。
`pool ntp.nict.jp iburst trust`のように複数指定して設定したりする。
| 設定 | 内容 |
|:-|:-|
| iburst | 起動直後に短時間で4回問い合わせて時刻合わせする設定。4回問い合わせをすることで時刻同期の精度を上げている。<br>※とりあえずつけておけば良しなやつ |
| prefer | 他のソースよりも優先的に同期する|
| trust | このソースが最優先させる |

NTP Pool Projectをソースにするのもあり。

https://www.ntppool.org/zone/jp

#### sourcedir /run/chrony-dhcp
DHCPサーバーとの時刻同期をする設定っぽい。
無効にする場合は削除かコメントアウト。
```console
# ls /run/chrony-dhcp
ls: '/run/chrony-dhcp' にアクセスできません: そのようなファイルやディレクトリはありません
```
存在しないんだけど・・・。

#### sourcedir /etc/chrony/sources.d
`sourcedir`の設定が2つあるような。上の`sourcedir`を上書きしている？？？
```console
# ls /etc/chrony/sources.d
README
```
READMEがおいてあった。
このディレクトリに`.sources`の拡張子の設定ファイルがあると読み込んでくれるようである。
設定ファイルには`peer`、`pool`、`server`ディレクティブの設定をかけるようである。
設定例も書いてある。優しい。
```console
# cat /etc/chrony/sources.d/README 
Only NTP sources can be specified in the /etc/chrony/sources.d directory.
Files in this directory must end with the ".sources" suffix, and can only
contain the "peer", "pool" and "server" directives.

There is no need to restart chronyd for these time sources to be usable,
running 'chronyc reload sources' is sufficient.

Example:

# echo 'server 192.0.2.1 iburst' > /etc/chrony/sources.d/local-ntp-server.sources
# chronyc reload sources
```

#### keyfile /etc/chrony/chrony.keys
クライアントがNTP認証で使う鍵ファイルの指定。
`.keys`ファイルの中身は鍵の作り方の参考情報が書いてあった。
今回は使わないので、このままにする。
```console
# cat /etc/chrony/chrony.keys
# This file is solely used for NTP authentication with symmetric keys
# as defined by RFC 1305 and RFC 5905.
#
# It can contain ID/key pairs which can be generated using the “keygen” option
# from “chronyc”; for example:
# chronyc keygen 1 SHA256 256 >> /etc/chrony/chrony.keys
# would generate a 256-bit SHA-256 key using ID 1.
#
# A list of supported hash functions and output encoding is available by
# consulting the "keyfile" directive in the chrony.conf(5) man page.
```

#### driftfile /var/lib/chrony/chrony.drift
driftファイルを配置するパスをフルパス指定。
driftは、ハードウェア自身がどれくらいずれが生じるのか傾向を測り、自動補正するものだそう。
ハードの仕様で毎日0.001秒進むのであれば、毎日0.001秒戻すという補正をするような感じ。

ファイルの中身を見てみる。
数字が入っていた。この数字で補正してくれているのだろう。
```console
# cat /var/lib/chrony/chrony.drift
            0.782477             0.041395
```

#### ntsdumpdir /var/lib/chrony
NTS-KE要求が行われることを避けるために、クライアントがサーバーから受信したNTS Cookieを保存するディレクトリパスを指定。
クライアント側に、`{NTPソースのIPアドレス}.nts`拡張子のファイルが作られるらしい。
（忘れなかったら後で確認しよう）

(参考)
NTS(Network Time Security)は、NTP認証メカニズム。
クライアント側で、サーバから受信したパケットが変更されていないことを確認する。
サーバーとクライアント間で仕様される暗号鍵を自動的に作成するプロトコルが、`NTS-KE(Key Establishment)`だそう。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/assembly_overview-of-network-time-security-in-chrony_configuring-time-synchronization

#### log tracking measurements statistics
保存するログの種類を指定する。
デフォルトでコメントアウトされているので、ログ保存が有効化する場合はコメントアウトを外す。
`logdir`に指定したディレクトリ（今回は`logdir /var/log/chrony`)にログを保存する。

| ログ種別 | 内容 | 保存先ファイル |
|:-|:-|:-|
| tracking | システムクロックが進むまたは遅れる割合の予測に対する変更などを出力したログ。 | tracking.log |
| measurements | NTP測定値と関連情報のログ。 | measurements.log |
| statistics | 	回帰分析に関するログ。 | statistics.log |
| refclocks | 参照クロックの測定値に関するログ。GPSや原子時計などを利用したNTPサーバを立てた場合に出力されるらしい。つまりは設定不要そう。 | refclocks.log |

こちらのQiita記事に分かりやすくまとめてありました。

https://qiita.com/RCA3610/items/0bceddd0e46f230d8618

デフォルトで保存しない設定だったし、ラズパイ容量少ないからそのままでいいかな。

#### maxupdateskew 100.0
誤差の許容値。調整速度は`100.0`ppm(parts per million)で設定されている。
manを読むと、デフォルトは1000ppmと書かれているようだが、100.0？
とりあえずデフォルトのままにしよう。

#### rtcsync
カーネル同期の有効化。
リアルタイムクロックが11分ごとに更新される。
`rtcfile`とは一緒に設定できない。
これもそのままにしておこう。

#### makestep 1 3
何秒のずれが何回続いたらstepモードにするかを設定。
上記例だと、1秒以上のずれが、3回続いた場合にstepモードで同期する。
stepモードは、一気に修正するモード。
標準ではslewモード設定になっていて、これはゆっくり修正するモード。

#### leapsectz right/UTC
システムのTZデータベースから、うるう秒を取得。
うまいこと修正してくれるようである。

#### allow 192.168.0.0/24
許可するセグメントを設定。
この設定を入れないとNTPサーバーとして応答しない。

## 設定反映
```console
# systemctl restart chrony
```
同期状態確認。
`chronyc sources`もしくは`chronyc selectdata`で確認できる。
- ^はNTPサーバを示す。
- =はピアを示す。
- #はローカル接続を示す。
- *マークがついてるものが同期してるサーバー。(最適解と判断されたもの)
- +マークは*以外で同期対象として選ばれたサーバー。
- -マークは選ばれなかったサーバー。`chronyc selectdata`で確認する場合は、`D`と表示される。
同期候補となるNTPサーバーが変わった。
- ?マークは利用対象外。
```console
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^+ 2001:ce8:78::2                1   8   377    67   -236us[  -49us] +/- 6823us
^* ntp-a2.nict.go.jp             1   7   377     5    -91us[ +100us] +/- 6655us
^+ ntp-a3.nict.go.jp             1   7   377    72    +12us[ +199us] +/- 8055us
^+ ntp-b2.nict.go.jp             1   8   377   135  +1423us[+1967us] +/- 8604us
^- time.cloudflare.com           3   8   377     4  +4449us[+4449us] +/-   72ms
^- time.cloudflare.com           3   8   377   137  +3524us[+4067us] +/-   69ms
^- time.cloudflare.com           3   8   377   132  -1427us[-1245us] +/-   77ms
^- time.cloudflare.com           3   8   377   199  +1938us[+2463us] +/-   68ms
^+ ec2-13-208-246-234.ap-no>     4   6   377   132  +7618us[+7800us] +/-   18ms
^+ ec2-15-152-156-115.ap-no>     4   8   377    12  +2115us[+2306us] +/-   14ms
^+ 2406:da16:8ab:c600:f138:>     4   8   377   198  -1922us[-1397us] +/-   10ms
^+ 2406:da16:8ab:c600:5b22:>     4   8   377   195  -2754us[-2227us] +/- 9320us
^- time2.google.com              1   8   377     2  +1572us[+1572us] +/-   23ms
^- time3.google.com              1   8   377   133   +398us[ +579us] +/-   27ms
^- time1.google.com              1   8   377     0  +4479us[+4479us] +/-   30ms
^- time1.google.com              1   8   377   130  -4982us[-4800us] +/-   32ms
```
設定確認。
```console
# chronyc tracking
Reference ID    : 85F3EEF3 (ntp-a2.nict.go.jp)
Stratum         : 2
Ref time (UTC)  : Sat Jan 06 23:29:26 2024
System time     : 0.000471916 seconds fast of NTP time
Last offset     : +0.000362646 seconds
RMS offset      : 0.000476282 seconds
Frequency       : 0.839 ppm fast
Residual freq   : +0.057 ppm
Skew            : 0.808 ppm
Root delay      : 0.010814065 seconds
Root dispersion : 0.003205786 seconds
Update interval : 129.8 seconds
Leap status     : Normal
```
| 設定 | 説明 |
|:-|:-|
| Reference ID |  |
| Ref time (UTC) | 最終同期時間(UTCなので日本時間-9時間になってる) |
| System time | NTPサーバーとサーバーの時刻差分 |
| Leap status | 同期成功していればnormal<br>失敗しているとNot synchronisedとなる |

こちらのブログが詳しかったので参考になりそうです。

https://rurukblog.com/post/chronyc-tracking/

# Firewall(ufw)許可
以下のコマンドでNTPで使うポート番号が123であることが分かった。
```console
# cat /etc/services | grep ntp
nntp            119/tcp         readnews untp   # USENET News Transfer Protocol
ntp             123/udp                         # Network Time Protocol
nntps           563/tcp         snntp           # NNTP over SSL
```
以下の記事を参考に許可設定をする。

https://qiita.com/Nats72/items/013f6378933797110c06

```console
# ufw allow ntp/udp
Rule added
Rule added (v6)
```

# クライアント側で設定して接続確認
クライアントの`chrony.conf`に`pool 192.168.0.254 iburst trust`を追加。
`systemctl restart chronyd`で設定反映。
接続確認してみる。`^*`となっているので接続OKそう。
```console
# chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 192.168.0.254                 5   6    17     4    +18us[ +278us] +/-   19ms
```

# 同期してきてるクライアントを確認
```console
# chronyc -a clients
Hostname                      NTP   Drop Int IntL Last     Cmd   Drop Int  Last
===============================================================================
192.168.0.190                   7      0   6   -    25       0      0   -     -
```

# 参考サイト

https://milestone-of-se.nesuke.com/l7protocol/ntp/linux-spec/

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/configuring-time-synchronization_configuring-basic-system-settings#using-chrony-to-configure-ntp_configuring-time-synchronization

https://chrony-project.org/doc/4.3/chrony.conf.html