Güvenlik & SSL

    Sunucu Saati Yanlış: SSL, TOTP ve Cron Hatalarının Gizli Sebebi

    Bağımsız görünen sertifika, imzalı istek, TOTP ve cron arızalarını tek kök nedene bağlayıp NTP senkronizasyonunu kalıcı kuruyoruz.

    13 dk okuma Güncellendi: 18 Ağustos 2026

    Sabah 09:40. Yeni kurduğunuz Let's Encrypt sertifikası için tarayıcı NET::ERR_CERT_DATE_INVALID diyor ve detayda "sertifika henüz geçerli değil" yazıyor. Sertifikayı dakikalar önce aldınız, dosya yolları doğru, zincir tam. Aynı saatlerde ödeme sağlayıcısının API'si isteklerinizi imza hatasıyla reddetmeye başlıyor. Öğleden sonra bir müşteri arıyor: "Google Authenticator kodum kabul edilmiyor." Akşam yedeklemenin gece 03:00 yerine öğlen çalıştığını fark ediyorsunuz.

    Dört ayrı ekip, dört ayrı destek kaydı, dört ayrı hipotez. Aslında dördü de tek bir satıra bakıyor: sunucunun sistem saati kaymış. Bu arıza sinsi olmasının iki nedeni var. Birincisi, belirtiler birbirine hiç benzemez — biri TLS, biri HMAC imzası, biri OTP, biri zamanlayıcı. İkincisi, saat "biraz" yanlış olduğunda hiçbir şey çökmez; sadece bazı şeyler reddedilir. Sunucu ayakta, servisler active (running), disk boş, RAM rahat. Monitoring yeşil.

    Bu yazıda önce bu beş belirtiyi tek kök nedene bağlayacağız, sonra timedatectl ile teşhis koyacak ve chrony ya da systemd-timesyncd ile kalıcı senkronizasyon kuracağız. Sonunda saatin bir daha sessizce kaymayacağından emin olacak, kaydığında da beş dakika içinde teşhis edebilecek durumda olacaksınız.

    Beş Farklı Belirti, Tek Kök Neden#

    Saat kayması bir "hata" üretmez, bir red üretir. Zaman damgasına bakan her protokol, kabul ettiği bir pencereye sahiptir; sistem saati o pencerenin dışına çıktığı anda karşı taraf isteği geçersiz sayar. Pencerelerin genişliği birbirinden çok farklı olduğu için de belirtiler kademeli çıkar:

    BelirtiTolerans penceresiNe kadar kayma yeter
    TOTP kodu reddediliyor30 sn'lik adım, genelde ±1 adım~90 saniye
    İmzalı API isteği reddediliyor (S3/SigV4 tarzı)15 dakika~15 dakika
    Kerberos / Active Directory kimlik doğrulama5 dakika~5 dakika
    JWT nbf / exp doğrulamasıToken ömrüne bağlı, sıklıkla dakikalar1–60 dakika
    Sertifika "henüz geçerli değil"Sertifikanın notBefore anıSaatler / günler
    Cron ve log saatleriYokHerhangi bir kayma

    Bu tabloyu tersinden okuyun: elinizde hangi belirti varsa, kaymanın büyüklüğü hakkında fikriniz olur. Yalnızca TOTP kodları tutmuyorsa kayma muhtemelen dakikalar mertebesinde. Sertifika "henüz geçerli değil" diyorsa sunucu saati saatler, çoğu zaman günler ileri gitmiş demektir. Bu, teşhis sırasında zaman kazandıran pratik bir kısayoldur.

    Kaymanın yönü de bilgi taşır. Saat ileriyse yeni alınmış sertifikalar "henüz geçerli değil" olur, kısa ömürlü token'lar hemen süresi dolmuş görünür. Saat geriyse süresi dolmuş sertifikalar hâlâ geçerli görünür, süresi biten oturumlar kapanmaz — yani güvenlik açısından daha tehlikeli olan yön budur, çünkü hiçbir şey bağırmaz.

    Sunucu Saatinin Yanlış Olduğunu Nasıl Anlarım?#

    İlk komut her zaman aynı olmalı. Yerel saate değil, UTC'ye bakın; zaman dilimi ayrı bir sorun ve karıştırmak teşhisi bozar.

    # Sunucunun UTC saati
    date -u
    
    # Senkronizasyon durumunun tam özeti
    timedatectl status
    

    timedatectl status çıktısında üç satır kritiktir:

                   Local time: Tue 2026-08-18 14:32:07 +03
               Universal time: Tue 2026-08-18 11:32:07 UTC
                    Time zone: Europe/Istanbul (+03, +0300)
    System clock synchronized: yes
                  NTP service: active
    

    System clock synchronized: no veya NTP service: inactive görüyorsanız senkronizasyon çalışmıyor demektir. Ancak dikkat: synchronized: yes yazması saatin doğru olduğunu kanıtlamaz. Bu satır "bir zaman kaynağıyla senkronize oldum" der; kaynağın kendisi yanlışsa ya da senkronizasyon saatler önce olup sonra kaynak erişilemez hâle geldiyse yine yes görebilirsiniz.

    O yüzden bağımsız bir referansla karşılaştırın. En hızlı yöntem, güvendiğiniz bir sitenin HTTP Date başlığını okumaktır — bu başlık sunucunun kendi UTC saatini taşır:

    # Dış dünyanın saati ile kendi saatinizi yan yana görün
    curl -sI https://www.cloudflare.com | grep -i '^date:'
    date -u
    

    İki değer arasında saniyelerden fazla fark varsa kök nedeni buldunuz. Saniyeler mertebesindeki fark normaldir; ağ gecikmesi ve başlığın üretilme anı bunu açıklar.

    Sertifika Neden "Henüz Geçerli Değil" Diyor?#

    X.509 sertifikası iki zaman damgası taşır: notBefore ve notAfter. TLS el sıkışması sırasında doğrulayan taraf, kendi sistem saatinin bu iki değerin arasında olmasını bekler. Yani sertifikanın geçerliliği mutlak bir gerçek değil, saati kime sorduğunuza bağlı bir yargıdır.

    Sertifikanın gerçek tarihlerini görmek için:

    # Uzaktaki servisin sunduğu sertifikanın tarihleri
    openssl s_client -connect ornek.com:443 -servername ornek.com </dev/null 2>/dev/null \
      | openssl x509 -noout -dates -subject
    
    # Diskteki dosyadan
    openssl x509 -in /etc/letsencrypt/live/ornek.com/fullchain.pem -noout -dates
    

    Çıktı şuna benzer:

    notBefore=Aug 18 08:11:03 2026 GMT
    notAfter=Nov 16 08:11:02 2026 GMT
    

    Şimdi bu değerleri date -u çıktısıyla karşılaştırın. Sunucunuzun UTC saati notBefore'dan önceyse hata sertifikada değil, saattedir. Aynı durum tersine de işler: saat geride kalmış bir sunucuda süresi dolmuş bir sertifika hâlâ geçerli görünür ve siz sorunu ancak ziyaretçiler şikâyet edince fark edersiniz.

    Bu hatanın istemci tarafında da yaşanabileceğini unutmayın. Sertifikanız kusursuzken sadece bir kullanıcı hata alıyorsa, sorun büyük ihtimalle onun cihazının saatindedir. Diğer TLS hata türlerini ve ayırt edici işaretlerini SSL hataları ve çözümleri yazımızda topladık; sertifika ömrünün nasıl planlanacağı için de sertifika geçerlilik süresi rehberine bakabilirsiniz.

    Bir yan etki daha var: saat bozuksa otomatik yenileme de bozulur. Certbot'un systemd zamanlayıcısı ya da cron girdisi yanlış anda çalışır, kimi zaman hiç çalışmaz. Yenileme mantığını SSL otomatik yenileme yazısında ele almıştık; oradaki her şey doğru sistem saati varsayar.

    İmzalı API İstekleri Neden Reddediliyor?#

    Modern API'lerin çoğu isteği bir imzayla korur ve imzanın içine zaman damgası koyar. Amaç tekrar saldırısını (replay) engellemektir: eski bir isteği yakalayıp tekrar göndermek, damga eskidiği için işe yaramaz. Bunun bedeli, istemcinin saatinin doğru olması zorunluluğudur.

    Karşılaşacağınız tipik mesajlar:

    • RequestTimeTooSkewed — S3 uyumlu depolama ve benzeri servisler, genelde 15 dakikalık pencere
    • Signature expired / Invalid signature — imza doğru üretilmiş ama damga kabul aralığının dışında
    • KRB_AP_ERR_SKEW — Kerberos/AD, varsayılan 5 dakika
    • JWT tarafında nbf (not before) veya exp doğrulama hatası

    Buradaki en aldatıcı senaryo şudur: kod değişmedi, kimlik bilgileri değişmedi, dün çalışıyordu. Ekip doğal olarak sağlayıcıyı ya da anahtarları suçlar. Oysa sunucu saati sessizce kaymıştır. Bir S3 yedekleme betiği aniden çalışmayı bırakmışsa, anahtarları yeniden üretmeden önce date -u çalıştırın; iki saniyelik kontrol yarım günlük hata avını önler.

    TOTP Kodları Neden Tutmuyor?#

    TOTP (RFC 6238) paylaşılan bir sırdan, 30 saniyelik zaman adımlarını girdi alarak kod üretir. Doğrulayan taraf genelde bir adım geriye ve bir adım ileriye tolerans tanır; yani pratikte pencere yaklaşık 90 saniyedir.

    Sonuç: sunucu saati bir buçuk dakikadan fazla kaymışsa hiç kimse giriş yapamaz. Kullanıcının telefonu doğrudur, uygulama doğrudur, sır doğrudur; yalnızca sunucu farklı bir adımı hesaplamaktadır. Bu arızanın imzası çok belirgindir: sorun tek bir kullanıcıda değil, aynı anda herkeste başlar ve "az önce çalışıyordu" denir.

    Ters yön de mümkündür: sunucu doğru, kullanıcının telefonu kaymıştır. Android ve iOS'ta "saati otomatik ayarla" seçeneği kapalıysa cihaz dakikalarca sürüklenebilir. Destek talebinde ilk sorulacak soru budur. İki faktörlü doğrulamanın genel işleyişi ve kurtarma kodlarının rolü için iki faktörlü doğrulama (2FA) yazısına bakın — kurtarma kodları tam da bu tür durumlar için vardır, çünkü onlar zamana bağlı değildir.

    Loglar ve Cron: Gürültüsüz Ama Kalıcı Hasar#

    Kimlik doğrulama arızaları en azından bağırır. Saat kaymasının asıl kalıcı hasarı sessiz tarafta birikir.

    Log korelasyonu bozulur. Web sunucusu, uygulama ve veritabanı farklı saatlerdeyse bir olayı uçtan uca takip edemezsiniz. journalctl --since "10 minutes ago" boş döner, çünkü "10 dakika önce" gerçekte iki saat sonrasıdır. Log okuma pratiğini journalctl ile log yönetimi yazısında anlattık; orada tarif edilen zaman filtrelerinin tamamı doğru saate bağlıdır.

    Zamanlanmış görevler kayar. Yedekleme gece 03:00 yerine trafik saatinde çalışır. Daha kötüsü, saat elle ileri alındığında bazı görevler atlanır, geri alındığında ise iki kez çalışır. İki kez çalışan bir "eski kayıtları sil" işi geri dönüşü olmayan sonuç üretebilir. Cron görevleri yazısındaki tüm zamanlamalar sistem saatini referans alır; systemd tarafında da durum aynıdır, üstelik OnCalendar ile systemd zamanlayıcıları zaman dilimi değişimlerine karşı ayrıca hassastır.

    Oran sınırlama ve oturum süreleri şaşar. Kayan pencereli rate limit sayaçları, oturum zaman aşımları ve önbellek TTL'leri hep saate bakar. Saat geriye adım atarsa bir oturum beklenenden çok daha uzun yaşar.

    chrony ile Kalıcı Senkronizasyon Kurmak#

    Saati elle düzeltmek çözüm değildir; birkaç hafta içinde yeniden kayar. Kalıcı çözüm bir NTP istemcisidir. Sunucular için pratikte iki seçenek var: chrony ve systemd-timesyncd.

    Kurulum#

    # AlmaLinux / Rocky / RHEL
    sudo dnf install -y chrony
    sudo systemctl enable --now chronyd
    
    # Debian / Ubuntu
    sudo apt update && sudo apt install -y chrony
    sudo systemctl enable --now chrony
    

    Yapılandırma dosyası RHEL ailesinde /etc/chrony.conf, Debian ailesinde /etc/chrony/chrony.conf yolundadır. Türkiye'deki bir sunucu için makul bir başlangıç:

    # Coğrafi olarak yakın havuz, iburst ilk senkronizasyonu hızlandırır
    pool tr.pool.ntp.org iburst
    pool 2.pool.ntp.org iburst
    
    # İlk 3 güncellemede 1 saniyeden büyük fark varsa saati adımla (yavaşça değil)
    makestep 1.0 3
    
    # Sistem saati düzeldikçe donanım saatini de güncelle
    rtcsync
    
    # Sürüklenme katsayısını sakla, yeniden başlatmada daha hızlı yakınsa
    driftfile /var/lib/chrony/drift
    

    Değişiklikten sonra servisi yeniden başlatın:

    sudo systemctl restart chronyd   # Debian/Ubuntu'da: chrony
    

    Doğrulama ve chronyc Çıktısını Okumak#

    Kurulum yaptım demek yetmez; senkronizasyonun gerçekten oturduğunu görmelisiniz.

    chronyc tracking
    chronyc sources -v
    

    chronyc tracking çıktısında iki satıra bakın. System time satırı, sistem saatinizin NTP zamanından ne kadar saptığını gösterir — sağlıklı bir sunucuda bu değer milisaniyeler mertebesindedir. Leap status satırı Normal olmalıdır; Not synchronised görüyorsanız henüz bir kaynağa kilitlenilmemiş demektir.

    chronyc sources çıktısında satır başındaki işaretler kaynağın durumunu anlatır:

    İşaretAnlamı
    ^*Şu anda senkronize olunan kaynak — en az bir tane olmalı
    ^+Kabul edilebilir, birleştirmeye dahil edilen kaynak
    ^-Seçilebilir ama seçilmemiş
    ^?Ulaşılamıyor veya yeterli ölçüm yok
    ^xYanlış zaman bildiriyor (falseticker)
    ^~Ölçümleri çok değişken, güvenilmez

    Hiçbir satırda * yoksa senkronizasyon çalışmıyor demektir; Reach sütununda uzun süre 0 görüyorsanız kaynağa hiç ulaşılamıyordur. Bu doğrudan bir ağ sorununa işaret eder.

    chrony mı systemd-timesyncd mi?#

    Ubuntu ve Debian kurulumlarının çoğunda hazır gelen systemd-timesyncd, basit bir SNTP istemcisidir. Çoğu web sunucusu için fazlasıyla yeterlidir.

    systemd-timesyncdchrony
    KurulumGenelde hazır gelirAyrıca kurulur
    Sunucu olabilir miHayır, yalnızca istemciEvet, ağınıza zaman dağıtabilir
    Kesintili ağda davranışZayıfGüçlü, sürüklenmeyi öğrenir
    Teşhis araçlarıSınırlıchronyc ile ayrıntılı
    Sanal makine / uzun kapalı kalmaOrtaİyi

    Pratik kural: tek başına duran bir web sunucusu için systemd-timesyncd yeterlidir. Birden fazla sunucunuz varsa, saat hassasiyeti iş mantığınıza giriyorsa (finans, loglama, dağıtık kilitler) ya da makine sık sık uyku/anlık görüntü döngüsüne giriyorsa chrony tercih edin.

    systemd-timesyncd tarafında yapılandırma /etc/systemd/timesyncd.conf içindedir:

    [Time]
    NTP=tr.pool.ntp.org 2.pool.ntp.org
    FallbackNTP=time.cloudflare.com
    

    Durumu şöyle doğrularsınız:

    sudo timedatectl set-ntp true
    timedatectl timesync-status
    systemctl status systemd-timesyncd
    

    ⚠️ İki zaman daemon'ı aynı anda çalışmamalıdır. chrony ile systemd-timesyncd birbirleriyle yarışır ve saati ileri geri iterler. Çoğu dağıtımda chrony kurulunca diğeri otomatik devre dışı bırakılır, ama elle kurulum yaptıysanız kontrol edin:

    systemctl is-active chronyd systemd-timesyncd ntpd
    

    Yalnızca biri active dönmelidir.

    Zaman Dilimi Ayrı Bir Konudur#

    Sistem saatinin doğru olması ile ekranda doğru saatin görünmesi iki farklı iştir. NTP UTC ile ilgilenir; zaman dilimi ise o UTC değerinin nasıl gösterileceğini belirler.

    timedatectl list-timezones | grep -i istanbul
    sudo timedatectl set-timezone Europe/Istanbul
    

    Türkiye 2016'dan beri kalıcı olarak UTC+3 kullanır ve yaz saati uygulaması yoktur; yine de Europe/Istanbul yazın, Etc/GMT-3 gibi sabit ofsetler kullanmayın. Zaman dilimi veritabanı ileride bir değişiklik olursa güncellenir, sabit ofset güncellenmez.

    Sunucularda yaygın ve iyi bir pratik, sistem zaman dilimini UTC'de bırakıp yerelleştirmeyi uygulama katmanında yapmaktır. Birden fazla sunucunuz varsa loglarınız aynı dilde konuşur ve korelasyon dertsiz olur.

    Bir de donanım saati (RTC) meselesi var. Linux sunucularda RTC'nin UTC tutması beklenir; makine Windows ile ikili önyükleme yapmıyorsa bunu değiştirmeyin:

    timedatectl set-local-rtc 0
    hwclock --show
    

    NTP Bir Türlü Senkronize Olmuyorsa#

    Kurulum doğru ama chronyc sources hâlâ * göstermiyorsa, sırayla şunlara bakın.

    1. Giden UDP 123 kapalı olabilir. NTP çoğu insanın sandığının aksine TCP değil UDP kullanır. Güvenlik duvarında yalnızca TCP çıkışına izin veren kurallar NTP'yi sessizce keser. Çıkış kurallarınızda UDP 123'e izin verin.
    2. Sağlayıcı NTP'yi kendi ağında yönlendiriyor olabilir. Bazı bulut ortamlarında yalnızca sağlayıcının kendi zaman sunucusu erişilebilirdir. Bu durumda havuz adresleri yerine sağlayıcının verdiği adresi yazın.
    3. Konteyner içinde saat ayarlanamaz. Docker konteynerleri çekirdek saatini host ile paylaşır; içeride NTP istemcisi çalıştırmak CAP_SYS_TIME olmadan işe yaramaz ve zaten yanlış çözümdür. Saati host üzerinde düzeltin.
    4. Anlık görüntüden dönen sanal makineler. Bir VM askıya alınıp saatler sonra devam ettirildiğinde saat donduğu yerden devam eder. Hipervizör misafir aracı (guest agent) bunu düzeltir; yoksa chronyc makestep ile elle adımlayın.
    5. Kaynak karışımı yanlış olabilir. Google'ın zaman sunucuları artık saniyesini "yayarak" (leap smearing) uygular; bu kaynakları yaymayan havuz sunucularıyla aynı yapılandırmada karıştırmayın. Ya hepsi yayan, ya hepsi standart olsun.

    Saati Düzeltirken Sistemi Bozmamak#

    Kayma büyükse saat "adımlanmalı" (step), yani bir anda doğru değere sıçratılmalıdır. Bu güvenli bir işlem değildir: saati geriye almak, zaman damgasına güvenen her şeyi şaşırtır — veritabanı replikasyonu, mesaj kuyrukları, kilit süreleri, log sıralaması.

    Pratik yaklaşım:

    # Ne kadar kaymışız, önce bakalım
    chronyc tracking | grep -i 'system time'
    
    # Küçük fark: chrony zaten yavaşça düzeltir, dokunmayın
    # Büyük fark: bilinçli olarak adımlayın
    sudo chronyc makestep
    

    İleri adımlama (saat geriden geliyorsa) genellikle zararsızdır. Geri adımlama (saat ileri gitmişse) için mümkünse bir bakım penceresi açın, kritik servisleri durdurun, adımlayın, sonra başlatın. Alternatif olarak chrony küçük farkları kendiliğinden yavaşça düzeltir (slew); acele etmiyorsanız en güvenli yol budur.

    Son adım, düzeltmenin kalıcı olduğundan emin olmaktır:

    timedatectl status
    systemctl is-enabled chronyd
    chronyc sources -v
    

    Üçü de beklediğiniz sonucu veriyorsa iş bitmiştir. İzleme sisteminize basit bir kontrol eklemeyi de unutmayın: chronyc tracking çıktısındaki sapma belirli bir eşiği aşarsa uyarı üretsin. Saat kayması, sizi ancak müşteri arayınca haberdar eden az sayıda arızadan biridir; oysa ölçülmesi son derece ucuzdur.

    Sıkça Sorulan Sorular#

    Sunucu saatini elle ayarlasam yetmez mi?#

    Yetmez. Her bilgisayarın kristal osilatörü sıcaklığa ve üretim toleransına bağlı olarak sürüklenir; sanal makinelerde bu sürüklenme daha da belirgindir. Elle düzelttiğiniz saat birkaç hafta içinde yeniden kayar ve aynı arızalarla karşılaşırsınız. Kalıcı çözüm, sürekli çalışan bir NTP istemcisi kurmaktır. Elle ayar yalnızca acil durumda, kalıcı çözüme geçmeden önceki geçici adımdır.

    timedatectl "synchronized: yes" diyor ama saat yine de yanlış, nasıl olur?#

    Bu satır "bir kaynakla senkronize oldum" bilgisini verir, "şu anda doğruyum" garantisini vermez. Senkronizasyon saatler önce gerçekleşmiş ve sonra kaynağa erişim kesilmiş olabilir; ya da yapılandırdığınız zaman sunucusunun kendisi yanlış olabilir. Bağımsız bir referansla karşılaştırın: bir HTTPS sitesinin Date başlığını okuyup date -u çıktısıyla yan yana koymak en hızlı doğrulamadır.

    Sertifikam geçerli görünüyor ama bazı ziyaretçiler hata alıyor, sunucu saati mi suçlu?#

    Hata yalnızca bazı kullanıcılarda çıkıyorsa sunucu saatiniz büyük ihtimalle doğrudur; sorun o cihazların kendi saatlerindedir. Sunucu kaynaklı olsaydı istisnasız herkes aynı hatayı alırdı. Kullanıcıdan telefon veya bilgisayarında saatin otomatik ayarlanmasını açmasını isteyin. Yine de kendi tarafınızı da doğrulamak için openssl ile sertifika tarihlerini ve date -u çıktısını karşılaştırmak birkaç saniyenizi alır.

    chrony ile systemd-timesyncd arasında hangisini seçmeliyim?#

    Tek bir web sunucusu yönetiyorsanız ve makine sürekli açıksa systemd-timesyncd yeterlidir; zaten kurulu gelir ve ek yük getirmez. Birden fazla sunucunuz varsa, ağınıza kendi zaman kaynağınızı dağıtmak istiyorsanız, makineler sık sık askıya alınıp devam ettiriliyorsa ya da ayrıntılı teşhis çıktısına ihtiyaç duyuyorsanız chrony daha iyi bir tercihtir. İkisini aynı anda çalıştırmayın.

    Docker konteynerinin saati yanlış, içeride NTP kursam olur mu?#

    Olmaz ve gerekmez. Konteynerler çekirdeği host ile paylaştığı için ayrı bir sistem saatleri yoktur; içeride saat ayarlamak yetki gerektirir ve doğru yaklaşım değildir. Konteynerin saati yanlışsa host makinenin saati yanlıştır, düzeltmeyi orada yapın. Konteyner içinde yalnızca zaman dilimi farklı görünebilir; bunu TZ ortam değişkeniyle ya da host'un zaman dilimi dosyasını bağlayarak çözebilirsiniz.

    Saati geriye almak neden riskli, ileri almaktan farkı ne?#

    İleri almak yalnızca "gelecekte bir noktaya atlamak" demektir; çoğu sistem bunu tolere eder. Geriye almak ise aynı zaman damgasının ikinci kez üretilmesine yol açar. Bu durumda log satırları sırasız görünür, artan sayaç varsayan mekanizmalar bozulur, zamanlanmış görevler ikinci kez tetiklenebilir ve veritabanı replikasyonu tutarsızlık bildirebilir. Büyük bir geri düzeltme gerekiyorsa bakım penceresinde, kritik servisler durdurulmuş hâlde yapın.

    Zaman SenkronizasyonuSSLSunucu Yönetimi

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.