Cómo corregir el reloj desajustado de un VPS
Compruebe la deriva del reloj de su VPS con chronyc y timedatectl. Identifique el servicio o UDP 123 bloqueado que rompe la sincronización y el acceso 2FA.
Por qué se desajusta el reloj de su VPS
El reloj de un VPS se desajusta porque nada lo corrige. El kernel calcula el tiempo a partir de un contador de hardware que funciona un poco rápido o un poco lento. Si no se ejecuta ningún cliente de sincronización horaria, ese pequeño error aumenta cada hora. En una máquina virtual hay una segunda causa: el guest comparte una CPU física con otros guests. Por tanto, durante los intervalos en que no se le asigna tiempo de CPU, no puede calcular el paso del tiempo.
En un guest KVM actual, el contador rara vez es el problema real. La fuente kvm-clock paravirtualizada lee un valor que mantiene el host, por lo que un guest en buen estado sigue de cerca la hora del host. Los relojes que muestran una desviación evidente suelen estar mal por una razón más simple. No se ejecuta ningún daemon de sincronización, o se ejecutan dos y entran en conflicto, o el puerto UDP saliente 123 no sale nunca de la red del proveedor. Un guest obtiene la disciplina horaria del host o de NTP (network time protocol), no de su propio oscilador.
Qué problemas causa realmente un reloj incorrecto
- Los códigos de autenticación de dos factores TOTP (contraseña de un solo uso basada en el tiempo) dejan de coincidir. Esto puede bloquear el acceso a un servidor aunque la contraseña y la clave sean correctas.
- Se rechaza un certificado emitido hace un minuto y
curlmuestraSSL certificate problem: certificate is not yet valid. apt updaterechaza un repositorio conE: Release file for ... is not valid yet (invalid for another 1d 2h 3min 4s).- Las tareas programadas se ejecutan en el momento incorrecto. Un salto del reloj puede hacer que una tarea se ejecute dos veces y que otra no se ejecute.
- No se pueden alinear los registros de dos servidores. Por tanto, la cronología de un incidente debe reconstruirse por aproximación.
La tolerancia es menor de lo que suele esperarse. Las cifras siguientes son valores predeterminados documentados, no mediciones obtenidas en una prueba.
The data behind this chart
[
{
"label": "TLS certificate boundary",
"tolerance_seconds": 0,
"documented_in": "RFC 5280"
},
{
"label": "chrony steps instead of slewing",
"tolerance_seconds": 1,
"documented_in": "Debian and Ubuntu chrony.conf"
},
{
"label": "TOTP code, one time step",
"tolerance_seconds": 30,
"documented_in": "RFC 6238"
},
{
"label": "Kerberos clock skew",
"tolerance_seconds": 300,
"documented_in": "MIT krb5 default"
}
]Un código TOTP se calcula a partir de un contador que avanza cada 30 segundos, y la mayoría de los verificadores aceptan un intervalo a cada lado. Un desfase de medio minuto en cada dirección agota todo el margen disponible. Kerberos es mucho más tolerante, con un margen de desfase predeterminado de 300 segundos. Los certificados no ofrecen ninguna tolerancia: se comprueban contra instantes fijos con un periodo de gracia de 0 segundos. Por tanto, un reloj adelantado un segundo rechaza un certificado perfectamente válido.
Los tres relojes y cuál importa
El reloj del sistema es el que importa. Es el CLOCK_REALTIME del kernel: el número de segundos desde el 1 de enero de 1970 UTC, mantenido en memoria y leído por todo lo que registra una hora. Las líneas de registro, las comprobaciones de certificados, los códigos TOTP y las horas de modificación de los archivos proceden de él. Cuando alguien dice que la hora del servidor es incorrecta, se refiere a este reloj.
El reloj de hardware, también llamado RTC (reloj de tiempo real), es un contador independiente que sigue funcionando mientras la máquina está apagada. En una máquina física es un chip respaldado por una batería. Dentro de un guest lo emula el hipervisor, por lo que depende en gran medida del host. Linux lo lee una vez durante el arranque para obtener un valor inicial y después mantiene su propio contador. timedatectl lo muestra en la línea RTC time. No depure a partir de esa línea en un VPS, porque le informa de la hora que mantiene el host, no del estado de sincronización del reloj del sistema. En un contenedor normalmente no existe ningún /dev/rtc, por lo que hwclock --show falla con hwclock: Cannot access the Hardware Clock via any known method.
La fuente de reloj es el mecanismo que usa el kernel para contar entre esas lecturas. Consulte cuál ha seleccionado el kernel:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
cat /sys/devices/system/clocksource/clocksource0/available_clocksourceEn KVM normalmente verá kvm-clock. Lee un valor mantenido por el host. Por eso, un guest de KVM sin ningún cliente NTP sigue manteniendo una hora aproximada durante un tiempo. tsc es el contador propio de la CPU. Los guests de Xen muestran xen y los guests de Hyper-V muestran una fuente hyperv. No cambie este ajuste salvo que tenga un motivo comprobado, porque el kernel ya selecciona la mejor fuente de confianza disponible en ese hardware.
Algunos hosts también proporcionan al guest un dispositivo PTP (protocolo de tiempo de precisión), que permite a chrony leer directamente el reloj del host en lugar de hacerlo a través de la red. Conviene comprobarlo, aunque a menudo no está disponible en un VPS compartido:
sudo modprobe ptp_kvm
ls /dev/ptp*
cat /sys/class/ptp/ptp0/clock_nameSi modprobe falla o no aparece ningún dispositivo, el host no lo ofrece y la respuesta es usar NTP por red. Si clock_name identifica el reloj virtual de KVM, chrony puede usarlo mediante una línea refclock PHC /dev/ptp0 poll 2 en su configuración.
Consulte el estado de la hora en su propia máquina
Empiece con un comando. Responde en una sola pantalla a la pregunta «¿hay algo que mantenga este reloj correctamente sincronizado?».
timedatectlLea estas líneas en lugar de confiar en un número que recuerde:
Local timeyUniversal timerepresentan el mismo instante, mostrado en su zona horaria y en UTC. Si son idénticos, la máquina ya usa UTC.RTC timees el reloj de hardware descrito anteriormente. En un VPS, ignórelo.Time zoneindica lo que usa el sistema para mostrar la hora local.System clock synchronizedes el indicador propio del kernel. Un daemon de hora lo establece cuando confía en sus fuentes. Por tanto,nosignifica que ningún proceso ha sincronizado este reloj desde el arranque.NTP serviceinforma específicamente sobre systemd-timesyncd.n/aes normal en una máquina que ejecuta chrony, porque timesyncd no está instalado allí.System clock synchronized: yesjunto conNTP service: n/asignifica que chrony está realizando el trabajo y que el kernel lo confirma.
A continuación, compruebe cuánto se desvía el reloj. No lo compare a ojo con el teléfono. Si chrony está en ejecución:
chronyc tracking
chronyc sources -vchronyc tracking muestra los valores que responden a la pregunta. System time es el desfase actual respecto a la hora NTP, seguido de la palabra fast o slow. Last offset es el tamaño de la corrección más reciente. Frequency es el error de frecuencia que chrony ha medido en su reloj y ya está compensando. Leap status debería mostrar Normal. Si muestra Not synchronised y Reference ID es 00000000 (), chrony todavía no ha seleccionado una fuente.
chronyc sources -v muestra una leyenda encima de la lista, para que no tenga que recordar los símbolos. Dos columnas contienen la mayor parte de la información. El carácter de estado al principio de cada línea indica cómo valora chrony esa fuente: * marca la fuente que está usando actualmente y ? en todas las líneas significa que ninguna responde. Reach es el historial de respuestas de las últimas ocho consultas, mostrado en octal: 377 significa que las ocho recibieron respuesta y 0 significa que no respondió ninguna.
Si systemd-timesyncd es el responsable:
timedatectl timesync-status
timedatectl show-timesync --alltimesync-status muestra el servidor con el que se comunica, el intervalo de consulta y un valor Offset. Si el comando devuelve un error sobre el servicio en lugar de mostrar el estado, timesyncd no es el daemon responsable en este equipo. Esa es precisamente la respuesta a su pregunta.
Para realizar una comprobación aproximada contra el exterior sin herramientas adicionales, compare su reloj con una cabecera HTTP pública Date, que se sirve en GMT con una resolución de un segundo:
date -u
curl -sI https://www.cloudflare.com | grep -i '^date:'Una diferencia de uno o dos segundos es normal y no indica ningún problema. Una diferencia de un minuto es un fallo de su configuración.
chrony o systemd-timesyncd en un VPS
Ubuntu y Debian incluyen systemd-timesyncd de forma predeterminada. Es un cliente SNTP (protocolo simple de tiempo de red): consulta un servidor cada vez y ajusta gradualmente el reloj hacia ese valor. En una máquina que permanece conectada y parte de una hora aproximada, es suficiente y consume muy pocos recursos.
chrony es una implementación completa de NTP y la opción predeterminada más adecuada en una máquina virtual, por motivos que se pueden comprobar en su propia salida. Consulta varias fuentes a la vez y descarta las que no coinciden. Mide el error de frecuencia del reloj y lo guarda en un archivo de deriva, por lo que corrige la tendencia del reloj en lugar de perseguir cada muestra. También se recupera rápidamente de las dos situaciones propias de una máquina virtual que no se dan en un equipo físico: el host puede pausarla y puede moverla a otro host mientras está en ejecución. Si se ofrece un dispositivo PTP del host, chrony es el componente que lo lee.
sudo apt update && sudo apt install -y chrony
systemctl status chrony --no-pager
chronyc sources -v
chronyc trackingLea la salida de apt mientras se ejecuta. En Debian y Ubuntu, los paquetes chrony y systemd-timesyncd proporcionan ambos time-daemon, por lo que apt elimina timesyncd al instalar chrony. Esto es correcto y esperado. Nunca ejecute ambos, porque dos daemons que configuran el mismo reloj entrarán en conflicto y no se podrá confiar en el offset indicado por ninguno mientras ambos estén activos. En Rocky y AlmaLinux, instale con sudo dnf install -y chrony; allí la unidad se llama chronyd en lugar de chrony.
El archivo de configuración es /etc/chrony/chrony.conf en Debian y Ubuntu, y /etc/chrony.conf en Rocky y Alma. El valor predeterminado de la distribución ya es adecuado para un VPS, así que cámbielo sólo si existe un motivo. Conviene entender dos directivas:
- Las líneas
poolyserverdefinen las fuentes de tiempo. Añadiriburstindica a chrony que envíe una ráfaga rápida al arrancar, de modo que la primera sincronización se produzca en segundos en lugar de minutos. makestepdetermina cuándo chrony adelanta o retrasa el reloj de forma inmediata en lugar de ajustarlo gradualmente. Compruebe su valor congrep -n makestep /etc/chrony/chrony.conf. El valor predeterminado de Debian y Ubuntu,makestep 1 3, significa lo siguiente: durante las tres primeras actualizaciones después de iniciar chronyd, adelanta o retrasa el reloj de forma inmediata si la diferencia supera un segundo; después, sólo lo corrige mediante ajuste gradual.
Si desea autenticar el tráfico de tiempo para evitar manipulaciones durante el tránsito, chrony 4 y posteriores admiten NTS (seguridad del tiempo de red). Confirme primero la versión con chronyd -v y tenga en cuenta que NTS también necesita abierto el puerto TCP 4460, además del puerto UDP 123:
server time.cloudflare.com iburst ntsReinicie y verifique el servicio antes de confiar en él. Si la configuración no se puede analizar, se quedará sin ningún daemon de tiempo, y el reloj no se lo indicará.
sudo systemctl restart chrony
chronyc sources -v
chronyc trackingPor qué un reloj con varios minutos de desfase sigue desfasado
Un daemon de hora puede corregir un desfase de dos formas. El ajuste gradual acelera o ralentiza el reloj hasta eliminar el error. Así, el tiempo sigue avanzando y nunca repite ni omite una marca de tiempo. El ajuste inmediato salta directamente al valor correcto. Es rápido y puede hacer que el reloj retroceda. Retroceder es peligroso para cualquier programa que mida el tiempo transcurrido a partir del reloj de pared. Por eso, ambos daemons prefieren el ajuste gradual.
Esa preferencia explica por qué un reloj con un desfase importante puede seguir incorrecto durante mucho tiempo. chrony sólo aplica un ajuste inmediato dentro de la ventana que permite makestep. De forma predeterminada, esa ventana corresponde a las primeras actualizaciones después de iniciar el daemon. Si un chronyd lleva una semana activo y después detecta un desfase de cuarenta segundos, lo corregirá gradualmente. Corregir cuarenta segundos de esta forma tarda mucho más de lo razonable. Fuerce la corrección una vez, de forma deliberada y en un momento de poca actividad:
sudo chronyc makestep
chronyc trackingchronyc tracking debería informar ahora de un desfase System time cercano a cero, y Last offset debería mostrar el tamaño de la corrección recién aplicada. Piense antes de ejecutar esto en un host de base de datos con actividad, porque un reloj que retrocede puede confundir al software que presupone que el tiempo sólo avanza. Reiniciar el daemon es una versión más suave de la misma corrección, ya que la ventana makestep vuelve a abrirse al iniciar.
Los contenedores comparten el reloj del host
Un contenedor no tiene su propio reloj de pared, por lo que no hay ningún reloj que sincronizar en su interior. Los espacios de nombres de tiempo de Linux virtualizan sólo los relojes monotónico y de tiempo de arranque. CLOCK_REALTIME no está virtualizado, por lo que un contenedor lee el mismo reloj del sistema que el host donde se ejecuta. Corrija el reloj en el host y todos los contenedores de ese host quedarán corregidos en el mismo momento.
Esto tiene varias consecuencias. No instale chrony ni ntpd en una imagen, porque, en el mejor de los casos, no hará nada. Establecer la fecha dentro de un contenedor sin privilegios falla con date: cannot set date: Operation not permitted, porque el kernel requiere CAP_SYS_TIME para esa llamada. Conceder CAP_SYS_TIME no proporciona al contenedor un reloj privado. Le proporciona la capacidad de cambiar el reloj del host y, por tanto, también el reloj de todos los demás contenedores.
Una zona horaria diferente dentro de un contenedor no es un problema del reloj. Una imagen que incluya su propio /etc/localtime muestra el mismo instante con el formato de otra zona, por lo que date parece incorrecto aunque el reloj sea correcto. Establezca TZ=UTC en el entorno del contenedor para eliminar la confusión. El runtime que haya elegido no cambia nada en este aspecto, y la comparación entre Podman y Docker rootless explica qué aspectos sí cambia.
Zonas horarias: UTC en el servidor, hora local para las personas
Configure la máquina con UTC y manténgala así.
timedatectl list-timezones | grep -i utc
sudo timedatectl set-timezone UTC
timedatectlUTC no tiene horario de verano. Ese es el argumento principal. Un trabajo diario a las 02:30 en una zona que aplica el horario de verano se ejecuta dos veces el día en que los relojes se retrasan y no se ejecuta el día en que se adelantan. man 8 cron documenta el tratamiento especial de los cambios de menos de tres horas: los trabajos omitidos por un adelanto se ejecutan poco después del cambio, y los trabajos que quedan dentro de una hora repetida por un retraso no se ejecutan por segunda vez. Este comportamiento es razonable, pero no debería tener que analizarlo a las 03:00. Con UTC, el trabajo se ejecuta una vez al día, todos los días del año. Si un trabajo suyo falta por completo en lugar de ejecutarse a una hora inusual, es más probable que un trabajo de cron no se ejecute nunca de forma silenciosa.
El mismo argumento se aplica a la lectura de registros. journalctl muestra las marcas de tiempo en la zona horaria del sistema y journalctl --utc fuerza UTC. Dos servidores en dos zonas horarias convierten cada incidente en un ejercicio de conversión, y las conversiones hechas bajo presión provocan errores al interpretar una línea temporal. Mantenga los sistemas en UTC, almacene las marcas de tiempo en UTC y conviértalas una sola vez cuando una persona las lea. Si alguien necesita ver la hora local para un comando, puede solicitarla sin cambiar la configuración de la máquina:
TZ=Europe/Berlin dateOtra línea de la salida de timedatectl corresponde a esta sección. RTC in local TZ debería mostrar no. Establecerlo en yes es una solución alternativa para arrancar Windows y otro sistema en el mismo portátil. En un servidor, sólo añade un desfase que puede causar problemas más adelante. Cuando está configurado, timedatectl muestra una advertencia indicando que el sistema está configurado para leer la hora del RTC en la zona horaria local.
Resolución de problemas por síntoma
El código de autenticación de dos factores se rechaza en un servidor. Compruebe el reloj antes que cualquier otra cosa. El código procede de un contador que avanza cada 30 segundos, por lo que un servidor con 90 segundos de retraso calcula un código correspondiente a un intervalo que el teléfono ya ha dejado atrás. timedatectl mostrará System clock synchronized: no o chronyc tracking informará de un desfase System time grande. Este fallo es distinto del rechazo directo de una clave, que muestra su propio mensaje y se trata en la guía sobre fallos de autenticación con publickey.
apt update indica que un archivo Release aún no es válido. El mensaje completo identifica el repositorio y cuánto tiempo seguirá sin ser válido, por ejemplo is not valid yet (invalid for another 1d 2h 3min 4s). El reloj está retrasado con respecto a la fecha incluida en el archivo Release del repositorio, y esa duración mide directamente cuánto se ha retrasado. Corrija el reloj. No desactive la comprobación de fechas de apt para evitar el error, porque esa comprobación impide que alguien le sirva un índice de paquetes obsoleto.
Todas las líneas de origen muestran el estado inalcanzable y Reach es 0. Nadie responde, así que revise la salida de red y no la configuración. NTP usa el puerto UDP 123 para las conexiones salientes, y algunas redes filtran o redirigen ese tráfico. sudo chronyc ntpdata muestra contadores por origen, incluidos Total TX y Total RX. Si el contador TX aumenta mientras RX permanece en cero, los paquetes salen y no vuelve ninguna respuesta. Esto apunta a un firewall entre el sistema y el origen.
El reloj era correcto y después saltó. Los eventos del host pueden provocarlo. La restauración de una instantánea, una máquina invitada pausada o una migración en vivo a otro host pueden hacer que la hora que ve la invitada quede retrasada con respecto a la hora real. chrony lo detecta en la siguiente consulta y corrige el desfase; systemd-timesyncd puede esperar primero un intervalo de consulta largo. Confirme que el daemon se inicia durante el arranque con systemctl is-enabled chrony, porque un daemon iniciado manualmente dejará de ejecutarse tras el siguiente reinicio.
El desfase es pequeño, pero nunca se estabiliza. Revise el steal de CPU. Una invitada que no recibe tiempo de CPU cuando debe ejecutarse su interrupción de temporizador obtiene las muestras con retraso. Por eso el desfase fluctúa en lugar de converger. top lo muestra como la cifra st en la línea de CPU. Cómo interpretar el tiempo de steal de CPU en un host compartido explica qué significa esa cifra y qué puede hacer al respecto.
Un certificado que acaba de emitir se rechaza porque aún no es válido. curl muestra SSL certificate problem: certificate is not yet valid y los navegadores indican algo similar. El certificado es correcto; el reloj que lo comprueba está retrasado. El problema puede estar en cualquiera de las dos máquinas, así que compruebe el cliente y el servidor. Si el servidor que lo emitió es el que tiene el reloj incorrecto, la guía de certificados de certbot y nginx explica la renovación en esta misma configuración.
Añádalo a las comprobaciones que ya ejecuta
La sincronización horaria es un ajuste del arranque que puede fallar silenciosamente meses después. Es exactamente el tipo de problema que una rutina detecta y la memoria no. timedatectl y chronyc tracking se leen juntos en dos segundos. Ejecútelos como parte de los primeros diez minutos en un VPS nuevo y de nuevo al seguir la lista periódica de mantenimiento de servidores Linux. Si prefiere que la comprobación se ejecute automáticamente y avise cuando aumente el desfase, crear un servicio y un temporizador de systemd explica el patrón para una unidad pequeña que genere informes según un calendario.
FAQ
¿Cómo compruebo si el reloj de mi VPS está sincronizado?
Ejecute timedatectl y lea la línea System clock synchronized. Esa es la marca del propio kernel, establecida por el daemon que sincroniza el reloj, por lo que yes junto con NTP service: n/a es normal y correcto en un equipo que usa chrony. Para conocer el tamaño del desfase, ejecute chronyc tracking y lea System time, o ejecute timedatectl timesync-status y lea Offset si el responsable es systemd-timesyncd. Para comparar el reloj con una referencia externa al equipo, compare date -u con la cabecera Date que devuelve cualquier sitio HTTPS.
¿Debo usar chrony o systemd-timesyncd en un VPS?
Use chrony en cualquier servidor importante. systemd-timesyncd es un cliente SNTP que sigue a un solo servidor y funciona bien en un equipo que permanece conectado y cuyo reloj comienza con una desviación pequeña. chrony consulta varias fuentes, descarta las que no coinciden, aprende la tasa de error del reloj y se recupera rápidamente después de una pausa del host o una migración en vivo. Instalar chrony en Debian o Ubuntu elimina automáticamente systemd-timesyncd porque ambos paquetes proporcionan time-daemon. Nunca ejecute dos daemons de sincronización horaria al mismo tiempo.
¿Por qué fallan mis códigos TOTP en un servidor, pero funcionan en todos los demás?
Porque un código TOTP depende de la hora actual. El código procede de un contador que avanza cada 30 segundos, por lo que el servidor y el teléfono deben coincidir en el intervalo actual. La mayoría de los verificadores acepta un intervalo a cada lado, lo que proporciona aproximadamente medio minuto de margen en cada dirección. Compruebe timedatectl en ese servidor. Si System clock synchronized muestra no, corrija la sincronización y los códigos volverán a coincidir sin cambiar el secreto compartido.
¿Puedo establecer la hora dentro de un contenedor Docker?
No, y no es necesario. Un contenedor comparte el CLOCK_REALTIME del host porque los espacios de nombres de tiempo de Linux sólo virtualizan los relojes monotónico y de tiempo de arranque. Un contenedor sin privilegios obtiene date: cannot set date: Operation not permitted, y añadir CAP_SYS_TIME le permite cambiar el reloj del host en lugar de proporcionarle un reloj propio. Sincronice el host. Una hora local diferente dentro de un contenedor es una configuración de zona horaria, así que establezca TZ en el entorno del contenedor.
¿Debe usar un servidor UTC o la hora local?
UTC, y aplique la hora local cuando una persona lea la salida. UTC nunca cambia por el horario de verano, por lo que una tarea diaria se ejecuta una vez al día durante todo el año y las marcas de tiempo de distintos servidores coinciden sin conversiones. Establézcalo con sudo timedatectl set-timezone UTC. Quien necesite consultar la hora local puede anteponerla a un único comando, por ejemplo TZ=America/New_York date, sin modificar el reloj del sistema.