Wyobraź sobie: wczoraj twój parser przez proxy działał idealnie, logi czyste, metryki zielone. Dziś rano otwierasz dashboard i widzisz ścianę błędów: certificate is not yet valid, token expired, signature does not match. Pierwsza myśl inżyniera jest przewidywalna: proxy się zepsuło, dostawca coś zmienił, trzeba wymienić pulę. Spędzasz godziny na diagnostyce sieci, zmieniasz endpointy, piszesz do wsparcia. A przyczyna przez cały czas siedziała tuż pod nosem i tykała nieprawidłowo. To zegar systemowy.

Desynchronizacja czasu to jedno z najbardziej niedocenianych źródeł awarii w infrastrukturze działającej przez proxy. Jest podstępna, bo maskuje się jako problemy sieciowe i certyfikatowe. Widzisz słowo certificate w błędzie i odruchowo idziesz zajmować się TLS, choć certyfikat jest absolutnie żywy i ważny. Po prostu twoja maszyna myśli, że jest inny dzień.

W tym przewodniku omówimy temat od A do Z. Dowiesz się, gdzie dokładnie czas jest wbudowany w kryptografię i protokoły, jak wyglądają konkretne błędy w curl, Pythonie i Node, dlaczego zegary rozjeżdżają się w wirtualkach i kontenerach, jak w minutę postawić diagnozę i jak skonfigurować synchronizację tak, żeby naprawdę działała, a nie tylko figurowała jako zainstalowana. Materiał napisany przez inżynierów Proxeon na podstawie analizy realnych incydentów. Osobno podkreślmy: nie chodzi o wystawianie certyfikatów ani o ich budowę - tylko o czas jako przyczynę awarii.

Podstawy: dlaczego czas jest częścią protokołu, a nie tylko cyfrą na ekranie

Zacznijmy od fundamentu. Wielu postrzega czas systemowy jako czysto ludzką konwencję: wygodnie wiedzieć, że teraz jest 14:30. Ale w świecie protokołów sieciowych czas jest aktywnym uczestnikiem kontroli bezpieczeństwa. Jest wbudowany w logikę walidacji na kilku poziomach jednocześnie.

Kiedy dwa węzły ustanawiają bezpieczne połączenie lub wymieniają podpisane wiadomości, potrzebują sposobu odróżnienia świeżych danych od przestarzałych. Bez pojęcia czasu nie da się odpowiedzieć na proste pytania: czy ten certyfikat nie wygasł? czy ten token nie jest przeterminowany? czy atakujący nie powtarza starego przechwyconego żądania? Właśnie dlatego w protokoły wbudowano znaczniki czasu i okna ważności.

Czym jest czas systemowy i skąd się bierze

W każdym systemie operacyjnym istnieją dwa powiązane pojęcia. Pierwsze to zegar sprzętowy (RTC, real-time clock), układ z własnym zasilaniem bateryjnym, który tyka nawet przy wyłączonym komputerze. Drugie to zegar systemowy, który jądro systemu prowadzi w pamięci operacyjnej, startując od wartości RTC przy rozruchu i korygując ją w trakcie pracy.

Problem w tym, że generator kwarcowy w każdym sprzęcie nie jest idealny. Spieszy się lub spóźnia o ułamki sekundy na dobę. Nazywa się to dryfem zegara. W tydzień bez korekty nazbierają się zauważalne sekundy, a w niektórych środowiskach wirtualnych - całe minuty. Aby zwalczać dryf, wymyślono protokół sieciowej synchronizacji czasu. Demon synchronizacji okresowo pyta serwery wzorcowe o dokładny czas i delikatnie doprowadza zegar lokalny.

UTC, strefy czasowe i dlaczego to ważne dla proxy

Kluczowy wgląd dla początkujących: cała poważna kryptografia sieciowa działa w UTC - uniwersalnym czasie koordynowanym, bez przywiązania do stref czasowych. Certyfikaty, JWT, podpisy żądań - wszystko operuje momentami czasu w UTC. Strefa czasowa to kosmetyka dla wyświetlania człowiekowi.

To oznacza, że jeśli nieprawidłowo ustawiłeś strefę czasową, ale samo absolutne tiempo (w UTC) jest poprawne, kryptografia nie ucierpi. A jeśli przesunięty jest właśnie czas absolutny - rozjedzie się wszystko. Częste zamieszanie: inżynier widzi w logach dziwny czas lokalny, idzie naprawiać strefę czasową, a źródło problemu jest inne. Zapamiętaj rozróżnienie: strefa czasowa wpływa na wyświetlanie, czas absolutny w UTC wpływa na walidacje.

Jak proxy wpisuje się w ten obraz

Kiedy pracujesz przez proxy, pojawia się dodatkowy węzeł na drodze żądania. Ale ważne jest, żeby zrozumieć: proxy w większości scenariuszy nie zmienia ani nie podmienia czasu w twoich kontrolach kryptograficznych. Uścisk dłoni TLS z serwerem docelowym, sprawdzanie terminu certyfikatu, walidacja tokenu - wszystko to dzieje się po twojej stronie lub po stronie serwera końcowego. Proxy tylko przekazuje bajty.

Stąd paradoks: praca przez proxy nie tworzy problemu czasu, ale czyni jego objawy bardziej zagmatwanymi. Inżynier widzi łańcuch klient - proxy - serwer i naturalnie podejrzewa ogniwo pośrednie. A winna jest lokalna maszyna, na której nieprawidłowo chodzi zegar. Nazywamy to efektem przesuniętego podejrzenia: im dłuższy łańcuch, tym chętniej obwiniamy jego środek, a nie końce.

Głębokie zanurzenie: gdzie dokładnie czas jest krytyczny

Teraz zejdźmy głębiej i omówmy konkretne punkty, w których nieprawidłowy czas zamienia się w awarię. Jest ich cztery, każdy zasługuje na osobną uwagę.

Sprawdzanie terminu ważności certyfikatu w TLS

Każdy certyfikat TLS zawiera dwa pola: notBefore (nie jest ważny wcześniej) i notAfter (nie jest ważny później). To granice okna ważności. Kiedy twój klient ustanawia bezpieczne połączenie, otrzymuje certyfikat serwera i sprawdza: czy aktualny czas mieści się w tym oknie?

I tu kluczowy moment: przez aktualny czas rozumie się czas na twojej maszynie. Jeśli twój zegar spóźnia się i pokazuje datę przed notBefore, klient uzna, że certyfikat jeszcze nie zaczął obowiązywać. Błąd typu certificate is not yet valid. Jeśli zegar uciekł do przodu za notAfter - certyfikat dla ciebie już wygasł, choć dla reszty świata jest świeży. Błąd certificate has expired.

Szczególnie podstępne są krótkotrwałe certyfikaty. Współczesna praktyka zmierza ku certyfikatom o terminie 90 dni i krótszym, a do 2026 roku branża dyskutuje o skróceniu terminów do 45 dni i mniej. Im krótsze okno ważności, tym mniejszy zapas odporności przeciw przesuniętym zegarom. Kiedyś desynchronizacja o godzinę była prawie niezauważalna na tle rocznego certyfikatu. Teraz wąskie okno oznacza, że nawet przesunięcie o kilka godzin u samej granicy odnowienia może położyć połączenie.

JWT: pola exp, nbf i iat

JSON Web Token - popularny format tokenów autoryzacyjnych. Wewnątrz niego żyją pola czasowe, które są sprawdzane przy każdym użyciu tokenu:

  • exp (expiration time) - moment, po którym token uznaje się za przeterminowany.
  • nbf (not before) - moment, przed którym token jeszcze nie jest ważny.
  • iat (issued at) - kiedy token został wydany.

Wszystkie trzy to znaczniki czasu Uniksa w sekundach od epoki, czyli czas absolutny w UTC. Kiedy serwer otrzymuje token, porównuje te pola ze swoim zegarem. Kiedy twój klient decyduje, czy odświeżyć token, patrzy na exp względem swojego zegara.

Scenariusz awarii jest elegancki w swojej szkodliwości. Załóżmy, że zegar twojego klienta uciekł o dziesięć minut do przodu. Serwer wydał token o czasie życia pięć minut. Twój klient, patrząc na swój spieszący zegar, natychmiast uznaje świeży token za już przeterminowany i albo go nie wysyła, albo uruchamia nieskończoną pętlę odświeżania. Odwrotna sytuacja: jeśli nbf jest przesunięty względem twojego zegara, otrzymasz token used before issued lub token not yet valid.

Podpisy żądań ze znacznikiem czasu

Wiele API wymaga, aby każde żądanie było podpisane, a w podpis włączany jest znacznik czasu. Klasyczny przykład - schematy typu podpis HMAC, gdzie klient tworzy ciąg z metody, ścieżki, treści i aktualnego znacznika czasu, a następnie podpisuje go kluczem tajnym. Serwer powtarza obliczenie i porównuje podpisy.

Tutaj czas odgrywa podwójną rolę. Po pierwsze, znacznik czasu wchodzi w podpisywany ciąg, więc serwer musi użyć dokładnie tego samego znacznika, który przysłał klient - pobiera go z nagłówka. Po drugie, serwer sprawdza, że ten znacznik nie jest zbyt odległy od jego własnego czasu. Zwykle dopuszcza się okno kilku minut - ochrona przed powtórnym odtworzeniem starych żądań.

Jeśli zegar klienta wyszedł poza to okno, serwer odrzuci żądanie jako zbyt stare lub przychodzące z przyszłości. Błędy typu request timestamp too skewed, signature expired lub ogólne signature does not match. Co więcej, właśnie z powodu czasu często widzisz błąd podpisu, a nie błąd czasu - serwer nie zawsze mówi szczerze, że chodzi o zegar.

Kody jednorazowe i hasła czasowe

Osobna kategoria - kody jednorazowe oparte na czasie (TOTP), używane w uwierzytelnianiu dwuskładnikowym przy dostępie do paneli zarządzania i konsol API. Taki kod jest obliczany ze wspólnego sekretu i aktualnego czasu, podzielonego na interwały zwykle po 30 sekund. Obie strony liczą kod niezależnie i porównują.

Jeśli zegar klienta jest przesunięty o więcej niż jeden-dwa interwały, kody przestaną się zgadzać. Wprowadzasz świeżo wygenerowany kod, a system mówi, że jest nieprawidłowy. Ludzie w tej sytuacji obwiniają aplikację-generator lub panikują z powodu włamania, choć wystarczyło spojrzeć na zegar. Tolerancja jest tu bardzo wąska - dziesiątki sekund, dlatego TOTP doskonale działa jako wskaźnik desynchronizacji.

Jak błąd wygląda w różnych klientach

Teoria teorią, a inżynier żyje w terminalu i czyta komunikaty błędów. Omówmy, jak desynchronizacja objawia się w popularnych narzędziach. To pomoże ci natychmiast rozpoznać objaw.

curl

Przy pracy z TLS przez curl przesunięte zegary dają charakterystyczne komunikaty. Jeśli czas spóźnia się i certyfikat według twojego zegara jeszcze nie zaczął obowiązywać:

