NTPサーバーの正しい時刻を取得する

複数の端末で時計にズレがあった場合「どちらのデータが新しいのか」判断できず困ることがあります。

ライセンス終了日確認で、永遠に過去の時刻にしてずっと使う…なんてガバ仕様のアプリが昔は結構ありました。

これを防ぐためには NTP サーバーと呼ばれるサーバー上の時刻を使うのが便利です。
以下のコードで取得できます。

using System;

public class NTPTime
{
    /// <summary>
    /// NTP サーバーよりサーバー時刻を取得
    /// </summary>
    public static DateTime Get()
    {
        // windows 標準だから重そう
        //const string NTP_SERVER = "time.windows.com";
        // DNS サーバーを通さない方が、より取得成功率が上がる
        //const string NTP_SERVER = "ntp.jst.mfeed.ad.jp";
        const string NTP_SERVER = "210.173.160.27";
        const int    NTP_PORT   = 123;

        // NTPサーバーへの接続用 UDP 生成
        System.Net.Sockets.UdpClient objSck;
        System.Net.IPEndPoint        ipAny = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
        objSck = new System.Net.Sockets.UdpClient(ipAny);

        // リクエスト送信
        byte[] sdat = new byte[48];
        sdat[0]     = 0xB;
        objSck.Send(sdat, sdat.Length, NTP_SERVER, NTP_PORT);

        // 日時データ受信
        byte[] rdat = objSck.Receive(ref ipAny);

        // 1900/1/1 からの経過秒数
        uint from19000101 = (uint)(rdat[40] << 24 | rdat[41] << 16 | rdat[42] << 8 | rdat[43]);

        // UTC Time
        DateTime dt = new DateTime(1900,1,1).AddSeconds(from19000101);
        return dt;
    }
}

問題点

日本時間ではない

日本時間に変換したい場合は、以下のコードでコンバートします。

var utcTime = NTPTime.Get();
var jpTime  = System.TimeZoneInfo.ConvertTimeFromUtc(utcTime, System.TimeZoneInfo.Local);

取得に失敗する

NTP サーバーという無料提供のサーバーにタダ乗りしているだけなので、動作が不安定だったり、取得に失敗することはあるでしょう。
サンプルのようにベタ IP にしたり、複数の NTP サーバー値を比較することで、問題はある程度緩和できます。

今回のサンプルは、単純化するため一つのサーバーからのみ取得しています。

受信ソケットデータが改ざんされる

アプリのお試し期間判定で、時刻を改ざんして使われたくない…そんな理由で NTP サーバーを検討する方もいるかもしれません。

このパケットは知っている人なら中身がバレバレなので、たとえ NTP サーバーから時間を取得しようが、ソケットデータ自身を改ざんされる恐れがあります。

この場合「ソケットデータの改ざんで、ユーザーがどれ程の利益を得るか」が判断のポイントになります。
アプリが年間 1000 万もかかるのであれば「お試し期間延長」は意味を持ちますが(やったらダメですよ?)、年間 1000 円であれば、改ざんする方がコスパは悪いでしょう。

問題がある場合、面倒ですが自社サーバーから署名&暗号化された時刻情報を取得するといった対処も検討しましょう。(そうやってどんどんサーバー運用費用は上がっていく…)

セキュリティ問題はどこまでいっても破られる可能性があります。そんな時、いかに「改ざんする方がコスパが悪い」と思わせられるかどうかが大事です。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA