علت عقب ماندن ساعت VPS و روش رفع مشکل همگامسازی زمان
ساعت VPS به دلیل نبود همگامسازی دقیق دچار خطا میشود. با بررسی خروجی chronyc و timedatectl، انحراف زمانی را شناسایی کرده و مشکل عدم ورود به سیستم و خطای 2FA را حل کنید.
چرا ساعت VPS شما دچار انحراف میشود
ساعت یک VPS به این دلیل دچار انحراف میشود که هیچ عاملی آن را اصلاح نمیکند. هسته سیستمعامل (kernel)، زمان را بر اساس یک شمارنده سختافزاری محاسبه میکند که ممکن است کمی سریعتر یا کندتر از حد معمول کار کند؛ در نبود یک کلاینت همگامسازی زمان، این خطای کوچک در هر ساعت افزایش مییابد. در داخل یک ماشین مجازی، دلیل دومی نیز وجود دارد: سیستمعامل مهمان (guest) شما از یک CPU فیزیکی بهصورت اشتراکی با سایر مهمانها استفاده میکند، بنابراین لحظاتی که سیستم شما برای پردازش زمانبندی (schedule) نمیشود، لحظاتی است که نمیتواند زمان را بشمارد.
در یک مهمان KVM امروزی، خودِ شمارنده بهندرت مشکل اصلی است. منبع پارا-مجازی kvm-clock مقداری را میخواند که میزبان (host) آن را نگهداری میکند، بنابراین یک مهمان سالم زمان را بسیار نزدیک به میزبان خود دنبال میکند. ساعتهایی که بهطور مشهودی اشتباه هستند، معمولاً به دلایل سادهتری دچار خطا میشوند. یا هیچ daemon همگامسازی در حال اجرا نیست، یا دو daemon همزمان در حال اجرا هستند و با یکدیگر تداخل دارند، یا ترافیک خروجی پورت 123 از نوع UDP هرگز از شبکه ارائهدهنده شما خارج نمیشود. یک مهمان، نظم زمانی خود را از میزبان یا از طریق پروتکل NTP (پروتکل زمان شبکه) دریافت میکند، نه از نوسانساز (oscillator) داخلی خودش.
پیامدهای واقعی تنظیم نبودن ساعت سیستم
- کدهای احراز هویت دو مرحلهای TOTP (رمز یکبارمصرف مبتنی بر زمان) دیگر مطابقت ندارند؛ در نتیجه، حتی با داشتن رمز عبور و کلید صحیح، دسترسی شما به سرور مسدود میشود.
- گواهینامهای که همین یک دقیقه پیش صادر شده است رد میشود و
curlخطایSSL certificate problem: certificate is not yet validرا چاپ میکند. apt updateمخزنی را با خطایE: Release file for ... is not valid yet (invalid for another 1d 2h 3min 4s)رد میکند.- وظایف زمانبندیشده (Scheduled work) در لحظه اشتباه اجرا میشوند؛ پرش ساعت میتواند باعث اجرای دوبارۀ یک وظیفه و نادیده گرفته شدن وظیفهای دیگر شود.
- لاگهای دو سرور مختلف با هم همگام نمیشوند و در نتیجه، بازسازی خط زمانی یک رخداد امنیتی تنها با حدس و گمان ممکن خواهد بود.
میزان تحمل خطا (Tolerance) بسیار کمتر از آن چیزی است که اکثر افراد تصور میکنند. ارقام زیر مقادیر پیشفرض مستند شده هستند، نه نتایج حاصل از آزمایش.
The data behind this chart
[
{
"label": "TLS certificate boundary",
"tolerance_seconds": 0,
"documented_in": "RFC 5280"
},
{
"label": "chrony steps instead of slewing",
"tolerance_seconds": 1,
"documented_in": "Debian and Ubuntu chrony.conf"
},
{
"label": "TOTP code, one time step",
"tolerance_seconds": 30,
"documented_in": "RFC 6238"
},
{
"label": "Kerberos clock skew",
"tolerance_seconds": 300,
"documented_in": "MIT krb5 default"
}
]کد TOTP بر اساس شمارندهای محاسبه میشود که هر 30 ثانیه تغییر میکند و اکثر سیستمهای تأییدکننده، یک گام اختلاف در هر دو طرف را میپذیرند. نیم دقیقه خطا در هر جهت، کل بودجه زمانی شماست. پروتکل Kerberos بسیار منعطفتر است و اجازه انحراف پیشفرض آن 300 ثانیه است. گواهینامهها اما هیچ انعطافی ندارند: آنها با لحظات زمانی ثابت و یک دوره ارفاق (Grace period) به میزان 0 ثانیه بررسی میشوند؛ بنابراین، ساعتی که حتی یک ثانیه جلوتر باشد، گواهینامهای که کاملاً معتبر است را رد میکند.
سه ساعت و اهمیت هر کدام
ساعت سیستم (system clock) همان ساعتی است که اهمیت دارد. این ساعت در واقع CLOCK_REALTIME هسته است: شمارش ثانیهها از اول ژانویه 1970 به وقت UTC که در حافظه نگهداری میشود و توسط هر فرآیندی که نیاز به درج زمان داشته باشد، خوانده میشود. خطوط لاگ، بررسی گواهیها، کدهای TOTP و زمان تغییر فایلها همگی از این ساعت نشأت میگیرند. وقتی کسی میگوید زمان سرور اشتباه است، منظورش همین ساعت است.
ساعت سختافزاری (hardware clock) که به آن RTC (ساعت زمان واقعی) نیز میگویند، یک شمارنده مجزا است که هنگام خاموش بودن دستگاه نیز به کار خود ادامه میدهد. در یک ماشین فیزیکی، این ساعت یک تراشه با پشتیبانی باتری است. در داخل یک ماشین مجازی (guest)، این ساعت توسط هایپروایزر شبیهسازی میشود، بنابراین تا حد زیادی یک مصنوع از سمت میزبان (host) است. لینوکس این ساعت را یکبار هنگام بوت برای مقداردهی اولیه میخواند و سپس شمارش خود را ادامه میدهد. دستور timedatectl مقدار آن را در خط RTC time چاپ میکند. در یک VPS برای عیبیابی به این خط تکیه نکنید، زیرا این مقدار دیدگاه میزبان از زمان را نشان میدهد و نه وضعیت همگامسازی ساعت سیستم شما. در یک کانتینر معمولاً هیچ /dev/rtc وجود ندارد، بنابراین hwclock --show با خطای hwclock: Cannot access the Hardware Clock via any known method. مواجه میشود.
منبع ساعت (clocksource) چیزی است که هسته با استفاده از آن، زمان را بین خواندنهای متوالی میشمارد. از هسته خود بپرسید کدام منبع را انتخاب کرده است:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
cat /sys/devices/system/clocksource/clocksource0/available_clocksourceدر KVM معمولاً kvm-clock را مشاهده خواهید کرد. این منبع مقداری را میخواند که توسط میزبان نگهداری میشود و به همین دلیل است که یک ماشین مجازی KVM حتی بدون کلاینت NTP، تا مدتی تقریباً دقیق باقی میماند. tsc شمارنده خودِ پردازنده است. ماشینهای مجازی Xen مقدار xen و ماشینهای مجازی Hyper-V منبع hyperv را گزارش میدهند. این تنظیمات را تغییر ندهید مگر اینکه دلیل فنی اندازهگیریشدهای برای آن داشته باشید، زیرا هسته از قبل بهترین منبعی را که به آن اعتماد دارد، انتخاب کرده است.
برخی از میزبانها یک دستگاه PTP (پروتکل زمان دقیق) را نیز در اختیار ماشین مجازی قرار میدهند که به chrony اجازه میدهد ساعت میزبان را مستقیماً و نه از طریق شبکه بخواند. بررسی این موضوع ارزشمند است، هرچند اغلب در VPSهای اشتراکی در دسترس نیست:
sudo modprobe ptp_kvm
ls /dev/ptp*
cat /sys/class/ptp/ptp0/clock_nameاگر modprobe با خطا مواجه شد یا دستگاهی نمایش داده نشد، میزبان شما این قابلیت را ارائه نمیدهد و پاسخ شما استفاده از NTP شبکه است. اگر clock_name ساعت مجازی KVM را نام برد، chrony میتواند با استفاده از یک خط refclock PHC /dev/ptp0 poll 2 در فایل پیکربندی خود از آن استفاده کند.
خواندن وضعیت زمان در ماشین خود
با یک دستور شروع کنید. این دستور در یک صفحه به این پرسش پاسخ میدهد که «آیا چیزی این ساعت را دقیق نگه میدارد یا خیر».
timedatectlبه جای اعتماد به عددی که در ذهن دارید، این خطوط را بخوانید:
Local timeوUniversal timeیک لحظهٔ واحد هستند که به ترتیب در منطقهٔ زمانی شما و به صورت UTC چاپ شدهاند. اگر این دو یکسان باشند، ماشین از قبل روی UTC تنظیم شده است.RTC timeهمان ساعت سختافزاری است که در بالا توضیح داده شد. در یک VPS، آن را نادیده بگیرید.Time zoneچیزی است که سیستم برای فرمتدهی زمان محلی استفاده میکند.System clock synchronizedپرچم اختصاصی کرنل است. یک دیمون زمان (time daemon) پس از آنکه به منابع خود اعتماد کرد، این پرچم را تنظیم میکند؛ بنابراینnoبه این معنی است که از زمان بوت، هیچ چیزی این ساعت را تنظیم نکرده است.NTP serviceوضعیت systemd-timesyncd را به طور خاص گزارش میدهد.n/aدر ماشینی که chrony را اجرا میکند طبیعی است، زیرا timesyncd در آنجا نصب نشده است.System clock synchronized: yesبه همراهNTP service: n/aبه این معنی است که chrony در حال انجام کار است و کرنل با آن موافق است.
در مرحله بعد، بپرسید که چقدر اختلاف زمانی دارید. آن را با نگاه کردن به ساعت گوشی خود تخمین نزنید. اگر chrony در حال اجراست:
chronyc tracking
chronyc sources -vchronyc tracking اعدادی را چاپ میکند که به این پرسش پاسخ میدهند. System time اختلاف فعلی از زمان NTP است که با کلمه fast یا slow دنبال میشود. Last offset اندازه آخرین اصلاح انجامشده است. Frequency خطای نرخ (rate error) است که chrony در ساعت شما اندازهگیری کرده و در حال جبران آن است. Leap status باید Normal را نشان دهد. اگر Not synchronised را نشان میدهد و Reference ID برابر با 00000000 () است، chrony هنوز منبعی را برای همگامسازی انتخاب نکرده است.
chronyc sources -v راهنمای علائم را بالای لیست چاپ میکند تا نیازی به حفظ کردن آنها نداشته باشید. دو ستون بیشترین اهمیت را دارند. کاراکتر وضعیت در ابتدای هر خط نشان میدهد که chrony چگونه آن منبع را ارزیابی میکند؛ جایی که * منبعی را که در حال حاضر استفاده میکند مشخص میکند و ? در هر خط به این معنی است که هیچ پاسخی دریافت نمیشود. Reach تاریخچه پاسخهای هشت نظرسنجی (poll) آخر است که به صورت اکتال چاپ شده: 377 یعنی هر هشت مورد پاسخ داده شدهاند، 0 یعنی هیچکدام پاسخ داده نشدهاند.
اگر systemd-timesyncd مسئولیت را بر عهده دارد:
timedatectl timesync-status
timedatectl show-timesync --alltimesync-status سروری که با آن در ارتباط است، بازه نظرسنجی و مقدار Offset را چاپ میکند. اگر دستور به جای چاپ وضعیت، خطایی درباره سرویس برگرداند، یعنی timesyncd دیمون مسئول در این سیستم نیست، که خود این موضوع پاسخ پرسش شماست.
برای یک بررسی کلی نسبت به دنیای بیرون بدون ابزارهای اضافی، ساعت خود را با هدر HTTP Date عمومی مقایسه کنید که با دقت یک ثانیه و به وقت GMT ارائه میشود:
date -u
curl -sI https://www.cloudflare.com | grep -i '^date:'اختلاف یک یا دو ثانیهای در اینجا طبیعی است و اهمیتی ندارد. اختلاف یک دقیقهای، باگ شماست.
استفاده از chrony یا systemd-timesyncd روی VPS
توزیعهای Ubuntu و Debian بهصورت پیشفرض از systemd-timesyncd استفاده میکنند. این ابزار یک کلاینت SNTP (پروتکل ساده زمان شبکه) است: این کلاینت در هر لحظه از یک سرور پرسوجو میکند و ساعت سیستم را به سمت آن تنظیم مینماید. برای ماشینی که همیشه آنلاین است و زمان آن از ابتدا تقریباً دقیق است، این ابزار کافی بوده و هزینه اجرایی ناچیزی دارد.
نرمافزار chrony یک پیادهسازی کامل از NTP است و به دلایلی که در خروجی خود آن قابل مشاهده است، گزینه پیشفرض بهتری برای ماشینهای مجازی محسوب میشود. این ابزار همزمان از چندین منبع پرسوجو کرده و منابعی که با بقیه همخوانی ندارند را کنار میگذارد. chrony خطای نرخ ساعت شما را اندازهگیری کرده و آن را در یک فایل drift مینویسد؛ بنابراین بهجای دنبال کردن هر نمونه، تمایل ساعت به خطا را اصلاح میکند. این ابزار همچنین در برابر دو اتفاقی که برای VMها رخ میدهد اما برای سیستمهای فیزیکی خیر، بهسرعت بازیابی میشود: یکی توقف (pause) توسط میزبان و دیگری انتقال به یک میزبان دیگر در حین اجرا. زمانی که یک دستگاه PTP توسط میزبان ارائه شود، این chrony است که آن را میخواند.
sudo apt update && sudo apt install -y chrony
systemctl status chrony --no-pager
chronyc sources -v
chronyc trackingهنگام اجرای apt، خروجی آن را بخوانید. در Debian و Ubuntu، بستههای chrony و systemd-timesyncd هر دو time-daemon را ارائه میدهند، بنابراین apt هنگام نصب chrony، ابزار timesyncd را حذف میکند. این رفتار صحیح و مورد انتظار است. هرگز هر دو را همزمان اجرا نکنید، زیرا دو daemon که یک ساعت را تنظیم میکنند با هم تداخل پیدا کرده و در این حالت، به offset گزارششده توسط هیچکدام نمیتوان اعتماد کرد. در Rocky و AlmaLinux، نصب را با sudo dnf install -y chrony انجام دهید، جایی که نام unit بهجای chrony، برابر با chronyd است.
فایل پیکربندی در Debian و Ubuntu برابر با /etc/chrony/chrony.conf و در Rocky و Alma برابر با /etc/chrony.conf است. تنظیمات پیشفرض توزیع برای یک VPS مناسب است، بنابراین تنها در صورت نیاز آن را تغییر دهید. درک دو دستورالعمل زیر مفید است:
- خطوط
poolوserverمنابع زمانی را مشخص میکنند. افزودنiburstبه chrony دستور میدهد که در هنگام راهاندازی یک burst سریع ارسال کند تا اولین همگامسازی بهجای چند دقیقه، در چند ثانیه انجام شود. - دستور
makestepتعیین میکند که chrony چه زمانی ساعت را بهجای اصلاح تدریجی، بهیکباره پرش دهد (jump). تنظیمات فعلی خود را باgrep -n makestep /etc/chrony/chrony.confبررسی کنید. مقدار پیشفرض در Debian و Ubuntu یعنیmakestep 1 3به این معناست: در طول سه بهروزرسانی اول پس از شروع chronyd، اگر اختلاف ساعت بیش از یک ثانیه بود، ساعت را پرش دهید و پس از آن، فقط از طریق slewing (اصلاح تدریجی) عمل کنید.
اگر میخواهید ترافیک زمانی در برابر دستکاری در مسیر احراز هویت شود، chrony نسخه 4 و بالاتر از NTS (امنیت زمان شبکه) پشتیبانی میکند. ابتدا نسخه خود را با chronyd -v تأیید کنید و توجه داشته باشید که NTS علاوه بر پورت UDP 123، به باز بودن پورت خروجی TCP 4460 نیز نیاز دارد:
server time.cloudflare.com iburst ntsپیش از اعتماد به سرویس، آن را restart کرده و وضعیتش را بررسی کنید. پیکربندیای که در تجزیه (parse) شکست بخورد، شما را بدون هیچ daemon زمانی رها میکند و ساعت سیستم نیز این موضوع را به شما اطلاع نخواهد داد.
sudo systemctl restart chrony
chronyc sources -v
chronyc trackingچرا ساعتی که چند دقیقه عقب یا جلو است، همچنان اشتباه میماند
یک daemon زمانسنج برای اصلاح اختلاف زمانی، دو روش دارد. روش Slewing سرعت ساعت را کم یا زیاد میکند تا خطا بهتدریج برطرف شود؛ در این حالت زمان همیشه رو به جلو حرکت میکند و هیچ timestamp تکراری یا حذفشدهای نخواهیم داشت. روش Stepping مستقیماً به مقدار صحیح میپرد که بسیار سریع است اما میتواند ساعت را به عقب برگرداند. عقب رفتن زمان برای هر فرآیندی که مدتزمان سپریشده را بر اساس ساعت دیواری محاسبه میکند خطرناک است، بنابراین هر دو daemon روش Slewing را ترجیح میدهند.
همین اولویت باعث میشود ساعتی که خطای زیادی دارد، برای مدت طولانی اشتباه بماند. برنامه chrony فقط در بازه زمانی که makestep اجازه میدهد عمل Stepping را انجام میدهد؛ این بازه بهصورت پیشفرض شامل چند بهروزرسانی اول پس از شروع به کار daemon است. اگر chronyd یک هفته روشن باشد و سپس متوجه خطای 40 ثانیهای شود، از روش Slewing استفاده میکند و اصلاح 40 ثانیه با این روش بسیار طولانیتر از آن است که بخواهید منتظر بمانید. آن را یکبار و آگاهانه در یک لحظه خلوت، بهصورت دستی اعمال کنید:
sudo chronyc makestep
chronyc trackingاکنون chronyc tracking باید یک offset در System time نزدیک به صفر گزارش کند و Last offset باید اندازه مقداری که بهتازگی اصلاح شده را نشان دهد. پیش از اجرای این دستور روی یک میزبان دیتابیس پرمشغله فکر کنید، زیرا ساعتی که به عقب میپرد میتواند نرمافزارهایی را که فرض کردهاند زمان فقط رو به جلو حرکت میکند، دچار اختلال کند. راهاندازی مجدد (Restart) daemon نسخه ملایمتری از همین اصلاح است، زیرا پنجره makestep دوباره در لحظه شروع باز میشود.
کانتینرها از ساعت میزبان (Host) استفاده میکنند
یک کانتینر ساعت دیواری (wall clock) مستقل ندارد، بنابراین چیزی برای همگامسازی در داخل آن وجود ندارد. فضای نام زمان (time namespaces) در لینوکس فقط ساعتهای monotonic و boot-time را مجازیسازی میکند. CLOCK_REALTIME مجازیسازی نمیشود، به این معنی که کانتینر همان ساعت سیستمی را میخواند که میزبانِ در حال اجرای آن از آن استفاده میکند. ساعت را روی میزبان اصلاح کنید تا ساعت تمام کانتینرهای موجود روی آن میزبان در همان لحظه اصلاح شود.
چند پیامد از این موضوع ناشی میشود. در یک image، ابزارهای chrony یا ntpd را نصب نکنید، زیرا در بهترین حالت هیچ کاری انجام نمیدهند. تنظیم تاریخ در داخل یک کانتینر بدون امتیاز (unprivileged) با خطای date: cannot set date: Operation not permitted مواجه میشود، زیرا هسته برای این فراخوانی به CAP_SYS_TIME نیاز دارد. اعطای CAP_SYS_TIME به کانتینر یک ساعت اختصاصی نمیدهد، بلکه به کانتینر این امکان را میدهد که ساعت میزبان و در نتیجه ساعت تمام کانتینرهای دیگر را تغییر دهد.
تفاوت منطقه زمانی (time zone) در داخل کانتینر، مشکل ساعت نیست. یک image که /etc/localtime خاص خود را دارد، همان لحظه را با فرمت منطقه زمانی دیگری نمایش میدهد، بنابراین date اشتباه به نظر میرسد در حالی که ساعت درست است. متغیر TZ=UTC را در محیط کانتینر تنظیم کنید تا این سردرگمی برطرف شود. runtime انتخابی شما در اینجا تغییری ایجاد نمیکند و مقایسه Podman بدون روت و Docker مواردی را که تغییر میدهد، پوشش میدهد.
مناطق زمانی: UTC روی سرور، زمان محلی برای کاربران
ماشین را روی UTC تنظیم کنید و آن را تغییر ندهید.
timedatectl list-timezones | grep -i utc
sudo timedatectl set-timezone UTC
timedatectlزمان UTC فاقد تغییر ساعت تابستانی (Daylight Saving) است و همین موضوع، دلیل اصلی این انتخاب است. یک وظیفهٔ روزانه (cron job) در ساعت 02:30 در منطقهای که ساعت تابستانی را اعمال میکند، در روزی که ساعتها به عقب کشیده میشوند دو بار اجرا شده و در روزی که به جلو کشیده میشوند، اصلاً اجرا نمیشود. man 8 cron نحوهٔ مدیریت خاص برای تغییرات کمتر از سه ساعت را مستند کرده است: وظایفی که به دلیل پرش به جلو نادیده گرفته شدهاند، بلافاصله پس از تغییر اجرا میشوند و وظایفی که در یک ساعت تکراری ناشی از پرش به عقب قرار میگیرند، برای بار دوم اجرا نمیشوند. این رفتار منطقی است، اما همچنان رفتاری است که نباید در ساعت 03:00 نگران آن باشید. تحت UTC، وظیفه در هر روز از سال، دقیقاً یک بار اجرا میشود. اگر وظیفهٔ شما به جای اجرا در ساعت نامناسب، بهطور کامل اجرا نمیشود، دلایل اجرا نشدن بیسروصدای یک cron job توضیح محتملتری است.
همین استدلال برای خواندن لاگها نیز صادق است. journalctl برچسبهای زمانی را در منطقه زمانی سیستم فرمت میکند و journalctl --utc آن را مجبور به استفاده از UTC میکند. وجود دو سرور در دو منطقه زمانی مختلف، هر حادثه را به یک تمرین تبدیل واحد تبدیل میکند و تبدیلهایی که تحت فشار انجام میشوند، عامل اصلی اشتباه در خواندن خط زمانی هستند. سیستمها را روی UTC نگه دارید، برچسبهای زمانی را در UTC ذخیره کنید و تبدیل را فقط در نقطهای انجام دهید که یک انسان آنها را میخواند. هر کسی که برای یک دستور خاص به زمان محلی نیاز دارد، میتواند بدون تغییر تنظیمات ماشین، آن را درخواست کند:
TZ=Europe/Berlin dateیک خط دیگر در خروجی timedatectl به این بخش مربوط میشود. RTC in local TZ باید به صورت no خوانده شود. تنظیم آن روی yes یک راهکار موقت برای سیستمهای dual-boot با ویندوز روی لپتاپ است و در سرور، فقط یک اختلاف زمانی (offset) ایجاد میکند که بعداً باعث دردسر خواهد شد. وقتی این گزینه تنظیم شده باشد، timedatectl هشداری چاپ میکند مبنی بر اینکه سیستم برای خواندن زمان RTC در منطقه زمانی محلی پیکربندی شده است.
عیبیابی بر اساس علائم
کد احراز هویت دو مرحلهای شما در یک سرور رد میشود. پیش از هر اقدامی، ساعت سیستم را بررسی کنید. این کد از شمارندهای تولید میشود که هر 30 ثانیه تغییر میکند؛ بنابراین اگر ساعت سرور 90 ثانیه عقب باشد، کدی را محاسبه میکند که گوشی شما قبلاً از آن عبور کرده است. timedatectl مقدار System clock synchronized: no را نشان میدهد یا chronyc tracking یک offset بزرگ در System time گزارش میکند. این خطا با رد شدن کلید (key) متفاوت است؛ رد شدن کلید پیام خاص خود را دارد و در راهنمای خطاهای احراز هویت publickey پوشش داده شده است.
apt update میگوید فایل Release هنوز معتبر نیست. پیام کامل، نام مخزن (repository) و مدت زمانی که تا معتبر شدن باقی مانده را ذکر میکند، برای مثال is not valid yet (invalid for another 1d 2h 3min 4s). ساعت شما از تاریخی که در فایل Release مخزن درج شده عقبتر است و آن مدت زمان، دقیقاً نشاندهنده میزان عقب بودن ساعت شماست. ساعت را اصلاح کنید. بررسی تاریخ در apt را غیرفعال نکنید، زیرا این بررسی مانع از آن میشود که کسی فهرست بستههای قدیمی (stale) را به شما ارائه دهد.
تمام خطوط منبع وضعیت unreachable را نشان میدهند و Reach برابر 0 است. هیچ پاسخی دریافت نمیشود، بنابراین به جای پیکربندی، خروجی شبکه (egress) را بررسی کنید. پروتکل NTP از پورت UDP 123 برای خروجی استفاده میکند و برخی شبکهها آن را فیلتر یا هدایت میکنند. sudo chronyc ntpdata شمارندههای هر منبع از جمله Total TX و Total RX را چاپ میکند. اگر تعداد TX افزایش مییابد اما RX روی صفر باقی میماند، به این معنی است که بستههای شما خارج میشوند اما پاسخی دریافت نمیشود؛ این موضوع نشاندهنده وجود یک فایروال بین شما و منبع است.
ساعت درست بود، اما ناگهان تغییر کرد. رویدادهای میزبان (host) باعث این اتفاق میشوند. بازگردانی یک snapshot، متوقف کردن یک guest یا مهاجرت زنده (live migration) به یک میزبان دیگر میتواند باعث شود زمان در guest از زمان واقعی عقب بماند. chrony در نظرسنجی (poll) بعدی متوجه شده و اصلاح میکند؛ اما systemd-timesyncd ممکن است ابتدا منتظر یک بازه طولانی نظرسنجی بماند. با استفاده از systemctl is-enabled chrony تأیید کنید که daemon در زمان بوت شروع میشود، زیرا daemonای که بهصورت دستی اجرا شده باشد، پس از reboot بعدی از بین میرود.
میزان offset کوچک است اما هرگز ثابت نمیشود. CPU steal را بررسی کنید. guestای که در زمان سررسید وقفه تایمر (timer interrupt) زمانبندی نشده باشد، نمونهگیریاش با تأخیر مواجه میشود و در نتیجه offset به جای همگرا شدن، نوسان میکند. top این مورد را به عنوان مقدار st در خط CPU نشان میدهد. خواندن زمان CPU steal در یک میزبان اشتراکی توضیح میدهد که این عدد به چه معناست و چه کاری میتوانید در مورد آن انجام دهید.
گواهیای که بهتازگی صادر کردهاید به دلیل معتبر نبودن رد میشود. curl مقدار SSL certificate problem: certificate is not yet valid را چاپ میکند و مرورگرها نیز پیام مشابهی میدهند. گواهی مشکلی ندارد؛ ساعتی که آن را بررسی میکند عقب است. هر کدام از دو دستگاه میتوانند مقصر باشند، بنابراین کلاینت و سرور را بررسی کنید. اگر سروری که گواهی را صادر کرده همان سروری است که ساعت اشتباه دارد، راهنمای گواهی certbot و nginx بخش تمدید در همین سناریو را پوشش میدهد.
آن را به بررسیهایی که از قبل انجام میدهید اضافه کنید
همگامسازی زمان (Time sync) تنظیمی است که در زمان بوت اعمال میشود اما ممکن است ماهها بعد بیسروصدا از کار بیفتد؛ این دقیقاً همان موردی است که یک بررسی روتین آن را شناسایی میکند، اما حافظه انسان از آن غافل میماند. خواندن timedatectl و chronyc tracking با هم تنها دو ثانیه زمان میبرد. آنها را به عنوان بخشی از ده دقیقه اول روی یک VPS جدید اجرا کنید و دوباره هنگام کار با چکلیست نگهداری منظم سرور لینوکس آنها را بررسی نمایید. اگر ترجیح میدهید این بررسی بهصورت خودکار انجام شود و در صورت افزایش اختلاف زمانی هشدار دهد، نوشتن یک سرویس و تایمر systemd الگوی مربوط به یک unit کوچک را توضیح میدهد که طبق زمانبندی گزارش میدهد. چنین بررسیای بیشتر یک اسکریپت کوتاه است تا یک daemon، بنابراین به جای مقدار پیشفرض، به Type=oneshot نیاز دارد و بررسی انواع سرویسهای systemd توضیح میدهد که چرا انتخاب نوع اشتباه باعث میشود unit گزارشی از موفقیت ارائه دهد که هرگز به آن دست نیافته است.
FAQ
چگونه متوجه شوم که ساعت VPS من همگام است؟
دستور timedatectl را اجرا کرده و خط System clock synchronized را بخوانید. این خط نشاندهنده پرچم داخلی کرنل است که توسط دیمونی که وظیفه تنظیم ساعت را بر عهده دارد، مقداردهی میشود؛ بنابراین مشاهده yes در کنار NTP service: n/a در سیستمی که از chrony استفاده میکند، عادی و نشاندهنده وضعیت سالم است. برای مشاهده میزان خطا، دستور chronyc tracking را اجرا کرده و System time را بررسی کنید، یا اگر systemd-timesyncd مسئولیت زمان را بر عهده دارد، دستور timedatectl timesync-status را اجرا کرده و Offset را بخوانید. برای بررسی ساعت در مقایسه با یک منبع خارجی، مقدار date -u را با هدر Date که توسط هر سایت HTTPS بازگردانده میشود، مقایسه کنید.
آیا باید از chrony استفاده کنم یا systemd-timesyncd روی VPS؟
برای هر سروری که اهمیت دارد از chrony استفاده کنید. ابزار systemd-timesyncd یک کلاینت SNTP است که تنها از یک سرور پیروی میکند و برای ماشینی که همیشه آنلاین است و از ابتدا زمان نسبتاً دقیقی دارد، مناسب است. ابزار chrony چندین منبع را بررسی میکند، منابع نامعتبر را رد میکند، خطای نرخ ساعت شما را یاد میگیرد و پس از توقف میزبان یا مهاجرت زنده (live migration) بهسرعت بازیابی میشود. نصب chrony روی Debian یا Ubuntu بهطور خودکار systemd-timesyncd را حذف میکند، زیرا هر دو بسته time-daemon را ارائه میدهند. هرگز دو دیمون زمان را بهطور همزمان اجرا نکنید.
چرا کدهای TOTP من روی یک سرور کار نمیکنند اما در جاهای دیگر درست هستند؟
زیرا کد TOTP تابعی از زمان فعلی است. این کد از شمارندهای میآید که هر 30 ثانیه تغییر میکند، بنابراین سرور و گوشی شما باید روی گام زمانی فعلی توافق داشته باشند. اکثر تأییدکنندهها یک گام اختلاف در هر دو جهت را میپذیرند که حدود نیم دقیقه تلورانس ایجاد میکند. دستور timedatectl را روی آن سرور بررسی کنید. اگر خروجی System clock synchronized برابر با no باشد، همگامسازی را اصلاح کنید تا کدها بدون نیاز به تغییر در secret مشترک، دوباره مطابقت پیدا کنند.
آیا میتوانم زمان را داخل یک کانتینر Docker تنظیم کنم؟
خیر، و نیازی هم به این کار ندارید. یک کانتینر از CLOCK_REALTIME میزبان استفاده میکند، زیرا فضای نام زمان در لینوکس فقط ساعتهای monotonic و boot-time را مجازیسازی میکند. یک کانتینر بدون امتیاز (unprivileged) مقدار date: cannot set date: Operation not permitted را دریافت میکند و افزودن CAP_SYS_TIME به آن اجازه میدهد ساعت میزبان را تغییر دهد، نه اینکه ساعت مستقلی برای خود داشته باشد. میزبان را همگامسازی کنید. تفاوت زمان محلی داخل کانتینر مربوط به تنظیمات منطقه زمانی است، بنابراین TZ را در محیط کانتینر تنظیم کنید.
آیا سرور باید از UTC استفاده کند یا زمان محلی؟
از UTC استفاده کنید و زمان محلی را فقط در لحظهای که کاربر خروجی را میخواند اعمال کنید. زمان UTC هرگز به دلیل تغییرات ساعت تابستانی تغییر نمیکند، بنابراین یک وظیفه روزانه (daily job) در تمام طول سال دقیقاً یکبار اجرا میشود و زمانبندیهای سرورهای مختلف بدون نیاز به تبدیل، با هم هماهنگ میمانند. آن را با sudo timedatectl set-timezone UTC تنظیم کنید. هر کسی که نیاز به مشاهده زمان محلی دارد، میتواند پیشوند یک دستور را تغییر دهد؛ برای مثال TZ=America/New_York date، که هیچ تغییری در ساعت سیستم ایجاد نمیکند.