curl: (60) SSL certificate problem: certificate is not yet valid

Jeśli czas uciekł do przodu i certyfikat według twoich miar już wygasł:

curl: (60) SSL certificate problem: certificate has expired

Przydatny szczegół: kod błędu 60 odnosi się do problemów weryfikacji certyfikatu. Niedoświadczony inżynier widzi słowo certificate i idzie sprawdzać sam certyfikat komendą jego podglądu, upewnia się, że daty ważności są w porządku, i wpada w stupor. Rozwiązanie jest w tym, że daty certyfikatu są porównywane z twoim lokalnym czasem. Sprawdź przykład przez proxy:

curl -x http://user:pass@gateway.proxeon.net:8080 -v https://api.example.com/status

Jeśli w wyjściu -v widzisz linie o sprawdzaniu dat certyfikatu i zaraz potem błąd ważności - najpierw porównaj date -u z wzorcem, a nie podejrzewaj bramę.

Python (requests i httpx)

W Pythonie na bazie standardowego stosu TLS przesunięte zegary podnoszą wyjątek przy uścisku dłoni:

requests.exceptions.SSLError: HTTPSConnectionPool(host='api.example.com', port=443): Max retries exceeded (Caused by SSLError(SSLCertVerificationError("certificate verify failed: certificate is not yet valid")))

Zwróć uwagę na ogon komunikatu: certificate is not yet valid. To ten sam objaw czasowy. Przy pracy z JWT obraz jest inny - żadnych błędów TLS, ale biblioteka walidacji tokenu rzuci specyficzny wyjątek:

jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)

lub

jwt.exceptions.ExpiredSignatureError: Signature has expired

Tutaj słowo signature myli - wydaje się, że problem jest w podpisie kryptograficznym. W rzeczywistości expired wskazuje właśnie na pole exp i twój zegar. Szybkie sprawdzenie czasu prosto z kodu:

import time, datetime; print(datetime.datetime.utcnow(), int(time.time()))

Porównaj otrzymany znacznik czasu Uniksa z wzorcowym - rozbieżność większa niż kilka sekund jest już podejrzana.

Node.js

W Node błędy TLS przychodzą z kodami. Dla desynchronizacji charakterystyczne są:

Error: certificate is not yet valid\ncode: 'CERT_NOT_YET_VALID'

i

Error: certificate has expired\ncode: 'CERT_HAS_EXPIRED'

Kody CERT_NOT_YET_VALID i CERT_HAS_EXPIRED to bezpośrednie wskazówki. Jeśli widzisz pierwszy przy żywym certyfikacie, twój zegar się spóźnia. Jeśli drugi przy z pewnością świeżym certyfikacie - zegar się spieszy. Przy pracy z bibliotekami JWT w Node otrzymasz błędy o nazwach typu TokenExpiredError i NotBeforeError. Szybkie sprawdzenie:

node -e "console.log(new Date().toISOString(), Math.floor(Date.now()/1000))"

Zbiorcza tabela objawów

Zbierzmy wzorce w jedną mapę mentalną:

  • certificate is not yet valid / CERT_NOT_YET_VALID - zegar się spóźnia.
  • certificate has expired / CERT_HAS_EXPIRED przy świeżym certyfikacie - zegar się spieszy.
  • token not yet valid / nbf / ImmatureSignature - zegar spóźnia się względem serwera wydającego.
  • token expired / ExpiredSignature zaraz po otrzymaniu tokenu - zegar się spieszy.
  • signature does not match / timestamp too skewed - zegar wyszedł poza okno tolerancji serwera.
  • Stale nieprawidłowy kod TOTP - zegar przesunięty o dziesiątki sekund i więcej.

Dlaczego zegary się rozjeżdżają: anatomia dryfu

Zrozumienie przyczyny to połowa rozwiązania. Omówmy, dlaczego we współczesnej infrastrukturze zegary przesuwają się częściej, niż się wydaje. Dotyczy to zwłaszcza serwerów i węzłów roboczych, przez które przepuszczasz ruch proxy.

Maszyny wirtualne i zamrożenie

Maszyna wirtualna nie ma bezpośredniego dostępu do fizycznego kwarcu. Jej wyobrażenie o czasie to abstrakcja, którą utrzymuje hiperwizor. Zwykle wszystko jest dobrze, dopóki VM działa nieprzerwanie. Ale wystarczy, że hiperwizor wstrzyma maszynę, i zaczynają się cuda.

Klasyczny scenariusz - zamrożenie i snapshoty. Hiperwizor pauzuje VM, na przykład dla migracji lub kopii zapasowej. Wewnątrz gościa czas jakby się zatrzymuje. Kiedy maszyna jest odmrażana, jej zegar systemowy spóźnia się dokładnie o czas pauzy. Jeśli to była minuta - dostałeś minutowe przesunięcie natychmiast, w jednym momencie. Dla krótkotrwałych tokenów i wąskich okien podpisu to fatalne.

Jeszcze gorzej z odtwarzaniem ze starego snapshotu. Maszyna ożywa z czasem z momentu wykonania snapshotu - to mogą być godziny lub dni w przeszłości. TLS natychmiast zacznie odrzucać certyfikaty jako jeszcze nie ważne. Wiele platform chmurowych dostarcza agentów gościa, którzy doprowadzają czas po odmrożeniu, ale nie zawsze są i nie zawsze działają.

Kontenery

Z kontenerami historia jest subtelniejsza. Kontener nie ma własnego zegara systemowego - używa jądra hosta i, co za tym idzie, czasu hosta. To dobra wiadomość: jeśli host jest zsynchronizowany, kontener widzi prawidłowy czas automatycznie.

