前置き
かなり無理矢理かつ、動作を保証するものではありません。
手習いで試しに書いてみたぐらいの温度感です
うるう秒
”元旦「うるう秒」でエンジニア悲鳴 「年末年始がなくなる」”と言ったニュースサイトでも取り上げられているように、1月1日 日本時間朝9時にうるう秒が挿入されます。つまり、8時59分60秒 という時間が挿入されます。
60秒が挿入されるとはどういうことか
「NTP うるう秒(閏秒)」こちらのサイトの情報を引用させていただくと
日付(JST) | NTP time | LI |
2006/01/01 08:59:59 | 3345062399 | 01 |
2006/01/01 08:59:60 | 3345062400 | 01 |
2006/01/01 09:00:00 | 3345062400 | 00 |
NTPサーバからのレスポンスには事前にうるう秒の挿入を示すLeap Indicatorというフラグがセットされます。そうして、60秒から00秒にかけては同じ時間がレスポンスされて帰ってきます。
このLIですが、このLIがセットされているとSlewモードからStepモードに移行してしまうNTPクライアントのバグなども存在していますし、なかなか厄介な存在です。
前回は、このLIがNTPクライアントに到達しないように、該当時間だけ上位のNTPサーバとの同期を停止するという方法を取ったという人もいるようです。もちろん、60秒を挿入しないぶん1秒早く時刻が刻まれていきますが、殆どのソフトウェアは個々に対応が進んでいるとはいえ予期せぬうるう秒に起因する不具合を踏むよりはマシなのかと思います。
NTP leap indicatorを上書きするProxyを書いた
上位のNTPサーバと同期を止める方法は、ローカルのハードウェアクロックを頼りにしており、それはそれで心もとないなと思い、LIフラグをオフにするUDP Proxyを書いてみました。
unset-leap-indicator-proxy
https://github.com/flano-yuki/unset-leap-indicator-proxy
NTPサーバを指定して起動すると、UDPの123 portでLISTENし、受け取ったNTP Requestを指定したサーバにProxyします。
vagrant@vagrant:~/tmp$ sudo go run ./proxy.go -v ntp.nict.jp Info: Start Proxy on :123 to ntp.nict.jp Received from 192.168.0.179:123 Received from 192.168.0.179:123 Received from 192.168.0.179:123
このProxyはNTPパケットを実際にパースすることはなく、単純にUDPボディの上位2bit(Leap Indicator)を 00 に上書きします。
これによってNTPクライアントにLIが入ることもありません。しかし、うるう秒のタイミングでは60秒が挿入されず1秒ずれてしまうので、そこからはNTPの時刻同期の仕組みによってずれが解消されていくものと思います。
ACL機能がないため踏み台攻撃に注意してください。