最新記事
カテゴリ
最新記事
カテゴリ
文書の過去の版を表示しています。
Evernote 共有リンク(Evernote で保存したい人向け) https://www.evernote.com/shard/s32/sh/332945c9-464e-4816-9f60-c0d6c735d4e7/69b8e7b5e94ddbc9abb2a677a2ac37e8
Raspberry Pi は消費電力が2W程です.これでNTP Stratum-1 Server を作ると省電力ながらも精度の良いNTPサーバが出来ると思いましたので試してみました. Linux カーネルにパッチをあてて PPS(Pulse Per Second)が処理できるようにして,NTPサーバも再コンパイルして Stratum-1 サーバを構築します.
Linux ディストリビューションは Raspbian です. http://www.raspberrypi.org/downloads から得られる Raspbian Raw Images を SD カードに書き込みます.
Raspberry Pi の拡張ピンに直結できるGPSモジュール基板が販売されています.
Raspberry Pi GPS Addon Board
http://ava.upuaut.net/store/index.php?route=product/product&product_id=95
日本からも購入できて,購入してから約10日後に届きました.
まずは Raspbian を最新の状態へ更新します。
$ sudo apt-get update $ sudo apt-get upgrade
次に、ラズパイとGPSモジュールは,ラズパイの UART で直結しますので,Raspbian の inittab と cmdline.txt を編集して,カーネルのコンソールやシリアル経由でのログインを無効にします.
この時点で,一度ラズパイを再起動します.
もし triggerhappy が動いていれば,不要ですので停止します. なお,apt-get remove triggerhappy で triggerhappy を remove しようとすると,raspi-config も remove されそうなので,triggerhappy は remove せずに,自動起動をしないようにだけします.
$ sudo insserv -r triggerhappy
サウンド関係も不要ですので, /etc/modules を開いて snd-bcm2835 もロードさせないようにします.
$ cat /etc/modules # /etc/modules: kernel modules to load at boot time. ... #snd-bcm2835
また,insserv で alsa-utils も自動起動しないようにします.
$ sudo insserv -r alsa-utils
ホスト名の設定と,mdnsでホスト名でアクセスできるようにしておきます.
Raspbian では,ホスト名は /etc/hostname で決定します.また,avahi-daemon をインストールすると,Linux や Mac OS X から “ホスト名.local” で名前引き出来るようになりますのでインストールします.
$ sudo apt-get install avahi-daemon
ここまでで基本設定は終了です.
GPSモジュール購入サイトからは,GPS モジュールの詳細な資料が無さそうですので,ロジックアナライザを使って,どの様に信号が来ているのかを調べてみます.
GPS からの情報は,位置や時刻は NMEA センテンスと呼ばれる形式でシリアルで通信します. そのため,ラズパイでシリアルからGPSモジュールを読めるツールをインストールします. http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html を参考に,以下のツールを入れます.
$ sudo apt-get install gpsd gpsd-clients python-gps
gpsd は,GPS モジュールからのNMEAセンテンスを代表で受信して,クライアントからの要求に対して配送するデーモンです.最終的には gpsd は使いませんが,GPSモジュールの情報を受信できているかの動作確認に使います.
$ sudo gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock
gpsd が起動できれば,cgps -s を実行してGPSモジュールからの時間や位置情報などが受信できているかを確認します.
GPSモジュールからの時間や位置情報を受信できていれば,GPSモジュールとの接続はOKです. gpsd はこれ以上使用しません(2014-04-29).
http://ntpi.openchaos.org/pps_pi/ を参考に,ラズパイの拡張ピンのGPIO18 をPPSドライバで使えるようにします. このページに記載がありますが,「Enable modules Device Drivers/PPS support/PPS support and PPS client using GPIO」を忘れないで下さい.
(2014-04-29)ラズパイの Linux カーネルの Config は,CONFIG_NO_HZ が有効になっています. この場合,精度をナノ秒精度で合わせられないようです.必ず CONFIG_NO_HZ は is not set にしましょう.
以下のURLのページが参考になります.
Linux Kernel Config の要所は以下の通りです.
カーネルのビルドとインストールができたら,/etc/modules に pps-gpio を追加します.
$ cat /etc/modules # /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. # Parameters can be specified after the module name. #snd-bcm2835 pps-gpio $
Linux カーネルのPPSドライバが,GPSモジュールのPPSを読み取っているかを確認するには,pps-tools をインストールします.
$ sudo apt-get install pps-tools $ ppstest /dev/pps0
GPSモジュールが測位している(PPS LEDが点滅している)と,ppstest ではそのPPS周期で出力を出していくはずです.
これも,http://ntpi.openchaos.org/pps_pi/ を参考にビルドします.
ここからは,http://ntpi.openchaos.org/pps_pi/ で書いている方法とは異なります. http://ntpi.openchaos.org/pps_pi/ に記載している方法は,GPSモジュールからの情報はgpsd がまず読み取り,gpsd と ntpd が共有メモリで時刻情報を読み出す方式です.
私の方法は,gpsd を介さずに,ntpd が直接GPSモジュールから読み出す方法です. なぜこの方法にするのかと言うと,gpsd と ntpd 間での共有メモリ書き込み・読み取り誤差を無くして精度を上げるためです. しかし逆に gpsd を使いませんので,他の用途でGPSの位置情報を使うことができなくなります.
ntpd が,GPSモジュールのデバイスファイルを使用できるようにするため,/etc/udev/rules.d/09.pps.rules を作成します.
$ cat /etc/udev/rules.d/09.pps.rules KERNEL=="ttyAMA0", SYMLINK+="gps0" KERNEL=="pps0", OWNER="root", GROUP="dialout", MODE="0660", SYMLINK+="gpspps0" $
また,vigr コマンドで,ntp ユーザを dialout グループに追加します. ここでラズパイを一旦再起動します.これで,以下の様になるはずです.
まずは現在の ntp サーバ設定をバックアップします.
$ sudo cp /etc/ntp.conf /etc/ntp_orig.conf
次に,ntp.conf を修正して,GPSモジュールからの情報を読めるようにします. 以下にその差分を貼ります.
https://gist.github.com/tosihisa/bd55fec0b706b2fb062e“
重要な変更は以下の通りです.
以下のURLの方も,同じようにラズパイによる NTP Stratum-1 Server に取り組んでおられます.こちらの方の情報を参考にさせて頂きました. http://nyanchew.com/jp/gps%E3%81%AEpps%E4%BF%A1%E5%8F%B7%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F-stratum-1-ntp%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9
上記URLによりますと,Linux カーネルの設定以外に,以下の設定を行うと良さそうですので試します.
disable_pvt=1
を /boot/config.txt
に追加する.smsc95xx.turbo_mode=0
を /boot/cmdline.txt
に追加する.echo “performance” > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
/etc/init.d/ntp
の start で上記処理を行うようにしました.setserial /dev/ttyAMA0 low_latency
/etc/init.d/ntp
の start で上記処理を行うようにしました.ここまで出来たら,ラズパイを再起動して,ntpd がGPSモジュールと同期できているかを確認します.
$ ntpq -p remote refid st t when poll reach delay offset jitter ============================================================================== oGPS_NMEA(0) .GPS. 0 l 5 16 377 0.000 0.000 0.001 $
なお,GPSモジュールとラズパイが完全に同期するには,数時間かかるようです.初めは,GPS_NMEA(0)の前が '*' ですが,PPS同期すると 'o' に変わるはずです. なのですぐに「おかしい?」と思わずに,数時間待ってみて確認すると良いです.
NTP サーバの稼働状況で,ntpd がGPSモジュールとどれくらいズレているのかは,ntpd のログ情報である loopstats から得られます.
loopstats ファイルはテキストファイルですので,gnuplot を使って簡単にグラフ化出来ます.
ntpd の loopstats ファイルを元に gnuplot でグラフ化出来るシェルスクリプトを以下に貼ります.
https://gist.github.com/tosihisa/7978b6497f57e506589e”
以下の様に使います.
$ loopstats_gnuplot.sh loopstats [レンジ範囲] [レンジメモリ]
以下に,ntpd の1日のGPSモジュールとの同期状態グラフを貼ります. 1日の内,初めの内は10マイクロ以上の変動が見られるのですが,その内収束して数マイクロ秒の差でGPSモジュールと同期しているのが確認できます.
1日のうちの初めの10マイクロ以上の変動は謎で,これは調査中ですが,これでラズパイが NTP Stratum 1 として動いていることが確認できます.
CONFIG_NO_HZ を無効にしたカーネルと,「●(2014-04-29)その他の設定」を実施した後のGPS同期状態グラフを以下に示します.
初めの±2マイクロ秒以上の offset は Linux カーネル変更と設定前です.
まだ24時間も稼働させていませんが同期精度が格段に向上しています.
上記のグラフではレンジが荒いので,±3マイクロ秒範囲でグラフにしたものを貼ります.時々1マイクロ秒を超えるオフセットがありますが,ナノ秒レベルで同期できています.
2014年1月に大規模なNTPリフレクションアタックがあったようです.これは NTP の monlist 機能を悪用したものです. http://www.jpcert.or.jp/at/2014/at140001.html
この攻撃への対象方法は様々な Web サイトで紹介されておりますが,ここでは,以下のWebページを参考に,Linux の iptables で遮断しようと思います. http://packetpushers.net/one-liner-iptables-rule-to-filter-ntp-reflection-on-linux-hypervisor/
このページでは,パケット仲介する所での FORWARD チェーンで対策されています. これを参考に,NTPサーバで以下のコマンドを実行して INPUT チェーンで monlist パケットを弾くようにします.
# iptables -A INPUT -i eth0 -p 17 -m multiport --ports 123 -m u32 --u32 "0>>22&0x3C@8&0xFF=42" -j DROP
本当に iptables で弾いているかどうか,試してみます. まず,NTPサーバで iptables の設定状況を確認します.
# iptables -L INPUT -n -v Chain INPUT (policy ACCEPT 1949K packets, 162M bytes) pkts bytes target prot opt in out source destination 0 0 DROP udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 multiport ports 123 u32 "0x0>>0x16&0x3c@0x8&0xff=0x2a" #
次に,NTPサーバ以外から,以下のコマンドを実行してみます.
$ ntpdc -nc monlist [NTPサーバ] [NTPサーバ]: timed out, nothing received ***Request timed out $
接続できませんでした.NTPサーバ側の iptables を再度確認します.
# iptables -L INPUT -n -v Chain INPUT (policy ACCEPT 1951K packets, 162M bytes) pkts bytes target prot opt in out source destination 1 220 DROP udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 multiport ports 123 u32 "0x0>>0x16&0x3c@0x8&0xff=0x2a" #
パケットカウントがカウントされ,monlist を検出して弾いたことが確認できます. なお,このNTPサーバは,2014年3月以降,pool.ntp.org に登録しているのですが,これまで 122回ほど monlist のクエリを受けていたようです. 数は多くないと思いますが,依然 monlist によるリフレクションアタックは0では無いので,公開NTPサーバを構築されている方は依然注意が必要です.
# iptables -L INPUT -n -v Chain INPUT (policy ACCEPT 369M packets, 28G bytes) pkts bytes target prot opt in out source destination 122 6958 DROP udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 multiport ports 123 u32 "0x0>>0x16&0x3c@0x8&0xff=0x2a"