Wybierz swój język

Podstawy sieci z Cisco IOS. Moduł 4: NTP (Network Time Protocol)

Czas jest jednym z ważniejszych elementów systemu IT. Jego nieprawidłowa konfiguracja, to duża ilość informacji, które ciężko ze sobą powiązać, trudności w wyszukiwaniu i lokalizacji źródeł incydentów, trudności w diagnozowaniu i rozwiązywaniu problemów, niemożliwość uruchomienia niektórych funkcjonalności czy szereg problemów wynikłych z nieprawidłowej ważności certyfikatów.

To niby nic skomplikowanego. Wystarczy pamiętać o konfiguracji czasu. Niemniej, kiedy mamy do czynienia z ciągle rosnącą ilością urządzeń sieciowych, serwerów usługowych, aplikacji, stacji końcowych i urządzeń przyłączanych do sieci IP (np. telefony, kamery, sensory czy roboty), oraz z urządzeniami ulokowanymi w różnych regionach świata (różne strefy czasowe), czy też potrzebą okresowej kontroli czasu i jego ewentualnej zmiany w celu zachowania synchronizacji, to robi się z tego niemałe wyzwanie.

Do synchronizacji czasu w "świecie IP" wykorzystuje się protokół NTP (Network Time Protocol). Obecnie powszechnie stosowany jest NTP w wersji 3 i 4 (NTPv3 i NTPv4), które zostały zdefiniowane odpowiednio w dokumentach RFC 1305 i RFC 5905. Wykorzystuje on strukturę warstwową (ang. stratum), gdzię serwery NTP w stratum N świadczą usługę dla serwerów NTP w stratum N+1 i mogą być jednocześnie klientami serwerów NTP stratum N-1. Stratum określa odległość od źródła czasu i może przyjmować wartości od 0 do 15, gdzie stratum 0 oznacza zegar atomowy. Wartość 16 oznacza brak synchronizacji. Protokół NTP korzysta z portu 123/UDP.


Przesyłanym przez NTP czasem wzorcowym, jest koordynowany czas uniwersalny UTC (Coordinated Universal Time). UTC jest międzynarodowym standardem do określania czasu oraz stref czasowych. Stosuje on bardzo precyzyjny zegar atomowy oraz koordynowany jest względem czasu słonecznego. Czas UTC zapisywany jest w formacie 24 godzinnym i stosuje kalendarz gregoriański. Nie ma w nim żadnych przesunięć związanych ze zmianą pory roku. Przez pilotów i wojsko jest on nazywany "czasem Zulu". Czas UTC odnosi się do czasu na południku zerowym. “Z” od zero, w alfabecie fonetycznym NATO oznacza Zulu.

O ile czas UTC jest czasem na południku zerowym, to nie należy mylić go z czasem GMT (Greenwich Mean Time) czy obecnie już może bardziej panującą tam strefą czasową GMT. Istnieje kilka drobnych różnic w wyliczaniu tych dwóch czasów. Dla przykładu UTC stosuje tak zwane sekundy skokowe (ang. leap seconds), a w GMT mamy uśrednione sekundy słoneczne (ang. mean solar seconds). Sekunda w czasie UTC wyznaczana jest przez zegar atomowy i trwa zawsze tyle samo, podczas gdy sekunda w czasie GMT bazuje na lekko zmiennych, okresowych obrotach Ziemi. W roku 1884 została określona długość geograficzna zero w miejscu, gdzie znajduje się obserwatorium w Greenwich (Londyn, Anglia). Mean Time w nazwie strefy GMT oznacza czas uśredniony, jako iż bazuje on na uśrednionych sekundach, powiązanych z cyklicznymi obrotami Ziemi czy też podróżą Słońca na niebie. W każdym razie, czas GMT przez wielu uznawany jest za przestarzały i nieprecyzyjnie zdefiniowany, stąd lepiej się do niego nie odnosić.

Prawie każdy dzień w czasie UTC składa się z 86,400 sekund, a prawie każda minuta ma 60 sekund. Ze względu na nieregularność ruchu ziemi względem słońca oraz potrzebę kompensacji tej różnicy, zostało wprowadzone pojęcie sekundy skokowej (ang. leap second). Jej zadaniem jest wyrównanie naszego czasu do czasu słonecznego, a właściwie do czasu UT1 (Universal Time). Różnica ta, tak zwane DUT1 (Delta Universal Time), nie powinna być większa niż +-0.9 sekundy. Dopuszcza się zatem minuty o 59 lub 61 sekundach. Takie przesunięcia są bardzo rzadkie i odbywają się po wcześniejszej zapowiedzi. Niestety, skokowe sekundy utrudniają wyliczenie czasu pomiędzy dwoma znacznikami czasu UTC. Wymusza to dodatkową weryfikację tablic, zawierających wprowadzone w tym okresie sekundy skokowe. Jest to powodem, dla którego wiele wyliczeń naukowych korzysta z czasu atomowego TAI (International Atomic Time). Czas TAI posiada stałą oś czasową, co ułatwia wyliczenia w których brane pod uwagę są okresy wieloletnie. Z każdą dodatkową sekundą skokową, czas TAI oddala się od czasu UTC.

Sekundy skokowe wymagają odpowiedniej obsługi przez protokoły służące do synchronizacji czasu. Protokół NTP, w polach swojego nagłówka posiada dwubitowe pole LI (Leap Indicator), które definiuje ilość sekund w ostatniej minucie danego dnia:

  • 60 sekund to binarnie 00 (zero, zero),
  • 61 sekund to binarnie 01 (zero, jeden),
  • 59 sekund to binarnie 10 (jeden, zero),
  • sytuacja awaryjna, brak synchronizacji 11 (jeden, jeden).

Sam czas w nagłówku NTP zapisywany jest jako liczba 64 bitowa, ze stałą kropką. Pierwsze 32 bity oznaczają ilość sekund od 1 stycznia 1900 roku, a drugie 32 bity są częściami sekundy.


Konfigurując urządzenia sieciowe, serwery usługowe czy różne platformy hostingowe, należy pamiętać o prawidłowej konfiguracji zarówno protokołu NTP, jak i stref czasowych. W rozległej na cały świat sieci IP, protokół NTP zajmuje się synchronizacją czasu uniwersalnego (UTC). Natomiast odpowiednia strefa czasowa dostosowuje go do naszych lokalnych potrzeb.

Kiedy już posiadamy czas wzorcowy (czas UTC), musimy jeszcze uwzględnić właściwą strefę czasową, w której się znajdujemy. Strefy czasowe, przedstawiane są jako pozytywne lub negatywne przesunięcia względem UTC. Stąd, w zależności od położenia i wynikającej z tego przynależności do strefy, dodawane lub odejmowane jest odpowiednie przesunięcie czasowe. W systemie Cisco IOS do określania strefy czasowej i jej przesunięcia względem UTC służy polecenie trybu konfiguracji globalnej: "clock timezone".

W zależności od regionu świata, oprócz konfiguracji odpowiedniej strefy czasowej, może być także potrzebne określenie terminu obowiązywania czasu letniego. Służy do tego polecenie trybu konfiguracji globalnej: "clock summer-time".

Załóżmy, że jesteśmy zlokalizowani w Polsce. Korzysta się tutaj z dwóch stref czasowych: CET (Central European Time) i CEST (Central European Summer Time). Odpowiadają one odpowiednio czasowi słonecznemu południka 15ºE i 30ºE. Decyzja przyjęcia określonej strefy czasowej nie jest związana tylko z położenie względem linii meridian ziemi. Dodatkowo brane pod uwagę są kryteria polityczno ekonomiczne. CET reprezentuje czas środkowoeuropejski, który jest o jedną godzinę przesunięty do przodu względem czasu UTC. Przesunięcie to często zapisywane jest jako +01:00, dając zapis UTC+01:00. Czas ten wykorzystywany jest w okresie zimowym. W okresie letnim, dla lepszego wykorzystania światła słonecznego, następuje przesunięcie czasowe o dodatkowo jedną godzinę do przodu. Daje to sumarycznie UTC+02:00, co określane jest jako CEST. Odnosząc się do czasu UTC, czas CET w tym regionie obowiązuje do godziny 01:00 ostatniej niedzieli marca, a czas CEST do godziny 01:00 ostatniej niedzieli października. Można też spotkać alternatywne nazwy dla CEST, jak stosowana w Anglii nazwa CEDT (Central European Daylight Saving Time) lub w Niemczech MESZ (Mitteleuropäische Sommerzeit). Ogólnie CET nie jest jedynym określeniem dla czasu UTC+01:00, tak samo jak CEST dla czasu UTC+02:00. Istnieją inne strefy czasowe, które mają takie samo przesunięcie względem czasu UTC.