Zła wiadomość tkwi w niuansach. Po pierwsze, wewnątrz kontenera zwykle nie można zmienić czasu systemowego - nie ma odpowiednich uprawnień, i słusznie. Po drugie, co ważne, wewnątrz kontenera często brakuje demona synchronizacji, i to normalne - synchronizować powinien host. Problem pojawia się, gdy host sam nie jest zsynchronizowany, a ty tego nie zauważasz, bo przywykłeś, że na laptopie dewelopera wszystko jest zsynchronizowane od razu.

Brak demona synchronizacji

Najbardziej banalna i najczęstsza przyczyna. Na minimalnych obrazach serwerów demon synchronizacji czasu może nie być zainstalowany lub nie być uruchomiony. Maszyna startuje, pobiera czas z RTC, a dalej żyje na dryfującym kwarcu bez korekty. Dzień po dniu przesunięcie się kumuluje.

Szczególnie niebezpieczne są obrazy budowane ręcznie lub klonowane. Inżynier skonfigurował wszystko na maszynie wzorcowej, zrobił obraz, wdrożył na sto węzłów - a demon synchronizacji nie jest tam aktywowany. Sto węzłów zaczyna cicho rozchodzić się każdy w swoją stronę. Dopóki przesunięcie jest małe, wszystko działa. Po tygodniu najszybsze kwarce wychodzą poza okno tolerancji i dostajesz pływające, nieodtwarzalne awarie na części parku.

Ręczna korekta i zablokowany RTC

Czasem czas psuje człowiek. Ktoś ręcznie ustawił datę do testu i zapomniał przywrócić. Ktoś wyłączył synchronizację, bo przeszkadzała w konkretnym eksperymencie. Osobny problem - rozładowana bateria RTC na fizycznym serwerze: po restarcie zegar resetuje się do odległej przeszłości i do pierwszej synchronizacji TLS w ogóle nie działa.

Podwójne zarządzanie czasem

Subtelny przypadek, o którym się zapomina. Czasem o czas walczą jednocześnie dwa mechanizmy: agent gościa hiperwizora i demon synchronizacji wewnątrz systemu. Ciągną zegar w różne strony i dostajesz wahania czasu tam i z powrotem. Objawia się to jako przerywane awarie, których nie da się złapać. Zasada jest prosta: za czas powinien odpowiadać dokładnie jeden mechanizm.

Diagnostyka w minutę: stawiamy diagnozę szybko

Przejdźmy do praktyki. Twoim celem jest w sześćdziesiąt sekund zrozumieć, czy winny jest czas. Oto krok po kroku framework, którego używamy w Proxeon przy analizie incydentów.

Krok pierwszy: spójrz na swój czas w UTC

Przede wszystkim dowiedz się, co myśli twój zegar, właśnie w UTC, żeby wykluczyć zamieszanie ze strefą czasową:

date -u

Zapisz wartość. Teraz porównaj z wzorcem.

Krok drugi: porównaj z zewnętrznym źródłem

Najbardziej niezawodny sposób - zapytać serwer czasu w sieci o dokładny czas i zobaczyć przesunięcie. Jeśli zainstalowany jest chrony:

chronyc tracking

W wyjściu szukaj linii System time - pokazuje przesunięcie zegara systemowego względem wzorca. Wartość typu 0.000030 seconds to ideał. Jeśli systemd-timesyncd:

timedatectl show-timesync --all | grep -i offset

Jeszcze jeden szybki trik - jednorazowe zapytanie do serwera czasu bez zmiany zegara:

chronyd -Q 'server pool.ntp.org iburst'

Wydrukuje przewidywaną korektę. Jeśli jej moduł jest duży - masz odpowiedź.

Krok trzeci: sprawdź przez nagłówek HTTP Date

Wgląd, który oszczędza mnóstwo czasu. Prawie każdy serwer webowy zwraca w odpowiedzi nagłówek Date z aktualnym czasem w UTC. Porównaj go ze swoim zegarem bezpośrednio przez proxy:

curl -sI -x http://user:pass@gateway.proxeon.net:8080 https://example.com | grep -i ^date

Zestaw z date -u. Jeśli rozbieżność to sekundy - wszystko w porządku. Jeśli minuty - oto twoja przyczyna. Urok metody polega na tym, że nie wymaga zainstalowanych demonów i działa nawet wewnątrz gołego kontenera, gdzie nie ma nic oprócz curl.

Jaki rozrzut uznać za normę

Praktyczne punkty odniesienia wypracowane doświadczeniem:

  • Do 1 sekundy - doskonale, nic nie trzeba robić. Zdrowy zsynchronizowany system trzyma ułamki sekundy.
  • 1-5 sekund - akceptowalne dla TLS i większości JWT, ale już strefa uwagi. Podpisy żądań i TOTP na razie się trzymają, ale zapas topnieje.
  • 5-30 sekund - alarm. TOTP zaczyna zawodzić, wąskie okna podpisu zagrożone. Synchronizacja wyraźnie nie działa jak trzeba.
  • Więcej niż 30 sekund - krytycznie. Zawodzą podpisy, krótkotrwałe tokeny, a przy dużych przesunięciach także TLS. Natychmiast naprawiaj.
  • Minuty i godziny - katastrofa, zwykle skutek zamrożenia, snapshotu lub martwej baterii RTC.

Złota zasada: jeśli przesunięcie przekracza pięć sekund, czas należy traktować jako pierwszego podejrzanego we wszystkich awariach TLS, tokenów i podpisów.

Konfiguracja synchronizacji: żeby naprawdę działała

