Più la domanda è semplice, più spesso sbaglio.

Più la domanda è semplice, più spesso sbaglio.

Questo compito triviale è emerso in un venerdì e avrebbe dovuto richiedere 2-3 minuti di tempo. Insomma, come al solito.

Un collega mi ha chiesto di sistemare uno script sul suo server. L'ho fatto, glielo ho passato e ho fatto involontariamente notare: «Il tempo corre di 5 minuti». È il suo server, che si occupi da solo della sincronizzazione. Sono passati mezz'ora, un'ora, e lui continua a brontolare e a imprecare sottovoce.

«Stupido!», pensai, cambiando al terminale. server «Va bene, mi prendo ancora un paio di minuti.»

Vediamo, ntp, rdate, sdwdate non sono installati, timesyncd è disattivato e non in esecuzione.

# timedatectl
      Local time: Sun 2019-08-25 20:44:39 +03
  Universal time: Sun 2019-08-25 17:44:39 UTC
        RTC time: Sun 2019-08-25 17:39:52
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Qui segnalo subito che l'orario hardware è corretto: sarà più facile orientarsi in seguito.

Da qui è iniziata una serie di errori.

Primo errore. Troppa sicurezza.

Click-click...

# systemctl enable systemd-timesyncd.service && systemctl start systemd-timesyncd.service && ntpdate 0.ru.pool.ntp.org && timedatectl set-ntp on && timedatectl
25 Aug 21:00:10 ntpdate[28114]: adjust time server 195.210.189.106 offset -249.015251 sec
      Local time: Sun 2019-08-25 21:00:10 +03
  Universal time: Sun 2019-08-25 18:00:10 UTC
        RTC time: Sun 2019-08-25 18:00:10
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

Tutto perfetto, il tempo è sincronizzato, quello di sistema corrisponde a quello hardware. «Prendi», dissi e tornai ai miei affari.

«Cosa prendo?», si indignò il collega. «Il tempo è lo stesso!»

Più si risolvono compiti standardizzati, più il pensiero si rinchiude e non si pensa che la centesima o millesima situazione sarà diversa, ma non questa volta.

# timedatectl
      Local time: Sun 2019-08-25 21:09:15 +03
  Universal time: Sun 2019-08-25 18:09:15 UTC
        RTC time: Sun 2019-08-25 18:05:04
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

L'ora di sistema è di nuovo sbagliata.

Proviamo ancora:

# ntpdate 0.ru.pool.ntp.org && timedatectl && sleep 1 && timedatectl
25 Aug 21:07:37 ntpdate[30350]: step time server 89.175.20.7 offset -249.220828 sec
      Local time: Sun 2019-08-25 21:07:37 +03
  Universal time: Sun 2019-08-25 18:07:37 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:11:46 +03
  Universal time: Sun 2019-08-25 18:11:46 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Facciamo diversamente:

# date -s "2019-08-25 21:10:30" && date && sleep 1 && timedatectl
Sun Aug 25 21:10:30 +03 2019
Sun Aug 25 21:10:30 +03 2019
      Local time: Sun 2019-08-25 21:14:36 +03
  Universal time: Sun 2019-08-25 18:14:36 UTC
        RTC time: Sun 2019-08-25 18:10:30
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

E così:

# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:11:31 +03
  Universal time: Sun 2019-08-25 18:11:31 UTC
        RTC time: Sun 2019-08-25 18:11:31
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:15:36 +03
  Universal time: Sun 2019-08-25 18:15:36 UTC
        RTC time: Sun 2019-08-25 18:11:32
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

L'ora si imposta in una frazione di secondo e poi inizia subito a «correre» di nuovo.

Tuttavia, nei log, al momento di questa modifica manuale, vediamo solo rapporti del sistema, che l'orario è cambiato, rispettivamente in direzioni corrette/errate e occasionalmente Resyncing da systemd-timesyncd.

Aug 25 21:18:51 wisi systemd[1]: Il tempo è stato cambiato
Aug 25 21:18:51 wisi systemd-timesyncd[29258]: L'ora di sistema è cambiata. Resyncing.
Aug 25 21:18:51 wisi systemd[1187]: Il tempo è stato cambiato
Aug 25 21:18:51 wisi systemd[1]: Il tempo è stato cambiato
Aug 25 21:18:51 wisi systemd[1187]: Il tempo è stato cambiato

qui

# ps afx | grep "[1]187"
 1187 ?        Ss     0:02 /lib/systemd/systemd --user

In questo momento bisognava già cercare la causa, ma il cervello, dopo 18 anni di amministrazione, ha accumulato statistiche degli errori di «tempo» e per abitudine accusa di nuovo la sincronizzazione.
La disattiviamo completamente.

# timedatectl set-ntp off && systemctl stop systemd-timesyncd.service
# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:25:40 +03
  Universal time: Sun 2019-08-25 18:25:40 UTC
        RTC time: Sun 2019-08-25 18:25:40
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:29:31 +03
  Universal time: Sun 2019-08-25 18:29:31 UTC
        RTC time: Sun 2019-08-25 18:25:41
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

e nei log

Aug 25 21:25:40 wisi systemd[1]: Il tempo è stato cambiato
Aug 25 21:25:40 wisi systemd[1187]: Il tempo è stato cambiato
Aug 25 21:29:30 wisi systemd[1]: Il tempo è stato cambiato
Aug 25 21:29:30 wisi systemd[1187]: Il tempo è stato cambiato

Resyncing è scomparso e gli altri log sono immacolati.

Controlliamo i risultati tcpdump sul porto 123 su tutte le interfacce. Non ci sono richieste, ma il tempo continua a «scappare».

Secondo errore. Fretta.

Manca un'ora alla fine della settimana lavorativa e non voglio lasciare per il weekend un compito trascurato (non badare all'ora nel codice, l'articolo è stato scritto nei giorni successivi).
E qui di nuovo, invece di cercare la causa, ho iniziato a cercare di inventare una spiegazione per il risultato. Dico "inventare" perché, nonostante tutte le spiegazioni logiche possibili per il risultato, questo è un approccio sbagliato per risolvere il problema.

Questo server è un server di streaming e converte il flusso DVB-S2 in IP. Nel flusso DVB-S sono presenti timestamp, quindi i ricevitori, i multiplex, gli scrambler e i televisori li utilizzano spesso per sincronizzare gli orologi di sistema. I driver DVB-S delle schede sono compilati nel kernel, quindi il modo più veloce per rimuovere garantitamente il flusso DVB-S2 è scollegare i cavi provenienti dalle "antenne". Fortunatamente, il server è dietro il muro, quindi così sia.

Certo, se nei log ci fosse stato ciò che doveva esserci, non sarebbe successo, ma di questo parleremo, ancora una volta, alla fine dell'articolo.

E poiché abbiamo già rimosso tutti i segnali satellitari, rimuoviamo anche quelli terrestri — estraiamo al contempo tutti i cavi di rete. Il server diventa isolato dal mondo esterno e funziona in modo completamente autonomo, ma gli orologi di sistema continuano a girare avanti.

La settimana lavorativa è finita, e la questione della data/ora su di esso non è critica, quindi potrei semplicemente andare a casa, ma qui commetto un nuovo errore.

Errore tre. Consiglieri

Mai! Non ponete mai domande sui forum e su siti specializzati (tipo stackoverflow) se la risposta richiede più di consultare i risultati della prima pagina di Google e leggere una pagina di un man.

Vi rimanderanno a Google, a leggere sempre lo stesso man e vi spiegheranno le regole del forum/sito, ma non vi daranno risposta.

Qui ci sono fattori sia oggettivi:

  • nessuno tranne voi può conoscere il problema altrettanto bene;
  • nessuno può eseguire test nelle stesse condizioni in cui vi trovate

e fattori soggettivi:

  • potreste non fornire tutti i dati necessari per risolvere il problema, perché avete già inventato una direzione "corretta" e presentate la questione basandovi su di essa;
  • il caporale (moderatore, veterano, admin) ha sempre ragione, se il caporale ha torto… beh, lo sapete…

Se nei commenti di risposta siete rimasti nei limiti di un linguaggio censurato, significa che avete nervi saldi.

Soluzione

Non bisogna dividere i compiti in semplici e complessi.

Smettiamo di fare affidamento sulla nostra esperienza, sulle statistiche, sui consigli e iniziamo a non "spiegare" il risultato finale, ma a cercare sistematicamente la causa.

Se qualcuno imposta l'ora, deve esserci una corrispondente chiamata di sistema.

Come nella documentazione del software, le migliori informazioni sono i sorgenti, così nell'amministrazione di sistema il miglior aiuto è l'audit, nel nostro caso auditd.

Un momento di dubbioHo esaminato i manuali, ma non ero del tutto sicuro che l'ora in Linux potesse essere impostata solo clock_settime e settimeofday, quindi per il primo test ho scelto tutte le chiamate "appropriate":

# man syscalls | col | grep -F '(2)' | grep -vE '(:|;)' | grep -E '(time|date|clock)' | sed "s/(2).*//" | xargs -I SYSCALL echo "-S SYSCALL " | xargs echo
-S adjtimex -S clock_adjtime -S clock_getres -S clock_gettime -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S s390_runtime_instr -S setitimer -S settimeofday -S stime -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_create -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

e scartando s390_runtime_instr, stime, timerfd_create, che auditctl non ho riconosciuto, ho inizialmente avviato l'audit in questo modo:

auditctl -a exit,always -S adjtimex -S clock_adjtime -S clock_getres -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S semtimedop -S setitimer -S settimeofday -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

Accertato che nei luoghi di log che mi interessano non ci siano altri syscalls tranne questi due, ho continuato a utilizzare solo loro.

Avviamo l'audit delle chiamate di sistema clock_settime e settimeofday e proviamo a cambiare la data:

# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D

Una pausa di cinque secondi è stata aggiunta affinché il nostro "parassita" possa garantire di correggere l'ora.

Guardiamo il report:

# aureport -s -i

Syscall Report
=======================================
# date time syscall pid comm auid event
=======================================
Warning - freq is non-zero and incremental flushing not selected.
1. 08/22/2019 12:10:00 settimeofday 3088 chkcache_proces root 479630
2. 08/26/2019 09:37:06 clock_settime 1538 date root 479629

Qui vediamo il nostro date e l'ignoto chkcache_proces. È apparso nel report sopra, poiché aureport ha ordinato l'output per data durante la conversione da binario, e l'evento è avvenuto nell'orario che abbiamo impostato date -s "2019-08-22 12:10:00".
Chi lo ha generato?

# ausearch -sc settimeofday --comm "chkcache_proces"
----
time->Thu Aug 22 12:10:00 2019
type=PROCTITLE msg=audit(1566465000.000:479630): proctitle="/usr/local/bin/oscam"
type=SYSCALL msg=audit(1566465000.000:479630): arch=c000003e syscall=164 success=yes exit=0 a0=7fde0dfc6e60 a1=0 a2=136cf a3=713ba56 items=0 ppid=3081 pid=3088 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts20 ses=68149 comm="chkcache_proces" exe="/usr/local/bin/oscam" key=(null)

/usr/local/bin/oscam — il nostro parassita è stato trovato. Nonostante il suo comportamento "maligno", non possiamo rinunciare al sistema di accesso condizionato, ma vorremmo sapere, oscam, WTF?

La risposta è rapidamente trovata in sorgenti:

#if defined(CLOCKFIX)
if (tv.tv_sec > lasttime.tv_sec || (tv.tv_sec == lasttime.tv_sec && tv.tv_usec >= lasttime.tv_usec)) // check for time issues!
{
  lasttime = tv; // register this valid time
}
  else
{
  tv = lasttime;
  settimeofday(&tv, NULL); // set time back to last known valid time
  //fprintf(stderr, "*** WARNING: BAD TIME AFFECTING WHOLE OSCAM ECM HANDLING, SYSTEMTIME SET TO LAST KNOWN VALID TIME **** n");
}

Che carino si presenta qui la riga commentata del warning

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster