
Esta tarea trivial surgió en uno de esos viernes y debería haber tomado de 2 a 3 minutos. Como siempre.
Un colega me pidió que corrigiera un script en su servidor. Lo hice, se lo entregue y solté sin querer: "El tiempo se adelanta 5 minutos". Es su servidor, que él se encargue de la sincronización. Pasó media hora, una hora, y él seguía resoplando y maldiciendo en voz baja.
"¡Torpe! — pensé, cambiando a la consola servidores — bueno, de acuerdo, me desconectaré por un par de minutos más."
Veamos, ntp, rdate, sdwdate no están instalados, timesyncd está desactivado y no se está ejecutando.
# 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
Aquí señalaré de inmediato que el tiempo del hardware es correcto: será más fácil orientarse más adelante.
De aquí comenzó una serie de errores.
Error uno. Presunción
Clac-clac...
# 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
Todo perfecto, el tiempo se sincronizó, el sistema coincide con el hardware. "Tómalo", dejé caer y volví a mis asuntos.
"¿Qué tomas? — se indignó el colega. — ¡El tiempo es el mismo!"
Cuanto más resuelves tareas típicas, más se cierra tu mente y ya no piensas que la centésima o milésima situación será diferente, pero no esta vez.
# 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
El tiempo del sistema nuevamente es incorrecto.
Intentémoslo de nuevo:
# 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
Hagámoslo de otra manera:
# 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
Y así:
# 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
El tiempo se establece en fracciones de segundo y luego comienza a "adelantarse" nuevamente.
Mientras tanto, en los registros, en el momento de tal cambio manual, solo vemos informes del sistema sobre que el tiempo ha cambiado, ya sea en la dirección correcta/incorrecta y de vez en cuando Resincronizando por systemd-timesyncd.
Aug 25 21:18:51 wisi systemd[1]: El tiempo ha cambiado
Aug 25 21:18:51 wisi systemd-timesyncd[29258]: El tiempo del sistema ha cambiado. Resincronizando.
Aug 25 21:18:51 wisi systemd[1187]: El tiempo ha cambiado
Aug 25 21:18:51 wisi systemd[1]: El tiempo ha cambiado
Aug 25 21:18:51 wisi systemd[1187]: El tiempo ha cambiado
aquí
# ps afx | grep "[1]187"
1187 ? Ss 0:02 /lib/systemd/systemd --user
En ese momento ya debería haber estado buscando la causa, pero el cerebro, tras 18 años de administración, acumuló estadísticas de errores de "tiempo" y por costumbre vuelve a culpar a la sincronización.
La desactivamos por completo.
# 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
y en los registros
Aug 25 21:25:40 wisi systemd[1]: El tiempo ha cambiado
Aug 25 21:25:40 wisi systemd[1187]: El tiempo ha cambiado
Aug 25 21:29:30 wisi systemd[1]: El tiempo ha cambiado
Aug 25 21:29:30 wisi systemd[1187]: El tiempo ha cambiado
Resincronizando desapareció y los demás registros están inmaculados.
Verificamos las salidas tcpdump por el puerto 123 en todas las interfaces. No hay solicitudes, pero el tiempo aún "se escapa".
Error dos. Prisa
Queda una hora hasta el fin de la semana laboral, y no quiero salir de fin de semana con una tarea insolucionada (no presten atención al tiempo en el código, el artículo fue escrito en días posteriores).
Y aquí, nuevamente, en lugar de buscar la causa, comencé a intentar idear una explicación para el resultado. Digo 'idear' porque, por muy lógicas que sean las explicaciones del resultado, es un enfoque erróneo para resolver el problema.
Este servidor es de streaming y convierte la transmisión DVB-S2 a IP. En la transmisión DVB-S hay marcas de tiempo, por lo que los receptores, multiplexores, scramblers y televisores a menudo las utilizan para sincronizar los relojes del sistema. Los controladores de las tarjetas DVB-S están compilados en el núcleo, así que la forma más rápida de eliminar con seguridad la transmisión DVB-S2 es desconectar los cables que vienen de las 'antenas'. Afortunadamente, el servidor está tras la pared, así que así será.
Por supuesto, si en los registros estuviera lo que debería estar, eso no habría pasado, pero sobre esto, de nuevo, al final del artículo.
Y ya que hemos eliminado todas las señales satelitales, también eliminaremos las terrestres — a la vez, desconectamos todos los cables de red. El servidor queda desconectado del mundo exterior y opera de forma completamente autónoma, pero los relojes del sistema siguen adelantados.
La semana laboral ha terminado, y la cuestión de la fecha/hora en él no es crítica, así que podría simplemente irme a casa, pero aquí cometo un nuevo error.
Error tres. Los consejeros.
¡Nunca! Nunca hagas preguntas en foros y sitios especializados (como stackoverflow) si la respuesta requiere más que estudiar los resultados de la primera página de Google y leer una página del man.
Te enviarán de vuelta a Google para leer el mismo man y te explicarán las reglas del foro/sitio, pero no te darán una respuesta.
Aquí hay tanto factores objetivos:
- nadie más que tú puede conocer el problema tan bien;
- nadie puede realizar pruebas en condiciones iguales a las tuyas.
así como subjetivos:
- puedes no proporcionar toda la información necesaria para resolver la tarea, porque ya has ideado una 'solución correcta' y presentas la esencia de la pregunta basándote en ello;
- el sargento (moderador, veterano, administrador) siempre tiene razón, si el sargento se equivoca… bueno, ya sabes...
Si en los comentarios de respuesta permaneciste dentro de un lenguaje censurado, significa que tienes nervios fuertes.
Solución
No se deben dividir las tareas en simples y complejas.
Dejamos de confiar en nuestra experiencia, estadísticas, consejeros y comenzamos a no 'explicar' el resultado final, sino a buscar la causa de manera secuencial.
Si alguien establece la hora, debe ocurrir una llamada al sistema correspondiente.
Así como en la documentación del software los mejores documentos son los códigos fuente, en administración de sistemas el mejor aliado es la auditoría, en nuestro caso. auditd.
Un momento de duda.Revisé los manuales, pero no estaba completamente seguro de que la hora en Linux solo pudiera establecerse con. clock_settime. y settimeofday., así que para la primera prueba elegí todas las llamadas «adecuadas»:
# 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
y descarté. s390_runtime_instr, stime, timerfd_create., de las cuales. auditctl. no reconoció, inicialmente ejecuté la auditoría como:
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.Asegurándome de que en los registros que me interesaban no había otros. syscalls además de estos dos, a continuación solo utilicé ellos.
Iniciamos la auditoría de llamadas al sistema. clock_settime. y settimeofday. y tratamos de cambiar la fecha:
# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D
Se añadió una demora de cinco segundos para que nuestro «parásito» ajustara la hora garantizadamente.
Veamos el informe:
# 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
Aquí vemos nuestro. Muestra la fecha y hora actuales del sistema. y el desconocido para nosotros. chkcache_proces.. Apareció en el informe anterior, ya que aureport ordenó la salida por fecha al convertir de formato binario, y el evento ocurrió a la hora que establecimos. date -s «2019-08-22 12:10:00»..
¿Quién lo creó?
# 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 — nuestro parásito encontrado. A pesar de su comportamiento «malicioso», no se puede prescindir del sistema de acceso condicional, pero aún así me gustaría saber. oscam., ¿WTF?.
La respuesta se encontró rápidamente en. :
#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");
}
Qué lindo se ve aquí. la línea comentada. advertencia. En Rainbow Six Siege se puede jugar gratis durante una semana.…
Fuente: habr.com