Zdiagnozować to za mało - trzeba wyleczyć i nie dopuścić do powtórki. Omówmy dwa główne narzędzia w Linuksie i, co najważniejsze, jak się upewnić, że synchronizacja jest rzeczywiście aktywna, a nie tylko zainstalowana. To kluczowa różnica, którą się pomija.

systemd-timesyncd: prosty wariant

Dla większości maszyn klienckich i lekkich węzłów wbudowany w systemd klient wystarcza. Wykonuje prostą synchronizację przez protokół czasu. Włączenie:

timedatectl set-ntp true

Sprawdzenie, że synchronizacja naprawdę trwa:

timedatectl status

Szukaj dwóch linii. System clock synchronized: yes oznacza, że system uważa się za zsynchronizowany. NTP service: active oznacza, że demon działa. Obie powinny być pozytywne. Jeśli synchronized: no przy active - demon uruchomiony, ale jeszcze nie zdołał połączyć się z serwerem albo ten jest niedostępny.

Szczegóły dotyczące konkretnego serwera:

timedatectl show-timesync --all

Tutaj widać, z jakim serwerem się połączono i jakie przesunięcie uzyskano. Właśnie ta komenda oddziela rzeczywiście działającą synchronizację od dekoracyjnej.

chrony: poważny wariant

Dla serwerów, gdzie ważna jest stabilność, zwłaszcza dla wirtualek z ryzykiem zamrożenia, preferowany jest chrony. Mądrzej znosi skoki czasu i szybciej zbiega po przestoju. Instalacja przez menedżer pakietów, potem uruchomienie usługi. Sprawdzenie pracy - główna komenda:

chronyc tracking

Analiza kluczowych linii wyjścia:

  • Reference ID - do jakiego źródła jesteśmy przywiązani. Jeśli jest tam 00000000 lub linia o tym, że źródło nie zostało wybrane, synchronizacji nie ma.
  • Stratum - poziom odległości od zegarów wzorcowych. Normalnie widzi się niewielką liczbę.
  • System time - aktualne przesunięcie zegara systemowego. To twój główny wskaźnik.
  • Last offset i RMS offset - niedawne i uśrednione korekty, pokazują stabilność.

Lista źródeł i ich stan:

chronyc sources -v

Symbol gwiazdki po lewej stronie serwera oznacza, że właśnie on został wybrany jako aktywne źródło. Jeśli żadne źródło nie ma oznaczenia wyboru, oznacza to, że demon jest zainstalowany, ale nie synchronizuje się - typowa pułapka.

Jak odróżnić zainstalowaną synchronizację od działającej

To ten wgląd, dla którego warto czytać ten rozdział. Fakt zainstalowania pakietu, a nawet fakt uruchomionej usługi, nie gwarantują synchronizacji. Usługa może się kręcić i nie mieć dostępu do serwerów czasu - na przykład firewall tnie pakiety wychodzące na właściwy port albo w zamkniętym środowisku nie ma wewnętrznego serwera czasu.

Prawdziwe sprawdzenie składa się z trzech pytań. Pierwsze: czy wybrano aktywne źródło? Patrz na oznaczenie w sources lub Reference ID w tracking. Drugie: jakie jest aktualne przesunięcie? System time powinno być w ułamkach sekundy. Trzecie: czy się aktualizuje? Uruchom sprawdzenie dwa razy w odstępie i upewnij się, że liczby są żywe, a nie zamarły. Jeśli wszystkie trzy odpowiedzi są pozytywne - synchronizacja działa naprawdę.

Monitoring przesunięcia jako metryka

Profesjonalne podejście - nie czekać na incydent, ale stale śledzić przesunięcie. Wyprowadzaj wartość System time do swojego systemu monitoringu jako zwykłą metrykę. Skonfiguruj ostrzeżenie przy przekroczeniu, powiedzmy, dwóch sekund i alarm przy pięciu. Wtedy dowiesz się o problemie, zanim posypią się podpisy i tokeny. Koszt takiego monitoringu jest bliski zeru, a zwrot ogromny: jeden zapobiegnięty nocny incydent uzasadnia wszystko.

Kontenery i zegary: co jest dziedziczone, a co nie

Konteneryzacja zasługuje na osobne głębokie omówienie, bo tu inżynierowie mają najwięcej nieporozumień. Rozłóżmy na czynniki, co kontener otrzymuje od hosta, a co nie.

Co jest dziedziczone: sam czas

Kluczowy fakt: kontener dzieli jądro hosta, a więc i zegar systemowy. Wewnątrz kontenera date -u pokaże dokładnie ten sam czas absolutny, co na hoście. Osobnego licznika czasu kontener nie ma. To fundamentalne. Stąd główny wniosek: żeby kontener widział prawidłowy czas, synchronizować trzeba hosta, a nie próbować konfigurować synchronizację wewnątrz kontenera.

Co nie jest dziedziczone: strefa czasowa

A wyświetlanie czasu to inna sprawa. Strefę czasową określają ustawienia wewnątrz kontenera, zwykle plik strefy i zmienna środowiskowa. Obraz bazowy często idzie z UTC, i to, nawiasem mówiąc, dobra praktyka dla serwerów. Jeśli wewnątrz kontenera czas lokalny wygląda inaczej niż na hoście - to prawie zawsze różnica stref czasowych, a nie rzeczywistego czasu. Sprawdź absolut przez UTC, zanim zaczniesz panikować.

Dlaczego nie należy uruchamiać demona czasu w kontenerze

Częsty błąd początkujących - wcisnąć demon synchronizacji do wnętrza kontenera. To nieprawidłowe z dwóch powodów. Po pierwsze, zmiana czasu systemowego to operacja uprzywilejowana, dotykająca całego jądra, a więc wszystkich kontenerów na hoście i samego hosta. Domyślnie kontenerowi jest to zabronione, i dobrze. Dawać to uprawnienie dla synchronizacji - to otwierać dziurę i tworzyć konflikt.

Po drugie, to po prostu niepotrzebne: czas już przychodzi od hosta. Prawidłowa architektura - jeden zsynchronizowany host, wiele kontenerów automatycznie widzących prawidłowy czas. Jeśli masz orkiestrator z wieloma węzłami, synchronizację trzeba zapewnić na każdym węźle-hoście, a nie w każdym podzie.

Pułapka laptopa dewelopera

Osobno ostrzeżemy o podstępnej sytuacji. Na laptopie dewelopera wszystko działa: kontenery widzą prawidłowy czas, bo system operacyjny stacji roboczej jest zsynchronizowany od razu. Inżynier buduje obraz, wszystko zielone. Obraz jedzie na serwer, gdzie host nie jest zsynchronizowany - i tam zaczynają się awarie. Lekcja: testuj zachowanie przy przesuniętym czasie, a nie tylko przy idealnym. Świadomie przesuń czas w środowisku testowym i zobacz, jak aplikacja reaguje.

Sprawdzenie czasu w działającym kontenerze

Szybka komenda, żeby zajrzeć do wnętrza uruchomionego kontenera i porównać jego czas absolutny:

docker exec -it my_container date -u

Jeśli zgadza się z date -u na hoście - wszystko w porządku, szukaj problemu gdzie indziej. Jeśli kontener jakimś cudem pokazuje inny czas absolutny, to sygnał o niestandardowej, potencjalnie niebezpiecznej konfiguracji, którą warto natychmiast przejrzeć.

Typowe błędy: czego nie należy robić

Doświadczenie z analizy incydentów układa się w listę grabi, na które się wchodzi w kółko. Przejdźmy przez nie, żebyś je ominął.

Błąd pierwszy: obwiniać proxy odruchem

Zaczęliśmy od tego i powtórzymy. Słowo certificate lub signature w błędzie przy pracy przez proxy automatycznie rodzi podejrzenie do sieci i bramy. Nie ulegaj. Pierwsze działanie przy tych błędach - porównać czas, a nie zmieniać endpoint. To zajmuje dziesięć sekund i odcina najczęstszą ukrytą przyczynę.

Błąd drugi: naprawiać strefę czasową zamiast czasu

Inżynier widzi dziwny czas lokalny w logach i przestawia strefę czasową. Objaw w logach się zmienia, ale kryptografia jak padała, tak pada, bo rzeczywisty czas absolutny w UTC pozostał przesunięty. Zawsze diagnozuj przez date -u i porównanie z wzorcem, a nie po lokalnym wyświetlaniu.

Błąd trzeci: uznawać instalację synchronizacji za rozwiązanie

Zainstalowałeś pakiet, zobaczyłeś, że usługa działa, zamknąłeś zadanie. Po tygodniu znowu awarie, bo usługa nie miała dostępu do serwerów czasu. Instalacja nie równa się synchronizacji. Zawsze sprawdzaj faktyczne przesunięcie i obecność wybranego źródła.

Błąd czwarty: twarda korekta zegara w biegu

Gwałtowny skok czasu systemowego komendą bezpośredniego ustawienia może zepsuć działające procesy, które polegają na monotoniczności czasu: wygasną timeouty, zerwą się sesje, wystąpią nieprawidłowe zadziałania planisty. Prawidłowo pozwolić demonowi synchronizacji doprowadzać zegar płynnie. Gwałtowna korekta dopuszczalna jest tylko przy ogromnym jednorazowym przesunięciu, i to świadomie.

Błąd piąty: ignorować zamrożenie wirtualek

Zespół nie uwzględnia, że migracje, snapshoty i wstrzymania tworzą jednorazowe przesunięcia. Dla takich środowisk potrzebny jest demon odporny na skoki i monitoring przesunięcia po operacjach serwisowych. Jeśli twoje awarie korelują czasowo z backupami lub migracjami - oto rozwiązanie.

Błąd szósty: podwójne zarządzanie czasem

Jednocześnie działają agent gościa hiperwizora i wewnętrzny demon. Zegar się szarpie, awarie są przerywane i nie odtwarzają się. Wybierz jeden mechanizm i wyłącz drugi. To leczy najbardziej wyczerpujące pływające bugi.

Błąd siódmy: zbyt wąskie okna bez zapasu

Jeśli tworzysz API z podpisem żądań, nie rób okna tolerancji trzydziestu sekund bez ważnego powodu. Rozsądny zapas kilku minut drastycznie zmniejsza wrażliwość na drobną desynchronizację klientów, nie rezygnując z ochrony przed powtórzeniem. Równowaga między surowością a odpornością to decyzja inżynierska, nie dogmat.

Narzędzia i zasoby

Zbierzmy arsenał, który warto mieć pod ręką. Wszystkie narzędzia są standardowe i legalne, do normalnej eksploatacji inżynierskiej.

Wiersz poleceń

  • date -u - natychmiastowy rzut oka na czas absolutny. Pierwsza komenda przy każdym podejrzeniu.
  • timedatectl - status synchronizacji i strefy czasowej w systemach z systemd.
  • chronyc tracking i chronyc sources - głęboka diagnostyka chrony: przesunięcie, źródła, stabilność.
  • curl -sI ... | grep -i date - porównanie czasu przez nagłówek HTTP odpowiedzi, działa nawet tam, gdzie nie ma demonów. Idealne dla gołych kontenerów i sprawdzania przez bramę.

Sprawdzenia językowe

  • W Pythonie: jedna linia z wyjściem utcnow i znacznika czasu do porównania prosto ze środowiska wykonawczego aplikacji.
  • W Node: jedna linia z toISOString i Date.now, żeby zobaczyć czas oczami właśnie twojego runtime'u.
  • Dekodowanie JWT bez weryfikacji podpisu, żeby na własne oczy zobaczyć pola exp, nbf, iat i zestawić je z aktualnym czasem. To usuwa domysły: dosłownie widzisz, czy token wygasł według twojego zegara, czy nie.

Co monitorować stale

  • Przesunięcie zegara systemowego jako metrykę liczbową z progami ostrzeżenia i alarmu.
  • Status obecności wybranego źródła czasu - wskaźnik boolowski zdrowia synchronizacji.
  • Częstotliwość błędów TLS i tokenów w podziale na węzły - skok na konkretnym węźle często wskazuje właśnie na jego przesunięty zegar.

Infrastruktura Proxeon

Przy pracy przez bramy Proxeon zalecamy wbudować sprawdzenie czasu w skrypt startowy twoich węzłów roboczych. Jedna linia porównania nagłówka Date przez bramę przy starcie - i złapiesz desynchronizację przed pierwszym roboczym żądaniem. To tanie i radykalnie zmniejsza udział fałszywych zgłoszeń do wsparcia, gdzie źródło okazuje się w zegarze strony klienta, a nie w proxy.

Case'y i wyniki

Teoria ożywa na prawdziwych historiach. Podajmy uogólnione case'y z praktyki - liczby zaokrąglone, szczegóły zanonimizowane, ale wzorce absolutnie realne.

Case pierwszy: nocny zawal parsera po backupie

Zespół zbierał dane przez proxy całodobowo. Każdej nocy około trzeciej zaczynała się ściana błędów certificate is not yet valid, nad ranem wszystko samo się naprawiało. Inżynierowie przez dwa tygodnie obwiniali pulę proxy, zmieniali endpointy, pisali skargi. Rozwiązanie przyszło, gdy ktoś zauważył korelację: awarie zaczynały się dokładnie w czasie nocnego backupu wirtualek.

Hiperwizor zamrażał VM na półtorej-dwie minuty dla zrobienia spójnego snapshotu. Po odmrożeniu zegar spóźniał się o te minuty, a agent gościa doprowadzał go nie od razu. W oknie między odmrożeniem a korektą TLS odrzucał świeże certyfikaty jako jeszcze nie ważne - bo według spóźnionego zegara zaczynały obowiązywać w przyszłości. Rozwiązaniem było przejście na chrony z szybkim zbieganiem po skoku i monitoring przesunięcia zaraz po operacjach backupu. Nocne awarie zniknęły całkowicie, czas diagnostyki przyszłych podobnych problemów skrócił się z dni do minut.

Case drugi: sto węzłów rozchodzących się w różne strony

Organizacja wdrożyła park stu węzłów roboczych z jednego obrazu. Pierwszy tydzień wszystko działało. Potem zaczęły się pływające awarie podpisów żądań na losowych węzłach - request timestamp too skewed. Nieodtwarzalne: restartujesz zadanie, może przejść na innym węźle.

Przyczyna - w obrazie nie była aktywowana synchronizacja czasu. Sto węzłów dryfowało każde po swoim kwarcu. Najszybsze w ciągu tygodnia wyszły poza okno tolerancji w podpisie. Masowe sprawdzenie chronyc tracking po całym parku pokazało przesunięcia od ułamków sekundy do piętnastu sekund. Po włączeniu i sprawdzeniu rzeczywistego działania synchronizacji na wszystkich węzłach, plus dodaniu metryki przesunięcia do monitoringu, awarie ustały. Wniosek zespołu: przy masowym wdrożeniu sprawdzać nie fakt instalacji, ale fakt synchronizacji.

Case trzeci: deweloper, którego nikt nie rozumiał

Jeden inżynier skarżył się, że lokalnie nie przechodzi mu autoryzacja przez TOTP w panelu zarządzania, choć u wszystkich działa. Kod wprowadza prawidłowy, system odrzuca. Podejrzewano problemy z jego kontem.

Okazało się, że tydzień wcześniej ręcznie przesunął czas systemowy na swojej stacji roboczej dla testu innej aplikacji i zapomniał przywrócić, a synchronizację przy tym wyłączył. Zegar wyszedł prawie o minutę. TOTP z oknem trzydziestu sekund przestał się zgadzać. Włączenie automatycznej synchronizacji natychmiast wszystko naprawiło. Morał: wąska tolerancja TOTP to wbudowany detektor desynchronizacji. Jeśli kody się nie zgadzają, najpierw spójrz na zegar.

Case czwarty: kontener z cudzą strefą czasową

W logach aplikacji w kontenerze czas szedł z trzechgodzinnym przesunięciem względem hosta. Inżynierowie uznali, że zegar kontenera jest przesunięty, i spędzili dzień na próbach skonfigurowania wewnątrz niego synchronizacji, omal nie dając kontenerowi zbędnych uprawnień.

Sprawdzenie date -u wewnątrz i na zewnątrz pokazało identyczny czas absolutny. Przesunięcie było czysto w wyświetlaniu: obraz bazowy miał jedną strefę czasową, host inną. Kryptografia przy tym działała bezbłędnie, bo w UTC wszystko się zgadzało. Rzeczywistego problemu nie było wcale - tylko kosmetyczne zamieszanie w logach. Lekcja kosztowała dzień pracy: zawsze rozróżniaj czas absolutny i jego wyświetlanie.