Na slajdzie powyżej można prześledzić sposób konfiguracji strefy czasowej CET i CEST zgodnie z opisanymi wyżej wytycznymi dla urządzenia zlokalizowanego w Polsce. Czas podawany w poleceniu "clock summer-time" jest zawsze czasem lokalnym, a nie czasem UTC. Zatem pierwszą wartością będzie data i godzina zgodna z czasem standardowym, czyli naszym czasem zimowym, inaczej czasem CET. Drugą wartośią będzie data i godzina zgodna już z naszym czasem letnim, czyli czasem CEST. Wynika to z tego, że w momencie przejścia z czasu letniego na zimowy, obowiązującym czasem lokalnym będzie jeszcze czas letni.


Konfiguracja czasu na pewno nie jest niczym ekscytującym czy czymś, na co chcielibyśmy poświęcić zbyt dużo czasu. W końcu jest tyle bardziej zaawansowanych, złożonych i interesujących technologii, którymi też trzeba się zająć, oraz oczywiście bardziej godnych nas wyzwań i problemów. Kto by sobie zawracał głowę jakimś czasem. Niemniej z doświadczenia wiemy, że w wielu środowiskach IT tak prosta rzecz potrafi być kompletnie źle ustawiona. W szczególności na urządzeniach sieciowych. Dotyczy to także dużych środowisk wielu poważnych instytucji, z którymi mieliśmy w naszej historii styczność. Nieraz już dostawaliśmy do analizy logi z różnych urządzeń i systemów, które nie dość, że nie miały poprawnie zsynchronizowanego czasu, to jeszcze miały błędnie i niespójnie poustawiane strefy czasowe i przejścia na czas letni. Pomijając to czy takie logi mają jakąś wartość i będzie dało się je potem gdzieś prawnie wykorzystać, jakakolwiek analiza czy diagnoza zajmowała przez to o wiele więcej czasu i nie prowadziła do żadnych sensownych wniosków. Wszystko się rozjaśniało dopiero jak uzyskaliśmy dostęp do urządzeń i ich ustawień czasu.


W module 1 omówiliśmy już przykład konfiguracji daty i czasu zegara systemowego w Cisco IOS. Czas ten można zweryfikować z użyciem polecenia trybu EXEC: "show clock". Jest to czas programowy, który zostanie zresetowany wraz z restartem urządzenia.

W większości urządzeń znajduje się także zegar sprzętowy, podtrzymywany bateryjnie. Wartość jego czasu można odczytać z użyciem polecenia trybu EXEC: "show calendar". Aby nasz czas programowy został zapisany w zegarze sprzętowym, należy użyć polecenia trybu EXEC: "clock update-calendar". Jeżeli po restarcie urządzenia zmodyfikowaliśmy czas programowy i chcielibyśmy przywrócić mu czas bazujący na zegarze sprzętowym, to należy użyć polecenia trybu EXEC: "clock read-calendar".

Używając polecenia trybu EXEC: "show clock detail" możemy zobaczyć zarówno źródło czasu, jak i konfigurację stref czasowych oraz przejścia pomiędzy czasem letnim i zimowym. W naszym przypadku źródłem czasu jest początkowo ręczna konfiguracja użytkownika (żółtawe tło), a następnie zegar sprzętowy (fioletowawe tło).


Aby korzystać z NTP potrzebne jest nam autorytatywne źródło czasu. Nie zawsze mamy dostępu do zewnętrznych serwerów NTP, by podpiąć się do istniejącej struktury warstw (ang. stratum). Przykładem może być sala szkoleniowa czy laboratorium. W takim przypadku możemy sprawić, aby to wewnętrzny zegar naszego urządzenia był uznawany za autorytatywne źródło czasu. Dokonać tego można z użyciem polecenia trybu konfiguracji globalnej: "ntp master". Na końcu polecenia można opcjonalnie wskazać wartość stratum jego wewnętrznego zegara (domyślnie jego wartość to 7, stąd nasze urządzenie będzie w stratum 8). W związku z tym, że czas programowy nie jest uznawany za wiarygodne źródła czasu, wcześniej należy wskazać nasz zegar sprzętowy, jako autorytatywne źródło czasu. Służy do tego polecenie trybu konfiguracji globalnej: "clock calendar-valid".

