أمن تطبيقك ضد تلاعب المستخدم بالوقت باستخدام بروتوكول NTP

في هذا الموضوع سوف اتطرق لافضل طريقة للحصول على التاريخ والوقت الحقيقي

في هذه الايام هناك عدة تطبيقات تعتمد على نظام الـ Credit بحيث يتم أعادة تعيينها بشكل يومي او اسبوعي

اغلب التطبيقات تعتمد على الوقت الحالي Current Date لكن هناك مشكله عند اعتماد التطبيقات عليها وهيا إمكانيه التلاعب بها بسهولة بتغيير وقت الجهاز في اعدادات النظام
وبما انه هذه التلاعب يضر المطور فهناك حل اخر وهو الاعتماد على السيرفر او خدمات World time API والتي اغلبها ليست مجانيه

لكن هناك طريقة افضل واسهل وهيا الاعتماد على بروتوكول NTP

فما هو NTP؟

NTP اختصار لـ Network Time Protocol، وهو بروتوكول ييستخدم لمزامنة الساعة (التاريخ والوقت) بين أجهزة الكمبيوتر والخوادم عبر الإنترنت

الهدف منه هو التأكد من أن كل الأجهزة في شبكة معينة تعمل بنفس الوقت الدقيق والفعلي

لماذا نحتاج إلى NTP؟

لأن الوقت الذي يظهر على الجهاز يمكن أن يكون غير دقيق، لعدة أسباب مثل:

  • تغيير المستخدم لإعدادات الوقت يدويًا

  • تعطل الساعة الداخلية للجهاز

  • الفروقات بين المناطق الزمنية

  • الحاجة لتوحيد الوقت بين عدة أنظمة أو خوادم (خاصة في التطبيقات الحساسة مثل البنوك، أو خدمات الاشتراكات)

كيف يعمل NTP؟

  1. جهازك (أو تطبيقك) يرسل طلب إلى خادم وقت NTP على الإنترنت.

  2. الخادم يرد بالتاريخ والوقت الدقيق

  3. الجهاز يستخدم هذا الوقت لتصحيح أو مقارنة ساعته المحلية

الـ NTP يعتمد على خوادم موثوقة جدًا مثل:

  • خوادم خاصة بالشركات مثل ابل time.apple.com وجوجل time.google.com

دقة NTP

  • يمكن لـ NTP أن يصل دقته إلى ميلي ثانية واحدة عند استخدامه على شبكات جيدة

  • بالرغم من أن الإنترنت قد يسبب تأخيرًا بسيطًا إلا أن NTP يستخدم خوارزميات للتعويض عن هذا التأخير وتقديم وقت قريب جدًا من الحقيقي

متى تستخدم NTP في تطبيقك؟

  • إذا كان تطبيقك يقدم وظائف تعتمد على الوقت بدقة (مثل العد التنازلي، الاشتراكات، الأحداث اليومية)

  • إذا كنت تريد التأكد من أن المستخدم لم يغيّر التاريخ والوقت لتجاوز حدود معينة

  • إذا كنت لا تثق بالساعة المحلية وتريد التحقق من الوقت الحقيقي من مصدر خارجي

كيف أستخدمه في مشروعي ؟

هناك عدة مكتبات ومن احدثها مكتبة swift-ntp المطورة من شركة Apple

بإستخدام هذا الكود سوف يتم إرجاع الوقت الفعلي وايضا وقت النظام للمقارنة

import NTPClient

func getCurrentTime() async {
        do {
            
            let ntp = NTPClient(
                config: NTPClient.Config(
                    version: .v4
                ),
                server: "time.apple.com" 
            )

            let response = try await ntp.query(timeout: .seconds(2))
            
            let secondsComponent = Double(response.offset.components.seconds)
            let attosecondsComponent = Double(response.offset.components.attoseconds) / 1_000_000_000_000_000_000
            let offsetSeconds = secondsComponent + attosecondsComponent
            
            let currentDate = Date().addingTimeInterval(offsetSeconds)
            
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
            formatter.timeZone = TimeZone.current
            
            print("System time: \(formatter.string(from: Date()))")
            print("Accurate time: \(formatter.string(from: currentDate))")
        } catch {
            print("Failed to get NTP time: \(error)")
        }
    }

النتيجة

في هذه التجربة قمت بتقديم التاريخ الى يوم 20 مايو
واليوم الحقيقي هو يوم 15
كما تشاهد في المثال التاريخ تم ارجاعه بالتاريخ الحقيقي حتى رغم تغييره من اعدادات النظام

أمر اخر في حال خوفك من تعطل السيرفر تستطيع اضافة عدة سيرفرات وتكتب كود يتحقق منها جمعها بالاعتماد على الكود السابق وفقط تضيفهم في Array و تعمل Loop