FAQ: głębokie odpowiedzi na częste pytania

Czy proxy samo może przesuwać mi czas lub podmieniać go w TLS?

W standardowych scenariuszach pracy przez bramę - nie. Proxy przekazuje bajty między tobą a serwerem docelowym. Sprawdzanie terminu certyfikatu, pól exp i nbf, okna podpisu odbywa się po twojej stronie lub po stronie serwera końcowego, opierając się na ich własnych zegarach. Dlatego przy błędach przypominających czasowe podejrzewać trzeba przede wszystkim lokalny zegar węzła roboczego, a nie bramę. Proxy jedynie wydłuża łańcuch i psychologicznie przesuwa podejrzenie ku środkowi.

Jak dokładnie musi chodzić czas, żeby wszystko działało?

Dla TLS zapas jest zwykle duży - tam okna ważności certyfikatów mierzy się w dniach, i nawet minutowe przesunięcie najczęściej przechodzi niezauważone, poza momentami u samej granicy odnowienia. Dla JWT wszystko zależy od czasu życia tokenu: przy krótkich tokenach już sekundy odgrywają rolę. Dla podpisów żądań typowe okno to minuty, ale lepiej trzymać przesunięcie w granicach sekundy. TOTP jest najbardziej wymagający - dziesiątki sekund. Uniwersalna rekomendacja: trzymaj przesunięcie w granicach jednej sekundy, wtedy jesteś zabezpieczony przed wszystkimi wymienionymi mechanizmami naraz.

Dlaczego certyfikat pokazuje ważne daty, ale klient mówi, że jeszcze nie jest ważny?

Ponieważ klient porównuje daty certyfikatu nie z absolutną prawdą, ale z twoim lokalnym zegarem. Jeśli twój zegar spóźnia się i pokazuje moment przed polem notBefore, dla klienta certyfikat jeszcze nie nastał. Daty w samym certyfikacie są przy tym idealne. Rozwiązanie zawsze tkwi w porównaniu twojego date -u z wzorcem. To najczęstsze źródło stuporu u inżynierów.

Czy trzeba instalować demon synchronizacji wewnątrz kontenera?

Nie. Kontener używa zegara jądra hosta, więc synchronizować trzeba hosta. Instalacja demona wewnątrz kontenera jest bezużyteczna i wymaga niebezpiecznych uprawnień do zmiany czasu systemowego, dotykających całego hosta. Prawidłowy model - zsynchronizowany host i wiele kontenerów automatycznie widzących prawidłowy czas. W orkiestratorze synchronizację zapewnia się na każdym węźle-hoście.

Jak odróżnić problem czasu od prawdziwego problemu proxy lub sieci?

Zacznij od sprawdzenia czasu - to dziesięć sekund. Porównaj date -u z wzorcem i z nagłówkiem HTTP Date przez twoją bramę. Jeśli przesunięcie jest małe, a błędy TLS i tokenów pozostają - wtedy przechodź do diagnostyki sieciowej. Jeśli przesunięcie jest duże - znalazłeś przyczynę. Kluczowy objaw problemów czasowych: błędy zawierają słowa not yet valid, expired, skewed, signature przy z pewnością żywych certyfikatach i świeżych tokenach.

Co robić zaraz po odmrożeniu lub migracji wirtualki?

Upewnij się, że demon synchronizacji szybko doprowadził zegar. Dla środowisk z zamrożeniami preferowany jest chrony, który dobrze znosi skoki. Sprawdź chronyc tracking i upewnij się, że System time wróciło do ułamków sekundy. Dobra praktyka - wymusić sprawdzenie przesunięcia po operacjach serwisowych i nie uruchamiać krytycznych podpisanych żądań, dopóki zegar się nie zbiegnie.

Czy nieprawidłowa strefa czasowa wpływa na działanie TLS i tokenów?

Nie, pod warunkiem, że czas absolutny w UTC jest prawidłowy. Cała kryptografia operuje na UTC, a strefa czasowa to tylko wyświetlanie dla człowieka. Nieprawidłowa strefa czasowa wprowadzi cię w błąd w logach, ale nie położy TLS, JWT ani podpisu. Właśnie dlatego diagnozować trzeba przez UTC, a nie przez czas lokalny. Mieszanie strefy czasowej i czasu absolutnego to klasyczna pułapka.

Jak wbudować sprawdzenie czasu w workflow przez proxy?

Dodaj do skryptu startowego węzła jedną linię porównania: zapytaj o nagłówek Date przez twoją bramę Proxeon i porównaj z lokalnym date -u. Przy rozbieżności większej niż próg zatrzymaj uruchamianie i podnieś alarm. Plus wyprowadź przesunięcie zegara systemowego do monitoringu jako stałą metrykę z progami. Te dwa środki wychwytują przytłaczającą większość incydentów czasowych, zanim zamienią się w awarie TLS i tokenów.

Dlaczego otrzymuję

O autorze

Andrey Kokh

Andrey Kokh

Leading Expert and Business Consultant

Doświadczenie zawodowe: Leading expert with 12 years of experience. Consults Forbes-listed companies, author of 3 books. Teaches at HSE and SKOLKOVO. His methodologies are used by hundreds of companies across Russia. RBC and Forbes expert on strategic development and digital transformation.
Wykształcenie: Higher School of Economics. Faculty of Economics, Master's Program
Ekspertyza:
Strategic Consulting Digital Transformation Change Management Business Strategy Innovation Management Organizational Development Lean Management Agile Transformation

Podziel się artykułem: