Saat kayması ve proxy üzerinden hatalar: TLS, JWT, istek imzaları ve bir dakikada teşhis
Makale içeriği
- Giriş: «dün çalışıyordu, bugün sertifika geçersiz»
- Temeller: saat nerede kritik ve protokoller saate neden bakar
- Derinlemesine bakış: istemci — proxy — sunucu zincirinde kimin saati önemli
- Hata farklı istemcilerde nasıl görünür: ilk satırdan tanınması gereken metinler
- Saat neden kayar: sanallaştırma, konteynerler, servis yokluğu, elle düzeltme
- Bir dakikada teşhis: dış kaynakla karşılaştırma ve kabul edilebilir sapma
- Senkronizasyon yapılandırması: systemd-timesyncd ve chrony, ve gerçekten çalıştığından nasıl emin olunur
- Konteynerler ve saat: ana makineden ne miras alınır, ne alınmaz
- Sık yapılan hatalar ve pratikten vakalar
- Araçlar ve «proxy'yi suçlamadan önce» kontrol listesi
- Sss: zaman, proxy ve arızalar hakkında sık sorulan sorular
- Sonuç: teşhisin ilk maddesi olarak zaman
Giriş: «Dün çalışıyordu, bugün sertifika geçersiz»
Öyle bir arıza sınıfı vardır ki, herkesten iyi kamufle olur. Aylardır proxy üzerinden onlarca API'ye giden bir betik aniden her istekte patlamaya başlar. Logda certificate has expired ya da certificate is not yet valid yazar. Mühendis kendi dizüstünde tarayıcıdan hedef sitenin sertifikasını açar: geçerlilik tarihi yerinde, güven zinciri yeşil. Betiği dizüstünden proxy olmadan yeniden çalıştırır — çalışır. Proxy'yi geri koyar — yine hata. Çıkarım kendini dayatır: suçlu proxy.
Ve bu çıkarım neredeyse her zaman yanlıştır. Mesele proxy'nin «sertifikayı değiştirmesi» ya da «TLS'i bozması» değildir. Mesele betiğin başka bir makinede — bir sunucuda, sanal makinede, konteynerde — çalışıyor olması ve o makinenin sistem saatinin kaymış olmasıdır. Birkaç dakika, saat ya da gün. Proxy denklem içinde sadece en göze çarpan değişken oldu ve darbeyi üstlendi.
Bu konuyu bütünüyle ele alacağız. Modern protokollerin tam olarak nerelerde güncel saate dayandığını ve saat kaymasının farklı yönlerde neden farklı belirtiler verdiğini öğreneceksiniz. curl, Python ve Node.js'teki somut hata metinlerini görerek sorunu trace'in ilk satırından tanıyacaksınız. Saatin neden özellikle sanal makinelerde ve konteynerlerde kaydığını ve kurulu bir senkronizasyon servisinin çalıştığını garanti etmediğini anlayacaksınız. Bir dakikalık teşhis prosedürü, çalışan chrony ve systemd-timesyncd yapılandırmaları ve proxy sağlayıcınıza yazmadan önce geçmeniz gereken bir kontrol listesi edineceksiniz.
Baştan sınırları çizelim. Bu yazı sertifika düzenleme, güven zincirleri ya da kök sertifika depolarıyla ilgili değil. Tek bir arıza nedenini — yanlış sistem saatini — ve proxy üzerinden çalışırken bundan doğan her şeyi inceliyoruz. Dar bir konu, ama entegrasyon, izleme, açık veri toplama ve Proxeon gibi proxy altyapıları üzerinden otomasyonla uğraşan ekiplerin saatlerini yakan tam da bu.
Temeller: saat nerede kritik ve protokoller saate neden bakar
Basit bir soruyla başlayalım. Ağ protokolleri saatin kaç olduğunu neden bilmek ister? Cevap tek: güvenin ömrünü sınırlamak için. Her sır — sertifika, token, imza, tek kullanımlık kod — eninde sonunda sızabilir. Bir son kullanma tarihi varsa, sızıntıdan doğan zarar sınırlıdır. Ama süre sınırlaması ancak doğrulayan taraf güncel saati biliyorsa işe yarar. Ve o saati tek bir yerden alır: doğrulamanın yapıldığı makinenin sistem saatinden.
Buradan temel bir sonuç çıkar: her saat kontrolü yereldir. Sunucu istemciye saatin kaç olduğunu sormaz. İstemci sunucuya sormaz. Her biri kendi saatine bakar ve bir sonuca varır. İki tarafın saati ayrılırsa, farklı bir gerçeklik görürler ve biri diğerini ihlalci sayar.
TLS'te sertifika geçerlilik süresi kontrolü
Her X.509 sertifikası iki alan içerir: notBefore (geçerli olduğu başlangıç) ve notAfter (geçerli olduğu bitiş). TLS el sıkışmasında istemci kendi saatinden güncel zamanı bu aralıkla karşılaştırır. Sertifikanın sunucu tarafından düzenlendiği an burada devreye girmez — önemli olan yalnızca istemcinin güncel zaman hakkında ne düşündüğüdür.
Kaymanın yönü belirtiyi belirler. İstemcinin saati gerideyse, yeni düzenlenmiş sertifikalar sanki henüz düzenlenmemiş gibi görünür: «certificate is not yet valid» hatası. İstemcinin saati ileriyse, sertifikalar süresi dolmuş gibi görünür: «certificate has expired». Bu, akılda tutulması gereken ilk teşhis işaretidir.
Bu konu neden tam da şimdi keskinleşti? Çünkü sertifikalar kısa ömürlü oluyor. Birçok kamu sertifika merkezi 90 günlük sertifika veriyor, 6 günlük seçenekler ortaya çıktı ve sektör gereksinimleri azami süreyi düzenli olarak kısaltıyor: Mart 2026'dan itibaren 200 gün, ardından 100 gün ve 2029'a kadar 47 gün. Eskiden iki hafta geride kalan bir saat neredeyse hiç taze bir sertifikaya denk gelmezdi. Şimdi hedef site sertifikasını birkaç günde bir yenileyebiliyor ve üç gün geride kalan bir makine onu «henüz geçerli değil» diye reddedecek.
Aynı gruba ilgili mekanizmalar da girer: OCSP yanıtlarının ve iptal listelerinin kendi geçerlilik pencereleri vardır, Certificate Transparency kayıtları zaman damgaları taşır ve TLS 1.3 oturum biletleri sınırlı süre yaşar. Hepsi yerel saate göre kontrol edilir.
JWT: exp, nbf ve iat alanları
JSON Web Token — API'lerde en yaygın erişim token'ı formatıdır. Gövdesinde Unix epoch biçiminde üç zaman alanı bulunur: iat (veriliş zamanı), nbf (not before — hangi andan itibaren geçerli) ve exp (ne zaman doluyor). Token'ı kabul eden taraf, bunları kendi saatiyle, genellikle 30-60 saniyelik küçük bir toleransla (leeway) karşılaştırır.
Burada ilginç bir asimetri ortaya çıkar. Genelde token'ı sunucu kendi saatine göre verir, istemci ise exp anına kadar önbelleğe alır — ama artık kendi saatine göre. İstemci beş dakika gerideyse, sunucu token'ı reddetmeye başladıktan sonra beş dakika daha onu geçerli sayar. Her token'ın ömrünün sonunda açıklanamayan 401'ler alırsınız. İstemci JWT'yi kendisi imzalıyorsa — örneğin servis hesabı kimlik doğrulaması için — ve saati ileriyse, sunucu iat'ı gelecekte görür ve token'ı henüz geçerli değil diye reddeder.
Zaman damgalı istek imzaları
Birçok API, isteği HMAC ile imzalamanızı ve imzalanan dizeye güncel zamanı eklemenizi ister. En bilinen örnek, S3 uyumlu nesne depolarının kullandığı Signature Version 4 şemasıdır. Sunucu, isteğin zaman damgası kendi saatinden 15 dakikadan fazla farklıysa isteği kabul etmez; aksi halde RequestTimeTooSkewed hatasını döndürür. Ödeme ağ geçitleri, borsa ve broker API'leri, kurumsal veri veriyolları 30 saniyeden birkaç dakikaya kadar değişen pencerelerle benzer şemalar kullanır. Kurumsal ağlarda Kerberos kimlik doğrulaması varsayılan olarak 5 dakikalık sapmaya izin verir.
Dikkat edin: imzayı istemciniz kendi saatine göre oluşturur. Proxy bu süreçte fiziksel olarak yer almaz — yalnızca baytları taşır. Dolayısıyla proxy üzerinden «imzada geçersiz zaman damgası» hatası her zaman makinenizin saatine dair bir sorudur.
Tek kullanımlık TOTP kodları
TOTP standardındaki iki faktörlü kimlik doğrulama kodları, paylaşılan bir sırdan ve 30 saniyelik aralık numarasından hesaplanır. Doğrulayan taraf genellikle artı-eksi bir aralığa izin verir. Saatiniz bir dakika kaydıysa kodlar tamamen kabul edilmemeye başlar. Bu, servis hesabının kurumsal portala giriş yapmak için programatik olarak TOTP ürettiği kendi entegrasyonlarınız için de geçerlidir.
Daha az belirgin zaman tüketicileri
- HTTP önbellekleme. Date, Expires ve max-age başlıkları yerel saatle karşılaştırılır; kaymada önbellek ya çalışmaz ya da bayat içerik verir.
- Expires'lı çerezler. Geride kalan saatli istemci onları daha uzun tutar, ileri kalan ise hemen atar.
- HSTS ve pinning. max-age direktifleri de yerel olarak hesaplanır.
- Kümeler içindeki sertifika rotasyonu. Orkestratör bileşenleri zamanlamaya göre sertifika yeniler ve düğümdeki saat kaydığında birbirlerine güvenmez hale gelir.
Derinlemesine bakış: istemci — proxy — sunucu zincirinde kimin saati önemli
Şimdi bu tabloyu gerçek topolojiye oturtalım. Proxy üzerinden çalışırken zincirde en az üç makine ve üç saat kümesi vardır: istemciniz, proxy sunucusu ve hedef sunucu. Teşhisin kilit sorusu şudur: patlayan kontrol bunlardan hangisinde yapılıyor?
HTTP CONNECT ve SOCKS5: proxy TLS'i görmez
HTTP proxy üzerinden HTTPS kaynağına istekte istemci, ana makine adı ve port ile bir CONNECT komutu gönderir. Proxy hedefle TCP bağlantısı kurar ve ardından iki yönde baytları kör bir şekilde aktarır. TLS el sıkışması proxy'nin üzerinden, istemcinizle hedef sunucu arasında gerçekleşir. Proxy sertifikayı görmez, değiştiremez ve doğrulamaya katılmaz. Aynısı SOCKS5 için de geçerlidir.
Pratik sonuç: şeffaf tünel üzerinden çalışırken «certificate is not yet valid» ya da «certificate has expired» hatasına proxy neden olamaz. Kaynak ya makinenizin saatidir, ya oradaki güvenilir kök deposudur, ya da hedefte gerçekten süresi dolmuş bir sertifikadır. İlk iki seçenek yereldir. Ve ilki on saniyede kontrol edilir.
Daha fazla saatin kontrol edildiği durum: proxy'nin kendisine kadar TLS
Proxy'ye güvenli bir kanaldan bağlanıyorsanız (proxy'nin kendisi için https:// şeması), istemci iki sertifika doğrular: proxy sunucusunun sertifikası ve hedef sitenin sertifikası. Her iki kontrol de istemcinin saatiyle yapılır. Belirtiler aynıdır, ancak ayrıntılı curl çıktısında hatanın hangi aşamada — «Proxy certificate» yoksa «Server certificate» — olduğu görülür.
Proxy'nin kendi saatine bağlı olanlar
Proxy sunucusunun saati sınırlı bir dizi şeyi etkiler: kendi loglarının doğruluğu, kendi TLS dinleyicisinin çalışması (örneğin OCSP yanıtları alması) ve sağlayıcı süre sınırlı token'lar kullanıyorsa yetkilendirme verilerinin kontrolü. Proxeon altyapısı düğümlerindeki saati standart olarak senkronize eder ve olayların ezici çoğunluğunda proxy'nin saati konu dışıdır: ne hedef sertifikasının kontrolüne, ne imzalarınızın oluşturulmasına, ne de JWT'lerinizin doğrulanmasına katılır. Bunların hepsini istemci ve hedef sunucu yapar.
Hedef sunucunun saati
Nadiren saat karşı tarafta kayar. Belirti: hatalar yalnızca tek bir ana makineyle ortaya çıkar, diğerlerine erişim normaldir; o ana makinenin yanıtındaki Date başlığı diğer sunucularınkinden belirgin biçimde farklıdır. Bunun için yapabileceğiniz bir şey yoktur; sahibine bildirmek ve API izin veriyorsa isteklerinizde kaymayı telafi etmek dışında — bazı kütüphaneler hatalı yanıttaki Date başlığından düzeltmeyi hesaplayıp sonraki isteği sapmayı hesaba katarak imzalayabilir.
Gecikme ve «kuyrukta bayatlama»
Proxy gecikme ekler — onlarca milisaniyeden mobil kanal yeniden bağlanmaları ve IP rotasyonunda saniyelere kadar. 15 dakikalık pencere için bu ihmal edilebilir. Ama yeniden deneme mantığında ince bir tuzak var. İsteği imzalayıp kuyruğa koyar ve bir dizi bekleme ile yeniden denemeden sonra gönderirseniz, imzadaki zaman damgası bayatlar. Yavaş ya da yüklü bir kanalda bu daha sık olur. Kural: göndermeden hemen önce imzalayın ve her yeniden denemede yeniden imzalayın, hazır imzalı nesneyi yeniden kullanmayın.
Sapma: büyüklük ve yön
Belirtinin sapmaya bağımlılığını tek bir liste-tabloda toplayalım — log okurken işe yarar:
- İstemci saati geride: «certificate is not yet valid», kendi imzalamada nbf ya da iat hatası olan JWT, kendi önbelleğe aldığınız token'lar canlı görünür ama sunucu 401 «expired» der, imzalar çok eski diye reddedilir, TOTP kabul edilmez.
- İstemci saati ileride: «certificate has expired», kendi JWT'leriniz iat gelecekte diye reddedilir, imzalar «gelecekten» diye reddedilir, token'lar süresinden önce önbellekten düşer, TOTP kabul edilmez.
- Sapma bir saniyeden az: Sıralanan mekanizmaların hiçbiri fark etmez.
- Sapma 30 saniye — 5 dakika: TOTP, küçük leeway'li JWT ve katı HMAC şemaları bozulur.
- Sapma 15 dakikadan fazla: Neredeyse tüm istek imzaları ve Kerberos bozulur.
- Sapma günlerce: Kısa ömürlü sertifikalı sitelere TLS bağlantıları çökmeye başlar.
Hata farklı istemcilerde nasıl görünür: ilk satırdan tanınması gereken metinler
Sorunu hata metninden tanımak, herhangi bir metodolojiden daha fazla zaman kazandırır. Aşağıda popüler istemcilerin karakteristik ifadeleri var. Altında OpenSSL olan kütüphanelerin yazdırdığı biçimde verilmiştir; parantez içindeki satır numaraları sürümden sürüme değişir.
curl
Yanlış saatteki temel mesajlar:
curl: (60) SSL certificate problem: certificate is not yet validcurl: (60) SSL certificate problem: certificate has expired60 kodu CURLE_PEER_FAILED_VERIFICATION'dır, tüm sertifika doğrulama sorunları için ortaktır. Zamana bağlı nedeni kök sertifika sorunundan ancak iki noktadan sonraki metinden ayırt edebilirsiniz. -v bayrağıyla OpenSSL'in sayısal doğrulama kodunu içeren faydalı bir satır görünür: 9 «not yet valid», 10 ise «has expired» anlamına gelir:
* SSL certificate verify result: certificate is not yet valid (9), continuing anyway.«continuing anyway» satırı yalnızca -k bayrağında görünür; onsuz bağlantı koparılır. Schannel arka uçlu Windows'ta metin farklıdır:
curl: (60) schannel: SEC_E_CERT_EXPIRED (0x80090328) - The received certificate has expired.Hem aşamayı (proxy mi hedef mi) hem de doğrulama sonucunu görmek için proxy üzerinden ayrıntılı çıktıyla tam kontrol örneği:
curl -v --proxy http://LOGIN:PASSWORD@PROXY_HOST:PORT https://example.com/ 2>&1 | grep -iE 'verify|expire|valid|date'Python: ssl, requests, httpx, aiohttp
Standart ssl modülü konuşkan bir son eki olan istisna fırlatır:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate is not yet valid (_ssl.c:1010)requests kütüphanesi bunu SSLError içine sarar ve bağlantı havuzu sarmalayıcısı ekler, bu yüzden anahtar kelimeler uzun dizenin en sonunda kalır:
requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1010)')))Proxy üzerinden çalışmak için önemli bir ayrıntı: CONNECT tünelinde hedef sertifikasının doğrulama hatası ProxyError değil, tam olarak SSLError olarak gelir. ProxyError, proxy'nin kendisiyle bağlantı kurulamadığında ortaya çıkar. Yani istisna türü bile nerede arayacağınızı söyler.
httpx daha kısa ifade eder:
httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1010)aiohttp — kendi sınıfıyla:
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host example.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate is not yet valid (_ssl.c:1010)')]Token'ı kendi tarafınızda kontrol ederken PyJWT'deki JWT hataları:
jwt.exceptions.ExpiredSignatureError: Signature has expiredjwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)İşte proxy üzerinden elinizin altında test senaryosu olarak tutmanız gereken asgari yeniden üretilebilir örnek:
import requests, ssl, sys
PROXY = "http://LOGIN:PASSWORD@PROXY_HOST:PORT"
try:
r = requests.get("https://example.com/", proxies={"https": PROXY}, timeout=15)
print(r.status_code, r.headers.get("Date"))
except requests.exceptions.SSLError as e:
msg = str(e)
if "not yet valid" in msg or "has expired" in msg:
print("Похоже на сдвиг системных часов, проверьте date -u")
print(msg)Küçük bir açıklama: bu ve sonraki örneklerde satır kaydırma karakteri, işaretlemenin tek satır kalması için HTML varlığı olarak gösterilmiştir; editöre kopyaladığınızda normal satır sonuna dönüşecektir.
Node.js: https, fetch, undici
Node kısa mesajlar yazdırır ve değerli olarak hataya code alanı ekler:
Error: certificate is not yet valid
code: 'CERT_NOT_YET_VALID'Error: certificate has expired
code: 'CERT_HAS_EXPIRED'Dahili fetch'in tuzağı: dışarıdan yalnızca TypeError: fetch failed görürsünüz, gerçek neden cause özelliğinde saklıdır. Açıkça loglayın:
try {
const res = await fetch("https://example.com/");
console.log(res.status, res.headers.get("date"));
} catch (e) {
console.error(e.message, e.cause && e.cause.code, e.cause && e.cause.message);
}Node'da fetch'i proxy üzerinden yönlendirmek için undici paketindeki ProxyAgent kullanılır. Hedef sertifikasının hatası yine cause içinde CERT_HAS_EXPIRED ya da CERT_NOT_YET_VALID koduyla gelir. Klasik https modülü ve axios gibi kütüphanelerde https-proxy-agent paketindeki ajan kullanılır — hata kodları aynıdır, çünkü onları Node içindeki aynı OpenSSL üretir.
jsonwebtoken kütüphanesi token doğrularken iki zaman durumunu ayırt eder:
TokenExpiredError: jwt expired
NotBeforeError: jwt not activeİmzalarda sunucu tarafı hatalar
Burada metni API belirler ama tipik ifadeler tanınabilir. S3 uyumlu depolarda:
<Code>RequestTimeTooSkewed</Code>
<Message>The difference between the request time and the current time is too large.</Message>OAuth sunucularında — error="invalid_token" ile WWW-Authenticate başlığı ve «The token expired» ya da «Token used before issued» tarzı açıklama. Finansal API'lerde — timestamp outside of recvWindow ya da «Timestamp for this request is outside of the allowed window» mesajları. Bu ifadelerden herhangi birini görüyorsanız ilk kontrol edilmesi gereken şey saattir.
Saat neden kayar: sanallaştırma, konteynerler, servis yokluğu, elle düzeltme
Anakartın kuvars osilatörü referans değildir. Tipik hata payı 10-100 ppm'dir, yani düzeltmesiz günde 1-9 saniye sapma. Senkronizasyonsuz bir ayda dakikalar birikir. Bu, her makinede olan arka plandır. Ama olayların çoğu yavaş sapmadan değil sıçramalardan kaynaklanır. Kaynakları inceleyelim.
Sanal makineler: duraklama, snapshot, göç
Sanal makine fiziksel saate sahip değildir. Zamanı paravirtual bir kaynaktan alır (kvm-clock, Hyper-V reference time, diğer hipervizörlerde eşdeğerleri). Konuk duraklatıldığında, snapshot'a kaydedildiğinde ya da ana makineler arasında göç ettiğinde iç saati «donar». Yeniden başlatıldıktan sonra çekirdek hipervizörden düzeltme alır ya da almaz — konuk ajanlarının ayarlarına bağlı. Klasik senaryo: ekip bir test sunucusunu iki hafta önceki snapshot'a geri aldı ve makine 14 gün geride bir saatle uyandı. Bu iki haftada düzenlenen tüm sertifikalar onun için «henüz geçerli değil».
Ayrı bir dert de iki doğruluk kaynağının çatışması. Hipervizörün konuk ajanı periyodik olarak saati ana makineye «çeker», konuk içinde ise kendi NTP servisi çalışır. Ana makine senkronize değilse konuk iki çelişkili sinyal alır ve saati ileri geri zıplayabilir. Sanallaştırma kılavuzlarının çoğunun önerisi: ya hipervizörden senkronizasyon ya da içeride NTP, ama ikisi birlikte değil.
Geliştirici dizüstüleri: uyku ve masaüstü sanal makineleri
Docker Desktop ve WSL2 hafif bir sanal makine içinde çalışır. Dizüstünün uykusundan ya da hazırda bekletmesinden sonra bu VM'in saati genellikle tam uyku süresi kadar — bir saat, bir gece, bir hafta sonu — geride kalır. Ana işletim sistemi saati düzeltir ama sanal makine her zaman değil. Sonuç: pazartesi sabahı konteynerlerdeki tüm betikler TLS'te patlar, terminalde ise her şey yolundadır. Çoğu zaman «dizüstünden proxy olmadan çalışıyor, konteynerde proxy üzerinden çalışmıyor» şikayetini doğuran tam da bu durumdur — oysa proxy her iki durumda da kontrole hiç katılmamış olabilir.
Konteynerler
Konteynerin kendi gerçek zamanlı saati yoktur — ana makinenin saatini kullanır. Bunu ayrı bir başlıkta ayrıntılı ele alacağız; burada ana olanı saptayalım: ana makine kaydıysa tüm konteynerler kaymıştır ve bu konteynerin içinden düzeltilemez.
Senkronizasyon servisinin yokluğu ya da çalışmaması
Minimal imajlar, «çıplak» kurulumlar ve kendi derlenmiş sistemler çoğu zaman NTP istemcisi olmadan gelir. Var olduğu yerlerde ise onlarca nedenden çalışmayabilir: giden UDP 123 portu güvenlik duvarıyla kapalıdır; havuz adları çözümlenmiyor; servis kurulu ama maskelenmiş; chrony ve timesyncd aynı anda kurulu ve birbirini engelliyor; başlangıçtaki sapma klasik ntpd'nin düzeltmeyi reddedip kapanmasına neden olan eşiği aştı. Özellikle internete tek çıkışı kurumsal ağın HTTP proxy'si olan sunucular savunmasızdır: böyle bir proxy üzerinden UDP ile NTP geçmez ve saat kendi başına kalır.
RTC yokluğu ve bitmiş pil
Raspberry Pi gibi tek kartlı bilgisayarların ve birçok mini PC'nin pille çalışan donanım saati yoktur. Açılışta ya epoch'tan ya da son kaydettikleri tarihten başlarlar ve ilk başarılı senkronizasyona kadar böyle yaşarlar. Eski sunucularda CMOS pili biter ve her kapanışta BIOS tarihi fabrika değerine sıfırlar. Senkronizasyon erişilemezse makine on yıl önceki bir tarihle çalışır ve her TLS bağlantısı mahkûmdur.
Elle düzeltme ve saat dilimi karışıklığı
«Hipotezi test etmek için» çalıştırılıp unutulan date -s komutu sık rastlanan bir olaydır. Bir diğeri de aynı makinede Windows ve Linux çift önyükleme: Windows donanım saatinde yerel zamanı tutar, Linux varsayılan olarak UTC bekler ve her yeniden başlatmada diğer işletim sistemine geçişte saat zaman dilimi kadar, Moskova saati için üç saat kayar. Son olarak zaman ile saat dilimi karışıklığı: TZ değişkenini ya da /etc/localtime dosyasını değiştirmek gösterimi değiştirir, sistem saatini değiştirmez. Yalnızca UTC karşılaştırılmalıdır.
Bir dakikada teşhis: dış kaynakla karşılaştırma ve kabul edilebilir sapma
Bu prosedürün amacı 60 saniyede tek bir soruya cevap vermektir: proxy üzerinden isteklerin çalıştırıldığı makinede saat doğru mu yürüyor? Tüm komutlar istemcinin patladığı makinede ya da tam o konteynerde, dizüstünüzde değil, çalıştırılır.
Adım 1. UTC'ye bakın ve herhangi bir güvenilir kaynakla karşılaştırın
date -uOperatörle senkronize telefonunuzun saatiyle karşılaştırın. Dakikalarca fark hemen görülür. Saniyeler için aşağıdaki adımlar gerekir.
Adım 2. Aynı proxy üzerinden HTTP Date başlığından zamanı alın
Her doğru çalışan HTTP sunucusu Date başlığını kendi (genellikle senkronize) saatine göre verir. İnce nokta: isteği HTTPS değil normal HTTP ile yapın, çünkü büyük sapmada TLS kurulmaz ve başlığı hiç alamazsınız:
date -u; curl -sI --proxy http://LOGIN:PASSWORD@PROXY_HOST:PORT http://example.com/ | grep -i '^date'İki satır bir-iki saniyelik doğrulukla örtüşmelidir (başlık saniye düzeyindedir, artı kanal gecikmesi). Bir dakika ve üzeri fark gördüyseniz tanı hazır. Bu yöntem UDP gerektirmemesi, her proxy üzerinden çalışması ve TLS'e bağlı olmamasıyla özellikle değerlidir.
Aynı yöntemin Python'da hali — Proxeon ya da başka bir proxy üzerinden giden servisin healthcheck'ine gömmek için kullanışlıdır:
import email.utils, time, requests
PROXY = "http://LOGIN:PASSWORD@PROXY_HOST:PORT"
r = requests.head("http://example.com/", proxies={"http": PROXY}, timeout=10)
server_ts = email.utils.parsedate_to_datetime(r.headers["Date"]).timestamp()
skew = time.time() - server_ts
print(f"Смещение локальных часов: {skew:+.1f} с")
if abs(skew) > 30:
raise SystemExit("Часы уехали, синхронизация обязательна")Adım 3. Sisteme kendini senkronize sayıp saymadığını sorun
timedatectlİki satır arayın: «System clock synchronized: yes» ve «NTP service: active». Herhangi bir «no» ya da «inactive» yapılandırma bölümüne gitme nedenidir. chrony kuruluysa:
chronyc tracking«System time» (sapmanın büyüklüğü ve işareti), «Stratum» (0 olmamalı) ve «Leap status» (Normal olmalı, «Not synchronised» değil) değerlerine bakın.
Adım 4. Saati değiştirmeden NTP sunucusuna tek seferlik sorgu
Dışarıya UDP açıksa sapmayı hiçbir şeyi değiştirmeden kesin ölçebilirsiniz:
chronyd -Q 'pool pool.ntp.org iburst'Ya da ntpdate kuruluysa:
ntpdate -q pool.ntp.orgÇıktı, işaretli saniye cinsinden offset'i gösterir.
Adım 5. TLS'i kıranın gerçekten saat olduğunu doğrulayın
openssl aracı HTTP proxy üzerinden gidebilir ve doğrulama sonucunu sayısal kodla yazdırır:
openssl s_client -connect example.com:443 -proxy PROXY_HOST:PORT -servername example.com </dev/null 2>/dev/null | grep 'Verify return code'Sertifika canlıyken «Verify return code: 9 (certificate is not yet valid)» ya da «10 (certificate has expired)» kesin kanıttır. Çoğu derlemede s_client proxy'de oturum açma kullanıcı adı ve parolasını desteklemez; bu kontrol için Proxeon'un desteklediği IP ile yetkilendirmeyi kullanmak uygundur. Sertifikanın kendi tarihlerini şöyle çıkarın:
openssl s_client -connect example.com:443 -proxy PROXY_HOST:PORT -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -datesHangi sapma normal sayılır
- 100 milisaniyeye kadar — NTP çalışan sağlıklı makine. Hiçbir şey yapmaya gerek yok.
- 100 ms — 1 saniye — tartışılan tüm protokoller için kabul edilebilir, ama kötü kaynağa ya da seyrek sorgulamaya işaret eder. Yapılandırmayı kontrol etmek gerekir.
- 1 — 30 saniye — sarı bölge. Geniş pencereli TLS ve imzalar hâlâ çalışır, küçük leeway'li TOTP ve JWT ise takılabilir. Bugün düzeltin.
- 30 saniyeden fazla — kırmızı bölge. Aksi kanıtlanana kadar her kimlik doğrulama ya da TLS hatasının saatten kaynaklandığını varsayın.
Sorunu bilerek yeniden üretme
Hata işlemenizin zaman kaynaklı arızayı doğru tanıdığından emin olmak için sistem saatine dokunmanız gerekmez. libfaketime kütüphanesi zamanı tek bir süreç için değiştirir:
faketime '2024-01-01 12:00:00' curl -sS https://example.com/ -o /dev/nullBelirtilen tarihten sonra düzenlenmiş sertifikaya sahip her site için «certificate is not yet valid» alırsınız. Ağsız sertifika kontrolü için OpenSSL, Unix zamanı alan -attime bayrağını destekler; CI'daki testlerde kullanışlıdır.
Senkronizasyon yapılandırması: systemd-timesyncd ve chrony, ve gerçekten çalıştığından nasıl emin olunur
Paket kurmak senkronizasyon değildir. Aşağıda iki çalışan şema ve daha da önemlisi doğrulama yöntemi var.
Seçim: timesyncd mi chrony mi
systemd-timesyncd — systemd ile gelen minimalist SNTP istemcisidir. Listeden tek bir sunucuyu sorgular, saati sıçramayla ve düzgün şekilde düzeltebilir, sunucu olarak çalışmaz, donanım kaynaklarını desteklemez. Onlarca milisaniye düzeyinde doğruluk gereken iş istasyonları ve kritik olmayan sunucular için yeterlidir.
chrony — NTP'nin tam uygulamasıdır. Birden çok kaynağı birleştirir, uzun kesintiden sonra hızla yakınsar, kesintili ağda düzgün davranır, NTS'yi (TLS ile kimlik doğrulanmış NTP) destekler, ağ içinde zaman dağıtabilir. Sunucular, sanal makineler ve imzalı isteklerle proxy işlerinin geçtiği tüm düğümler için varsayılan seçimdir.
Önemli: İki servisin aynı anda çalışması kaos kaynağıdır. chrony kurarken dağıtımlar genelde timesyncd'yi kapatır ama bunu açıkça kontrol edin.
Seçenek A: systemd-timesyncd
Yapılandırma /etc/systemd/timesyncd.conf dosyasında:
[Time]
NTP=ntp.your-provider.internal 0.pool.ntp.org 1.pool.ntp.org
FallbackNTP=2.pool.ntp.org 3.pool.ntp.org
PollIntervalMinSec=32
PollIntervalMaxSec=2048Etkinleştirme ve kontrol:
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd
timedatectl timesync-statustimesync-status çıktısında Server dolu olmalı, Stratum 0 olmamalı ve Offset alanı milisaniye cinsinden olmalı. Sunucu belirtilmemişse ya da «Packet count: 0» yazıyorsa NTP'den yanıt gelmiyor demektir — neredeyse kesin olarak UDP 123 kapalıdır.
Seçenek B: chrony
/etc/chrony/chrony.conf dosyası (bazı sistemlerde /etc/chrony.conf):
server ntp.your-provider.internal iburst prefer
pool pool.ntp.org iburst maxsources 4
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chronyKilit direktifleri inceleyelim, çünkü arıza durumundaki davranışı tam da onlar belirler:
- iburst — başlangıçta arka arkaya bir dizi istek gönderir ve dakikalar içinde değil saniyeler içinde senkronize olur.
- makestep 1.0 3 — sapma 1 saniyeden büyükse ilk üç güncellemede sıçramaya izin verilir, sonrasında yalnızca düzgün yaklaşım. Bu direktif olmadan snapshot ya da uykudan sonra chrony saati haftalarca «yakalamaya» çalışır. Sık uyuyan ya da göç eden sunucular için bazıları makestep 1.0 -1 koyup sıçramaya her zaman izin verir.
- rtcsync — periyodik olarak saati donanım saatine yazar, böylece yeniden başlatma sonrası yakın bir değerle başlar.
- Sağlayıcının iç sunucusu ilk sırada — bulut platformları genelde ağ içinde bir NTP adresi sunar; dış UDP kapalıyken bile erişilebilir ve gecikmesi en azdır. Adresi kendi sağlayıcınızın belgelerinden alın.
Başlatma:
sudo systemctl enable --now chrony
sudo chronyc makestep
chronyc tracking
chronyc sources -vSenkronizasyonun gerçekten çalıştığını nasıl anlarız
Bölümün en önemli kısmı burası. chrony'de çalışan senkronizasyonun işaretleri:
- chronyc tracking'de Reference ID sıfır değil ve tıpkı bir sunucu için Stratum 2-4 aralığında. Stratum 0 ya da boş Reference ID ile 10, «kendimle çalışıyorum» demektir.
- Leap status: Normal. «Not synchronised» değeri, saatin kimse tarafından düzeltilmediğini gösterir.
- System time, saniye değil milisaniye ya da mikrosaniye cinsinden sapma gösterir.
- chronyc sources'ta en az bir kaynak yıldızla (o an seçili) ya da artıyla (kombinasyona katılıyor) işaretli. Tüm kaynaklarda soru işareti varsa yanıt gelmiyor demektir; güvenlik duvarı ya da DNS arayın.
- Last offset ve RMS offset zamanla büyümek yerine azalıyor.
timesyncd için eşdeğer kontrol, timedatectl'de «System clock synchronized: yes» ve timesync-status'ta sıfırdan farklı Packet count'tur.
NTP güvenlik duvarıyla kapalıysa
Sunucuda yalnızca proxy üzerinden giden HTTP(S) izinliyse üç yolunuz var. Birincisi, en azından iç NTP sunucusuna UDP 123'ün açılmasını rica etmek; bu ağ yöneticilerine standart ve güvenli bir taleptir. İkincisi, sanal makine ya da konteynerse hipervizörden ya da ana makineden senkronize olmak. Üçüncüsü, htpdate aracıyla HTTP yanıtlarının Date başlığına göre saati ayarlamak; doğruluk saniye düzeyindedir, TLS, JWT ve istek imzaları için bu yeterlidir ve HTTP proxy üzerinden çalışabilir. En zarif değil ama yalıtılmış segmentler için işleyen bir seçenektir.
Windows
Windows ana makinelerinde zaman servisi şöyle kontrol edilir:
w32tm /query /status
w32tm /resyncEtki alanı ortamında kaynak etki alanı denetleyicisidir, etki alanı dışında yapılandırılmış NTP sunucusudur. Last Successful Sync Time alanı taze olmalıdır.
Konteynerler ve saat: ana makineden ne miras alınır, ne alınmaz
Konteyner, ortak bir çekirdek üzerinde yalıtılmış ad alanları kümesidir. Yalıtım süreçler, ağ, dosya sistemi, bağlama noktaları için geçerlidir. Ama gerçek zamanlı saat (CLOCK_REALTIME) yalıtılmaz. Linux 5.6 ile gelen zaman ad alanları yalnızca monotonik saatleri ve önyüklemeden bu yana geçen süreyi kaydırmaya izin verir — konteyner göçü için gerekir ve takvim zamanını etkilemez. Bundan birkaç kesin sonuç çıkar.
Miras alınanlar
- Takvim zamanı. Tüm konteynerler ana makinenin gördüğü zamanı aynen görür. Ana makine kaydıysa hepsi kaydı.
- Senkronizasyon. Ana makinede çalışan chrony tüm konteynerlerdeki saati otomatik «düzeltir».
- Sıçramalar. Ana makine saati sıçramayla düzeltirse konteynerlerdeki uygulamalar bu sıçramayı anında görür.
Miras alınmayanlar
- Saat dilimi. /etc/localtime dosyası ve TZ değişkeni imajın içinde yaşar. Minimal Alpine imajlarında tzdata paketi olmayabilir ve konteyner her zaman UTC gösterir. Bu saat hatası değil gösterim hatasıdır, ama log okurken düzenli olarak yanıltır.
- Kök sertifika deposu. Bu yazının konusu değil ama hatırlatalım: o da imajın içindedir.
- Saati değiştirme hakkı. Sistemi ayarlama sistem çağrısı CAP_SYS_TIME gerektirir, konteynerde varsayılan olarak yoktur. Konteyner içinde date -s komutu «Operation not permitted» hatasıyla biter. Normal bir konteynerde NTP servisini çalıştırmak anlamsızdır ve ona CAP_SYS_TIME vermek kötü pratiktir: tüm ana makinenin saatini yönetmeye başlar.
Pratik sonuçlar
Önceki bölümdeki teşhis konteynerin içinde de yapılabilir ve yapılmalıdır — date -u ve proxy üzerinden Date başlığı isteği gerçek tabloyu gösterir. Ama düzeltme her zaman ana makinede yapılır. Konteyner Kubernetes'te çalışıyorsa gerekli ana makine, pod'un planlandığı belirli düğümdür; düğümlerin temel imajında chrony bulunduğundan ve izlemenin her düğümden sapma metriğini topladığından emin olun.
Dizüstülerdeki Docker Desktop ve WSL2 ayrı bir hikâye, çünkü orada konteynerlerin «ana makinesi» uykudan sonra geride kalmaya meyilli gizli bir sanal makinedir. WSL2 için hızlı düzeltme — hipervizörün düzenli tuttuğu donanım saatinden zamanı çekmektir:
sudo hwclock -sDocker Desktop için radikal ama güvenilir yol uygulamayı yeniden başlatmaktır; başlatma sonrası VM ana makineyle senkronize olur. Yeni sürümlerde sorun daha seyrektir ama tamamen ortadan kalkmamıştır, bu yüzden geliştirme ortamında saat sapması healthcheck'i paranoya değil, sabah bir saatini kurtarmaktır.
Örnek: compose dosyasında healthcheck
Fikir — ana makinenin saati izin verilenin ötesinde kaydıysa çalışma konteynerini ayağa kaldırmamak. Kontrol, TLS'e bağımlı olmamak için proxy üzerinden normal HTTP ile aynı Date başlığı yöntemini kullanır:
healthcheck:
test: ["CMD", "python", "/app/clock_check.py"]
interval: 5m
timeout: 20s
retries: 1clock_check.py betiği — teşhis bölümünde yazdığımız, 30 saniye eşikli olan. Orkestratör konteyneri sağlıksız olarak işaretler ve nedeni uygulama loglarındaki TLS hataları yığınında değil, durumda görürsünüz.
Sık yapılan hatalar ve pratikten vakalar
Ne yapmamak gerektiği bölümü, ne yapmak gerektiği bölümünden daha faydalıdır. Burada olay anında mantıklı görünen ve sonradan pahalıya mal olan çözümlerle birlikte sayılarla birkaç karakteristik hikâye toplanmıştır.
Hata 1: Sertifika doğrulamasını kapatmak
-k bayrağı, verify=False, NODE_TLS_REJECT_UNAUTHORIZED=0. Betik yeniden «çalışır», görev kapanır. Ama istek imzaları ve JWT hâlâ uyuşmaz, TOTP kabul edilmez ve kanalı koruyan tek mekanizmayı kapatmış olursunuz. Saat ise bozuk kalır ve bir hafta sonra başka bir şeyi kırar. Doğrulamayı kapatmak teşhis kapsamında tam olarak tek bir komut için kabul edilebilir, kodda asla.
Hata 2: leeway ya da imza penceresini «pay bırakarak» büyütmek
JWT doğrulama toleransını 10 dakikaya çıkarmak, ele geçirilmiş bir token'ın yeniden kullanım penceresini 20 kat genişletmek demektir. Gerçek sorun (saat) ise hiç ortadan kalkmaz. JWT için doğru tolerans 30-60 saniyedir, HMAC imzalar için API sağlayıcının verdiği değerdir.
Hata 3: senkronizasyon yerine saati elle düzeltmek
date -s belirtiyi birkaç saat için düzeltir. Sapma ve sonraki snapshot her şeyi geri getirir, üstelik artık kimse saatin elle düzeltildiğini hatırlamayacaktır.
Hata 4: Aynı anda iki zaman servisi
chrony ile timesyncd ya da chrony ile senkronizasyonu açık hipervizör konuk ajanı saati farklı yönlere çeker. chrony loglarında bu sürekli büyük düzeltmeler olarak görünür. Tek bir doğruluk kaynağı bırakın.
Hata 5: Yerel saati UTC ile karşılaştırmak
Tam olarak 3, 5 ya da 7 saatlik fark neredeyse her zaman saat arızası değil, saat dilimidir. Her zaman date -u değerini UTC kaynağıyla karşılaştırın ve loglara zamanı açıkça dilimi belirterek yazın.
Hata 6: «installed» durumuna güvenmek
Ansible rolü chrony'yi kurdu, görev yeşil. Ama UDP 123 kapalı ve chrony «kendisiyle» senkronize. Altyapı yapılandırmasındaki kontrol paketin varlığına değil Leap status ve sapmaya bakmalıdır.
Hata 7: Yeniden denemelerde imzalı isteği yeniden kullanmak
Özellikle yeniden bağlanmalı proxy üzerinden. Her deneme yeni zaman damgası ve yeni imza almalıdır.
Vaka A: test ortamı snapshot'ı
Fiyat açık verisi toplayan bir ekip, işçi havuzunu sanal makinelerde tutuyor ve haftada bir ortamı «temiz» snapshot'a geri alıyordu. Geri alma işlemlerinden birinden sonra, proxy üzerinden giden tüm işçiler hedef sitelerin üçte birinde «certificate is not yet valid» ile patlamaya başladı — tam olarak 90 günlük sertifika kullanan ve snapshot'ın 12 günlük ömründe yenilemiş olanlar. Mühendisin dizüstünden proxy olmadan siteler açılıyordu. Biri date -u çalıştırıp 12 günlük geriliği görene kadar, proxy havuzlarını ve tarifeleri değiştirmek bir buçuk saat aldı. Düzeltme: temel ortam imajında makestep'li chrony ve geri yükleme sonrası betikte sapma kontrolü. Tekrar yaşanmadı.
Vaka B: yalıtılmış segment ve mini PC
Donanım saati olmayan bir mini PC, dışarıya yalnızca kurumsal proxy üzerinden HTTP izinli bir ağ segmentindeydi. Planlı elektrik kesintisinden sonra imaj derleme tarihiyle — 14 ay geride — açıldı. Hiçbir TLS bağlantısı kurulmuyordu, bu da proxy'nin tamamen çöktüğü gibi görünüyordu. Çözüm: şirketin iç NTP sunucusuna UDP 123 izni verildi, chrony makestep 1.0 -1 direktifini aldı ve NTP yokluğu durumu için başlangıçta proxy üzerinden htpdate çalıştırma eklendi.
Vaka C: Docker Desktop'tan nesne depolamaya yükleme
Bir geliştirici, dizüstündeki konteynerden proxy üzerinden S3 uyumlu bir depoya dosya yüklemesini ayıklıyordu. Öğle arasından sonra tüm istekler RequestTimeTooSkewed döndürmeye başladı. Docker Desktop sanal makinesinin saat sapması 23 dakika — 15 dakikalık pencerenin biraz üzerinde. Docker Desktop'ı yeniden başlatmak sorunu bir dakikada çözdü; projeye sapma healthcheck'i eklendi, nedeni hemen gösteriyor.
Vaka D: 50 saniye ve TOTP
Bir servis, kendi kurumsal portalına TOTP ile iki faktörlü kimlik doğrulamalı servis hesabıyla girişi otomatikleştirmişti. Kodlar kabul edilmemeye başladı: sunucu kodun yanlış olduğunu söylüyordu. Düğümün saat sapması 50 saniyeydi, çünkü timesyncd kuruluydu ama chrony'ye geçişte maskelenmiş, chrony ise hiç açılmamıştı. Tek bir 30 saniyelik aralık toleransıyla bu yetti. Kodda sıfır değişiklik, yalnızca chrony'yi başlatmak.
Araçlar ve «proxy'yi suçlamadan önce» kontrol listesi
Her şeyi bir bilete eklenebilecek ya da runbook'a gömülebilecek bir biçime getirelim. Önce araçlar, sonra sıra.
Araçlar
- date -u, timedatectl, chronyc, hwclock — saat ve senkronizasyon durumu.
- curl -v --proxy, openssl s_client -proxy — doğrulama koduyla proxy üzerinden TLS kontrolü.
- chronyd -Q, ntpdate -q — saati değiştirmeden tek seferlik sapma ölçümü.
- HTTP üzerinden Date başlığı — her proxy üzerinden çalışan evrensel zaman kaynağı.
- libfaketime, openssl -attime — arızayı yeniden üretme ve hata işlemeyi test etme.
- htpdate — UDP'nin kapalı olduğu segmentlerde acil senkronizasyon.
- Metrikler — chrony ya da timesyncd için dışa aktarıcılar sapmayı izleme sistemine verir; uyarı eşiği 1 saniye, kritik 30 saniye.
Kontrol listesi
- Patlayan kod tam olarak nerede çalışıyor? Dizüstü, sunucu, VM, konteyner, pod. Tüm kontrolleri orada yapıyoruz.
- date -u telefonla örtüşüyor mu? Dakikalarca fark varsa durun, saati düzeltin.
- Proxy üzerinden http:// ile Date başlığı yerel UTC ile bir-iki saniye içinde örtüşüyor mu? Hayırsa — saat.
- timedatectl synchronized: yes diyor mu, chronyc tracking Leap status Normal gösteriyor mu? Hayırsa — kurulu olana bakmadan, senkronizasyon çalışmıyor.
- Hata metni not yet valid, has expired, RequestTimeTooSkewed, jwt expired, jwt not active, timestamp içeriyor mu? Bu sözcüklerin her biri zamanla ilgilidir.
- Aynı makineden proxy olmadan da hata aynı mı? Öyleyse proxy konu dışıdır.
- Başka bir makineden proxy üzerinden hata yok mu? Öyleyse sorun ilk makinededir.
- openssl s_client proxy üzerinden sertifika tarihleri canlıyken Verify return code 9 ya da 10 gösteriyor mu? Tanı doğrulandı.
- Hatalar yalnızca tek bir hedef ana makineyle mi? Onun Date'ini diğerleriyle karşılaştırın — belki saat karşı tarafta kaymıştır.
- İmzalar her yeniden denemede yeniden oluşturuluyor mu? Hayırsa — yeniden deneme mantığını düzeltin.
- Yakın zamanda snapshot, uyku, göç, uzun kapanıştan sonra yeniden başlatma oldu mu? Her «evet» neredeyse kesin nedendir.
- Tüm «hayır»lardan sonra — proxy sağlayıcınıza başvuru, date -u, chronyc tracking ve curl -v çıktılarıyla birlikte. Böylece Proxeon ya da başka bir servisin desteği sorunu beş değil tek tur yazışmayla çözer.
SSS: zaman, proxy ve arızalar hakkında sık sorulan sorular
Proxy isteklerimdeki ya da TLS'teki zamanı kendisi çarpıtabilir mi?
CONNECT ya da SOCKS5 üzerinden tünellemede — hayır. TLS el sıkışması istemcinizle hedef sunucu arasında gerçekleşir, proxy yalnızca şifreli baytları görür. İmzalardaki ve JWT'lerdeki zaman damgalarını kodunuz kendi makinenizde oluşturur. Proxy'nin ekleyebileceği tek şey gecikmedir ve o da dakikalarla değil milisaniyelerle ölçülür.
Neden dizüstünden proxy olmadan çalışıyor da sunucudan proxy üzerinden çalışmıyor?
Çünkü bunlar iki farklı makine ve iki farklı saat kümesi. Karşılaştırma yapı gereği geçersiz: aynı anda iki değişken değişti. Proxy'nin etkisini yalıtmak için isteği sunucudan proxy olmadan çalıştırın. Makinenin etkisini yalıtmak için dizüstünden proxy üzerinden çalıştırın. Neredeyse her zaman hatanın makineye bağlı olduğu ortaya çıkar.
Proxy üzerinden çalışmak için saat ne kadar doğru olmalı?
TLS için sertifikalar uzun ömürlüyse saat düzeyinde, kısa ömürlüler için gün düzeyinde doğruluk yeter. İstek imzaları için tipik pencere 5-15 dakika. JWT için 30-60 saniye tolerans. TOTP için artı-eksi 30 saniye. Çalışan NTP milisaniye verir, bu yüzden pratik standart 1 saniyenin altında sapma, uyarı ise 30 saniye aşıldığında.
Konteynerin içinde NTP istemcisi çalıştırabilir miyim?
Teknik olarak yalnızca CAP_SYS_TIME ile ve o zaman tüm ana makinenin saatini yönetir, bu da yalıtımı bozar ve ana makinedeki servisle çatışır. Doğru yaklaşım ana makinede ya da küme düğümünde senkronizasyondur. Konteynerde yalnızca sapma kontrolünü bırakın.
UDP 123 tamamen kapalıysa ve tek çıkış HTTP proxy ise ne yapmalı?
En azından şirketin ya da bulut sağlayıcının iç NTP'sine UDP açılmasını talep edin — bu standart bir altyapı ihtiyacıdır. Çözülene kadar hipervizörden senkronizasyonu ya da proxy üzerinden Date başlıklarıyla htpdate kullanın. NTS'nin NTP'yi TCP 4460 portu üzerinden TLS ile koruduğunu ama zaman paketlerinin hâlâ UDP ile gittiğini, yani NTS'nin UDP engelini aşmadığını unutmayın.
Saat birkaç dakika ileride ama TLS çalışıyor. O halde neden API istekleri patlıyor?
Çünkü TLS'in penceresi günler, imzaların ve token'larınki ise saniyeler ve dakikalar. Bu normal bir durumdur: sertifikalar başarıyla doğrulanır ama üç dakika geleceğe gitmiş zaman damgalı HMAC imzası, katı pencereli bir sunucu tarafından reddedilir. Yalnızca bağlantının başarılı olmasına değil, API'nin hata metnine de bakın.
Hedef sunucunun saat mi kaydı, benim mi — nasıl anlarım?
Sorunlu ana makinenin yanıtındaki Date başlığını iki-üç diğer ana makinenin Date'i ve date -u değeriyle karşılaştırın. Sizin saatiniz çoğunlukla örtüşüyor da tek bir ana makine sapıyorsa — sorun onun tarafındadır. Bazı istemci SDK'ları hatalı zaman yanıtından sunucu sapmasını hesaplayıp otomatik telafi edebilir.
Proxy üzerinden tekrar denemede isteği yeniden imzalamak gerekir mi?
Evet. İmza zaman damgası içerir ve pencere içinde geçerlidir. İlk denemeyle tekrar arasında beklemeler ve yeniden bağlanmalar geçtiyse eski imza pencereyi aşabilir. İmzayı her denemenin gönderim anında oluşturun.
Saat kontrolünü izlemeye nasıl dahil ederim?
Sapmayı chrony ya da timesyncd'den metrik sistemine alın ve iki eşik koyun: 1 saniyede uyarı, 30 saniyede kritik. Ek olarak, çalışan proxy üzerinden Date başlığına göre servis healthcheck'i — zaman servisinin görünüşte canlı olduğu ama saatin yine de kaydığı durumları, örneğin snapshot geri yüklemesi sonrasını yakalar.
2026'da değişen bir şey oldu mu?
Ana değişiklik, kamu sertifikalarının ömrünün kısalması ve otomatik yenilemenin yaygınlaşması. Bu, birkaç günlük küçük saat geriliklerini bile TLS arızalarının gerçek nedeni haline getiriyor; eskiden böyle sıkıntılar nadirdi. Aynı zamanda kısa JWT'lerin ve API'lerde katı imza pencerelerinin payı artıyor. Diğer bir deyişle, istemci makinelerinin saat doğruluğuna yönelik gereksinimler artıyor ve zaman senkronizasyonu «üzerinde düşünülmeyen varsayılan ayar» olmaktan çıkıyor.
Sonuç: teşhisin ilk maddesi olarak zaman
Özetleyelim. Sertifika geçerlilik süresinin kontrolü, JWT'deki exp ve nbf alanları, istek imzasındaki zaman damgası ve tek kullanımlık kod — bunların hepsi sistem saatiyle yapılan yerel karşılaştırmalardır. Proxy üzerinden çalışırken zincire bir makine daha eklenir ve dikkat doğal olarak ona kayar, oysa ne TLS el sıkışması ne imza ne de token doğrulaması proxy tünelinden geçer. Proxy bu senaryolarda yalnızca taşıyıcıdır. Saat ise pekâlâ dünyevi nedenlerle kayar: sanal makinelerin snapshot'ları ve duraklaması, Docker Desktop ve WSL2'li dizüstülerin uykusu, senkronizasyon servisinin yokluğu ya da çalışmaması, kapalı UDP, bitmiş pil, elle düzeltme.
Pratik program basit ve üç adıma sığar. Birincisi — zamana bağlı hataları metninden tanımaya alışmak: not yet valid, has expired, RequestTimeTooSkewed, jwt expired, jwt not active. İkincisi — proxy ile ilgili her olay incelemesinin ilk maddesi saat sapması kontrolünü yapmak: date -u, proxy üzerinden HTTP Date başlığı, timedatectl ya da chronyc tracking. Bu, saatler kazandıran bir dakikadır. Üçüncüsü — sorunun geri dönmemesini sağlamak: temel imajlarda iburst ve makestep'li chrony, makine başına tek zaman kaynağı, konteynerler için ana makinede senkronizasyon, izlemede sapma metriği ve proxy üzerinden giden servislerde healthcheck.
Bunların hepsi yapıldığında proxy sağlayıcınıza başvuru anlamlı hale gelir: elinizde dışlanmış bir hipotez ve komutların hazır çıktıları olur ve inceleme özünde ilerler. Çoğu durumda ise başvuruya gerek kalmaz — çünkü saat ilk kontrol ettiğiniz ve sizi son şaşırtan şey olur.