Referencyjny serwer NTP, stratum w jakim działa nasze urządzenie i stan synchronizacji można sprawdzić z użyciem polecenia trybu EXEC: "show ntp status". Warto zwrócić uwagę na powyższy slajd. Początkowo nasz zegar nie był w synchronizacji (niebieskawe tło), po czym się to zmieniło (żółtawe tło). Widać tam też zarówno stratum urządzenia, jak i adres IP wybranego serwera NTP. Informacje o ustawionych serwerach NTP można uzyskać z użyciem polecenia trybu EXEC: "show ntp associations". Na powyższym zrzucie poleceń widać zarówno wartość stratum wewnętrznego zegara, jak i jego adres IP (zielonawe tło).

W trakcie diagnozy przydatne bywa także polecenie trybu EXEC: "show ntp packets". Pokazuje ono informacje o odebranych i wysłanych pakietach NTP, w tym również informacje o odebranych pakietach z błędami lub w błędnej wersji. Polecenie trybu EXEC: "show ntp information" pokazuje informacje o działającej wersji protokołu NTP.


Dobrą praktyką jest konfiguracja czy wskazanie minimum trzech serwerów NTP. Najczęściej wybiera się 3-5 urządzeń lub serwerów wewnątrz infrastruktury do takiej funkcji. Czasem jest to nawet oddzielne 3-5 serwerów NTP dla urządzeń sieciowych i systemów obsługujących infrastrukturę oraz oddzielne 3-5 serwerów NTP dla urządzeń końcowych. Większa ilość serwerów NTP pozwala zminimalizować ryzyko wykorzystania złego czasu na skutek awarii czy kompromitacji jednego z serwerów NTP. Serwery te powinny zostać podłączone do istniejącej struktury warstwowej NTP. W najlepszym scenariuszu do zegara atomowego, źródła czasu korzystającego z GPS czy innego specjalistycznego urządzenia pełniącego tę funkcję. Niemniej, najczęściej podłącza się je do publicznie dostępnych serwerów NTP, które często są darmowe, jeżeli nie chcemy korzystać z funkcji uwierzytelnienia źródła.

NTP może działać w kilku trybach. Tryb klienta konfigurowany jest poprzez zdefiniowanie serwerów NTP. Służy do tego polecenie trybu konfiguracji globalnej: "ntp server", po którym trzeba podać adres IP lub nazwę domenową serwera NTP. Aby wskazać kilka serwerów NTP, należy to polecenie kilkukrotnie powtórzyć z innymi parametrami. Warto jednak pamiętać, że urządzenie będące klientem NTP automatycznie staje się również serwerem NTP. Konfigurację tego trybu widać na powyższym zrzucie poleceń.

W ramach trybu symetrycznego (ang. symetric active mode) obie strony mogą pełnić względem siebie zarówno funkcję serwera, jak i klienta. O ile synchronizacja możliwa jest w obu kierunkach, to może odbywać się tylko w jednym w danej chwili. Zatem, któryś z serwerów musi zostać uznany za ten lepszy. Tryb ten często stosowany jest na równorzędnych serwerach czasu w ramach jednej infrastruktury, gdzie każdy z serwerów posiada różne łącza do sieci Internet lub ma wskazane inne źródła czasu. W ten sposób, jeżeli któryś z serwerów straci dostęp do lepszych źródeł czasu, zawsze będzie mógł skorzystać z czasu, jaki udostępnia serwer równorzędny. Do konfiguracji tego trybu służy polecenie trybu konfiguracji globalnej: "ntp peer".

Aby wskazać interfejs źródłowy dla usługi NTP należy użyć polecenia trybu konfiguracji globalnej: "ntp source". Pakiety generowane przez usługę NTP będą stosować źródłowy adres IP z tego interfejsu. Domyślnie do tego celu stosowany jest interfejs, który zgodnie z tablicą routingu udostępnia najlepszą drogę w kierunku docelowego adresu IP.

Dostępny jest też tryb rozgłoszeniowy. Nie jest on obecnie popularny. Charakteryzuje się on mniejszą dokładnością czasu. Aczkolwiek jest mniej obciążający dla serwera, co przy dużej ilości klientów może mieć znaczenie. Klienci biernie nasłuchują pakietów NTP wysyłanych przez serwer. Aby go uruchomić, należy w trybie konfiguracji wybranego interfejsu serwera NTP użyć polecenia: "ntp broadcast", a w trybie konfiguracji interfejsu klienta NTP polecenia: "ntp broadcast client".

Jeżeli NTP nie jest nam potrzebne, można całkowicie wyłączyć tę usługę z użyciem polecenia trybu konfiguracji globalnej: "no ntp".

Tryby działania NTP (server, client, peer) zostały zobrazowane na pierwszym slajdzie, stąd warto do niego na tym etapie wrócić.


Szczegółową weryfikację serwerów NTP można przeprowadzić z użyciem polecenia trybu EXEC: "show ntp associations detail". Każda z 8 widocznych tam próbek czasu zawiera informacje o opóźnieniu w obie strony "filtdelay" w milisekundach, przesunięciu zegara "filtoffset" w milisekundach i przybliżonym błędzie "filterror". Warto też zwrócić uwagę na to, czy dane źródło czasu przeszło testy weryfikacyjne i uznawane jest za rozsądne (ang. sane) czy też nie (ang. insane). Czy jego czas jest akceptowalny (ang. valid) czy nieakceptowalny (ang. invalid) oraz wartościom "our conf", "peer conf", "our mode" i "peer mode", które pokazują skonfigurowane tryby i stany obu stron relacji oraz zostały opisane w tabeli widocznej w lewym dolnym rogu poniższego slajdu.

Sposób wyboru najlepszego źródła czasu zależny jest od efektu działania algorytmu stosowanego przez NTP, który bierze pod uwagę m.in. to czy źródło jest zsynchronizowane, jego poziom stratum, opóźnienia sieciowe oraz dokładność czasu i jego korelację z innymi źródłami. Istnieje także możliwość zwiększenia preferencji podczas oceny źródła. Dokonać tego można z użyciem parametru "prefer" poleceń trybu konfiguracji globalnej: "ntp server" i "ntp peer".


Domyślnie NTP jest wyłączone i nie przetwarza pakietów NTP na żadnym z interfejsów. Niemniej, po uruchomieniu usługi NTP zaczyna przetwarzać pakiety NTP na wszystkich interfejsach. Dodatkowo nasze urządzenie stanie się serwerem NTP, kiedy tylko uruchomimy usługę NTP w trybie klienta i nasze urządzenie dołączy do struktury warstwowej NTP. W ten sposób usługa serwera NTP naszego urządzenia stanie się dostępna poprzez wszystkie jego interfejsy. Aby wyłączć przetwarzanie pakietów NTP na wybranym interfejsie należy użyć polecenie trybu konfiguracji danego interfejsu: "ntp disable".

Kiedy urządzenie ma już dobry czas, warto skonfigurować synchronizację zegara sprzętowego z usługą NTP. Domyślnie nie jest to realizowane, stąd po restarcie urządzenia ponowna synchronizacja może zająć więcej czasu. Dokonać tego można z użyciem polecenia trybu konfiguracji globalnej: "ntp update-calendar".

Czas jest jedną z krytycznych usług systemu informatycznego. Dlatego dobrze jest logować informacje o wszelkich zdarzeniach powiązanych z utratą synchronizacji czy komunikacji do serwerów NTP. Aby takie zdarzenia były logowane przez usługę Syslog, należy użyć polecenia trybu konfiguracji globalnej: "ntp logging". Przykłady takich komunikatów widać na powyższym zrzucie poleceń, gdzie usługa NTP traci dostęp do serwera NTP (niebieskawe tło), a następnie synchronizację czasu (zielonawe tło).

Po utracie synchronizacji czasu, przed czasem pojawiała się kropka "." (czerwonawe tlo). Nie było jej, kiedy wcześniej użyliśmy polecenia trybu EXEC: "show clock" lub "show clock detail". Na początku znacznika czasowego mogą pojawić się:

  •  [nic] – zegar został ustawiony ręcznie lub jest w synchronizacji z serwerem NTP,
  • * [gwiazdka] – zegar nie został ustawiony lub nie jest w synchronizacji z serwerem NTP,
  • . [kropka] – zegar był zsynchronizowany, ale utracił kontakt z serwerem NTP.

Warto prześć przez wcześniejsze slajdy i zwrócić uwagę na wynik użycia tych poleceń.


Usługa NTP korzysta z dwóch kategorii wiadomości. NTP Control służą do weryfikacji i zmiany wartości procesu NTP (à la SNMP, ale dotyczy tylko usługi NTP), a NTP Request/Update służą do synchronizacji czasu. Zamiast blokować przetwarzanie wszystkich wiadomości NTP na poszczególnych interfejsach, możemy wybiórczo zezwolić na to, co w danym scenariuszu uznamy na zasadne. Służy do tego mechanizm NTP Access Control.

Kontrola dostępu z użyciem mechanizmu NTP Access Control wyróżnia 4 typy dostępu, które można wskazać w poleceniu trybu konfiguracji globalnej: "ntp access-group":

  1. peer – odpowiada na NTP Request i przyjmuje NTP Update oraz zapytania NTP Control.
  2. serve – odpowiada na NTP Request oraz przyjmuje NTP Control. Nie przyjmuje NTP Update.
  3. serve-only – odpowiada na NTP Request. Nie przyjmuje  NTP Update i NTP Control.
  4. query-only – przyjmuje tylko NTP Control. Nie odpowiada na NTP Request i nie przyjmuje NTP Update.

Do każdego z tych 4 typów kontroli można przypiąć listę kontroli dostępu ACL (Access Control List). Stosuje się tutaj standardowe listy kontroli dostępu, jako że wskazujemy tylko kto może wysyłać wybrane rodzaje komunikatów do usługi NTP.

Typy dostępu sprawdzane są w kolejności od 1 do 4. Przydzielany jest dostęp na podstawie pierwszego dopasowania. Jeżeli chociaż jeden typ dostępu został określony, pozostałe są niejawnie zabronione. Istnieje zarówno możliwość akceptacji/odrzucania pakietów NTP, jak i odmowy dostępu poprzez wysłanie specjalnego pakietu "kod" – Kiss-of-Death (opcjonalny parametr "kod").


Funkcja NTP Authentication obsługuje uwierzytelnienia źródła czasu. Jest to tylko uwierzytelnienie serwera lub lepszego peer'a, a nie klienta. Informacje uwierzytelnienia dołączane są do komunikatu NTP przez źródło czasu. Druga strona może, ale nie musi ich weryfikować. W fioletowym obramowaniu widać konfigurację serwera NTP z funkcją uwierzytelnienia. W zielonym obramowaniu widać konfigurację klienta NTP z funkcją uwierzytelnienia, a w czerwonym konfigurację klienta bez uwierzytelnienia.

W konfiguracji NTP Authentication początek jest taki sam dla klienta i serwera NTP. Należy włączyć uwierzytelnienie z użyciem polecenia trybu konfiguracji globalnej: "ntp authentication". Następnie w tym samym trybie zdefiniować klucz i dodać go do zbioru zaufanych kluczy. Służą do tego odpowiednio polecenia "ntp authentication-key" i "ntp trusted-key". Tak skonfigurowany serwer NTP może obsługiwać zarówno klientów z włączoną funkcją NTP Authentication, jak i bez niej. Dodatkowo, kiedy konfigurujemy klienta NTP, należy dla każdego z serwerów wskazać używany klucz z użyciem parametru "key" polecenia trybu konfiguracji globalnej: "ntp server". Zwykle każdy z zewnętrznych serwerów NTP będzie miał dla nas swój unikalny klucz.

O ile na slajdzie widać tylko konfigurację uwierzytelnienia z użyciem MD5, to w nowszych modelach urządzeń dostępne są także bardziej bezpieczne mechanizmy, jak m.in. CMAC-AES-128, HMAC-SHA1 i HMAC-SHA2-256.


Przed kolejną porcją wiedzy zachęcamy do przećwiczenia i utrwalenia tej poznanej tutaj. Skorzystaj z naszych ćwiczeń!


Zachęcamy do śledzenia nas w mediach społecznościowych Facebook i LinkedIn.


Zapraszamy do kontaktu drogą mailową Ten adres pocztowy jest chroniony przed spamowaniem. Aby go zobaczyć, konieczne jest włączenie w przeglądarce obsługi JavaScript. lub telefonicznie +48 797 004 932 lub +48 797 004 938.