Imagine: ontem seu scraper via proxy funcionava perfeitamente, logs limpos, métricas verdes. Hoje de manhã você abre o dashboard e vê uma parede de erros: certificate is not yet valid, token expired, signature does not match. O primeiro pensamento do engenheiro é previsível: o proxy quebrou, o provedor fez algo, precisa trocar o pool. Você gasta horas diagnosticando a rede, troca endpoints, escreve para o suporte. E a causa o tempo todo estava bem debaixo do seu nariz, tiquetaqueando errado. É o relógio do sistema.

A dessincronização de horário é uma das fontes de falha mais subestimadas em infraestrutura que opera via proxy. Ela é traiçoeira porque se disfarça de problema de rede e de certificado. Você vê a palavra certificate no erro e vai correndo mexer com TLS, embora o certificado esteja vivo e válido. Só que a sua máquina acha que hoje é outro dia.

Neste guia vamos destrinchar o tema de A a Z. Você vai entender onde exatamente o horário está embutido na criptografia e nos protocolos, como são os erros específicos em curl, Python e Node, por que o relógio desanda em VMs e contêineres, como fechar o diagnóstico em um minuto e como configurar a sincronização de modo que ela realmente funcione, e não apenas conste como instalada. O material foi escrito pelos engenheiros da Proxeon com base na análise de incidentes reais. Um destaque importante: não estamos falando de emissão de certificados nem de como eles funcionam internamente — apenas do horário como causa de falhas.

Fundamentos: por que o horário faz parte do protocolo, e não é só um número na tela

Comecemos pelo básico. Muita gente enxerga o horário do sistema como uma convenção puramente humana: é útil saber que agora são 14h30. Mas no mundo dos protocolos de rede, o horário é um participante ativo das verificações de segurança. Ele está embutido na lógica de validação em vários níveis ao mesmo tempo.

Quando dois nós estabelecem uma conexão segura ou trocam mensagens assinadas, eles precisam de um jeito de distinguir dados recentes de dados antigos. Sem a noção de tempo, é impossível responder a perguntas simples: este certificado já expirou? este token já venceu? um atacante está repetindo uma requisição antiga capturada? É exatamente por isso que os protocolos trazem marcas de tempo e janelas de validade embutidas.

O que é o horário do sistema e de onde ele vem

Em qualquer sistema operacional existem dois conceitos ligados. O primeiro é o relógio de hardware (RTC, real-time clock), um chip com alimentação própria por bateria, que continua contando mesmo com o computador desligado. O segundo é o relógio do sistema, que o kernel do SO mantém na memória RAM, partindo do valor do RTC na inicialização e ajustando ao longo do funcionamento.

O problema é que o oscilador de quartzo em qualquer hardware não é perfeito. Ele adianta ou atrasa frações de segundo por dia. Isso se chama desvio de relógio. Em uma semana sem correção, acumulam-se segundos perceptíveis e, em alguns ambientes virtuais, minutos inteiros. Para combater o desvio, criou-se o protocolo de sincronização de horário pela rede. O daemon de sincronização pergunta periodicamente a servidores de referência o horário exato e ajusta suavemente o relógio local.

UTC, fusos horários e por que isso importa para proxies

Um insight fundamental para iniciantes: toda criptografia séria de rede opera em UTC — Tempo Universal Coordenado, sem vínculo com fusos horários. Certificados, JWT, assinaturas de requisições — tudo trabalha com instantes de tempo em UTC. O fuso horário é só cosmética de exibição para humanos.

Isso significa que, se você configurou o fuso errado, mas o tempo absoluto (em UTC) está correto, a criptografia não é afetada. Mas se o tempo absoluto está bagunçado, tudo desanda. Uma confusão comum: o engenheiro vê um horário local estranho nos logs, vai mexer no fuso, e a raiz do problema está em outro lugar. Grave essa separação: o fuso afeta a exibição, o tempo absoluto em UTC afeta as verificações.

Como o proxy entra nessa história

Quando você opera via proxy, surge um nó adicional no caminho da requisição. Mas é importante entender: o proxy, na maioria dos cenários, não altera nem substitui o horário nas suas verificações criptográficas. O handshake TLS com o servidor de destino, a checagem da validade do certificado, a validação do token — tudo isso acontece do seu lado ou do lado do servidor final. O proxy apenas repassa bytes.

Daí o paradoxo: operar via proxy não cria o problema de horário, mas deixa os sintomas mais confusos. O engenheiro enxerga a cadeia cliente — proxy — servidor e naturalmente suspeita do elo intermediário. Mas a culpa é da máquina local, onde o relógio está errado. Chamamos isso de efeito da suspeita deslocada: quanto mais longa a cadeia, mais a gente culpa o meio em vez das pontas.

Mergulho profundo: onde exatamente o horário é crítico

Agora vamos mais fundo e destrinchar os pontos concretos em que o horário incorreto vira falha. São quatro, e cada um merece atenção própria.

Verificação de validade do certificado em TLS

Todo certificado TLS contém dois campos: notBefore (não válido antes) e notAfter (não válido depois). São os limites da janela de validade. Quando seu cliente estabelece uma conexão segura, ele recebe o certificado do servidor e verifica: o horário atual cai dentro dessa janela?

E aqui está o ponto-chave: o horário atual significa o horário da sua máquina. Se o seu relógio está atrasado e mostra uma data anterior ao notBefore, o cliente vai achar que o certificado ainda não começou a valer. Erro do tipo certificate is not yet valid. Se o relógio adiantou além do notAfter, o certificado já expirou para você, embora para o resto do mundo esteja fresquinho. Erro certificate has expired.

Certificados de curta duração são especialmente traiçoeiros. A prática moderna caminha para certificados com validade de 90 dias ou menos, e até 2026 o setor discute reduzir prazos para 45 dias ou menos. Quanto mais curta a janela de validade, menor a margem de segurança contra relógios bagunçados. Antigamente, uma dessincronização de uma hora era quase imperceptível diante de um certificado anual. Agora, uma janela estreita significa que até um desvio de algumas horas bem na borda da renovação pode derrubar a conexão.

JWT: os campos exp, nbf e iat

JSON Web Token é um formato popular de token de autorização. Dentro dele vivem campos temporais que são verificados a cada uso do token:

  • exp (expiration time) — o instante após o qual o token é considerado vencido.
  • nbf (not before) — o instante antes do qual o token ainda não é válido.
  • iat (issued at) — quando o token foi emitido.

Os três são timestamps Unix em segundos desde a época, ou seja, tempo absoluto em UTC. Quando o servidor recebe o token, compara esses campos com o seu próprio relógio. Quando o seu cliente decide se precisa renovar o token, olha o exp relativo ao seu relógio.

O cenário de falha é elegante na sua maldade. Suponha que o relógio do seu cliente adiantou dez minutos. O servidor emitiu um token com vida útil de cinco minutos. O seu cliente, olhando para o relógio adiantado, imediatamente considera o token recém-emitido já vencido e ou não o envia, ou entra em um loop infinito de renovação. A situação inversa: se o nbf estiver desalinhado com o seu relógio, você recebe token used before issued ou token not yet valid.

Assinaturas de requisição com marca de tempo

Muitas APIs exigem que cada requisição seja assinada e incluem uma marca de tempo na assinatura. Exemplo clássico são esquemas do tipo assinatura HMAC, em que o cliente monta uma string com método, caminho, corpo e o timestamp atual, e depois a assina com uma chave secreta. O servidor repete o cálculo e compara as assinaturas.

Aqui o horário tem papel duplo. Primeiro, o timestamp entra na string assinada, então o servidor precisa usar exatamente o mesmo timestamp que o cliente enviou — ele o pega do header. Segundo, o servidor verifica se esse timestamp não está longe demais do seu próprio horário. Normalmente se admite uma janela de alguns minutos — proteção contra replay de requisições antigas.

Se o relógio do cliente saiu dessa janela, o servidor rejeita a requisição como velha demais ou vinda do futuro. Erros do tipo request timestamp too skewed, signature expired ou o genérico signature does not match. E é justamente por causa do horário que você costuma ver erro de assinatura, e não erro de horário — o servidor nem sempre é honesto em dizer que o problema é o relógio.

Códigos de uso único e senhas temporárias

Uma categoria à parte são os códigos de uso único baseados em tempo (TOTP), usados na autenticação de dois fatores para acessar painéis de controle e consoles de API. Esse código é calculado a partir de um segredo compartilhado e do horário atual, dividido em intervalos geralmente de 30 segundos. Os dois lados calculam o código de forma independente e comparam.

Se o relógio do cliente estiver fora por mais de um ou dois intervalos, os códigos param de coincidir. Você digita um código recém-gerado e o sistema diz que é inválido. Nessa situação, as pessoas culpam o app gerador ou entram em pânico achando que foram hackeadas, quando bastava olhar o relógio. A tolerância aqui é bem estreita — dezenas de segundos — por isso o TOTP funciona muito bem como indicador de dessincronização.

Como o erro aparece em diferentes clientes

Teoria é teoria, mas o engenheiro vive no terminal e lê mensagens de erro. Vamos destrinchar como a dessincronização se manifesta nas ferramentas populares. Isso vai te ajudar a reconhecer o sintoma na hora.

curl

Ao trabalhar com TLS via curl, um relógio bagunçado dá mensagens características. Se o horário está atrasado e o certificado ainda não começou a valer segundo o seu relógio:

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

Se o horário adiantou e o certificado, pelos seus critérios, já expirou:

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

Detalhe útil: o código de erro 60 se refere a problemas de verificação de certificado. O engenheiro inexperiente vê a palavra certificate e vai checar o próprio certificado com um comando de visualização, confirma que as datas de validade estão em ordem e trava. A explicação é que as datas do certificado são comparadas com o seu horário local. Teste um exemplo via proxy:

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

Se na saída do -v você vir linhas sobre verificação de datas do certificado e logo depois um erro de validade — antes de tudo confira o date -u com uma referência, em vez de suspeitar do gateway.

Python (requests e httpx)

Em Python, na base padrão de TLS, um relógio bagunçado levanta uma exceção no handshake:

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")))

Repare no final da mensagem: certificate is not yet valid. É o mesmo sintoma temporal. Com JWT a história é outra — nada de erro TLS, mas a biblioteca de validação de token vai lançar uma exceção específica:

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

ou

jwt.exceptions.ExpiredSignatureError: Signature has expired

Aqui a palavra signature confunde — parece que o problema é na assinatura criptográfica. Na verdade, expired aponta exatamente para o campo exp e para o seu relógio. Verificação rápida do horário direto do código:

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

Compare o timestamp Unix obtido com a referência — uma divergência de mais de uns segundos já é suspeita.

Node.js

No Node, os erros de TLS vêm com códigos. Para dessincronização, os característicos são:

Error: certificate is not yet valid
code: 'CERT_NOT_YET_VALID'

e

Error: certificate has expired
code: 'CERT_HAS_EXPIRED'

Os códigos CERT_NOT_YET_VALID e CERT_HAS_EXPIRED são indicadores diretos. Se você vê o primeiro com um certificado vivo, seu relógio está atrasado. Se vê o segundo com um certificado sabidamente novo, seu relógio está adiantado. Com bibliotecas JWT no Node, você recebe erros com nomes como TokenExpiredError e NotBeforeError. Verificação rápida:

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

Tabela-resumo de sintomas

Vamos consolidar os padrões em um mapa mental único:

  • certificate is not yet valid / CERT_NOT_YET_VALID — relógio atrasado.
  • certificate has expired / CERT_HAS_EXPIRED com certificado novo — relógio adiantado.
  • token not yet valid / nbf / ImmatureSignature — relógio atrasado em relação ao servidor emissor.
  • token expired / ExpiredSignature logo após receber o token — relógio adiantado.
  • signature does not match / timestamp too skewed — relógio saiu da janela de tolerância do servidor.
  • Código TOTP sempre inválido — relógio desalinhado em dezenas de segundos ou mais.

Por que o relógio desanda: anatomia do desvio

Entender a causa é metade da solução. Vamos ver por que, na infraestrutura moderna, o relógio se bagunça mais do que parece. Isso vale especialmente para servidores e nós de trabalho por onde você passa o tráfego de proxy.

Máquinas virtuais e congelamento

Uma máquina virtual não tem acesso direto ao quartzo físico. A noção de tempo dela é uma abstração mantida pelo hypervisor. Normalmente está tudo bem, desde que a VM rode continuamente. Mas basta o hypervisor pausar a máquina para começar a mágica.

O cenário clássico é o congelamento e snapshots. O hypervisor pausa a VM, por exemplo para migração ou backup. Dentro do guest, o tempo meio que para. Quando a máquina é descongelada, o relógio do sistema fica atrasado exatamente pelo tempo da pausa. Se foi um minuto, você ganhou um desvio de um minuto instantaneamente, de uma vez só. Para tokens de curta duração e janelas estreitas de assinatura, isso é fatal.

Pior ainda é restaurar de um snapshot antigo. A máquina acorda com o horário do momento em que o snapshot foi tirado — podem ser horas ou dias no passado. O TLS vai imediatamente rejeitar certificados como ainda não válidos. Muitas plataformas de nuvem oferecem guest agents que ajustam o horário após o descongelamento, mas eles existem e funcionam nem sempre.

Contêineres

Com contêineres a história é mais sutil. Um contêiner não tem relógio de sistema próprio — ele usa o kernel do host e, portanto, o horário do host. Isso é boa notícia: se o host está sincronizado, o contêiner vê o horário correto automaticamente.

A má notícia está nos detalhes. Primeiro, dentro do contêiner geralmente não se pode alterar o horário do sistema — ele não tem os privilégios necessários, e isso é correto. Segundo, e o mais importante, dentro do contêiner frequentemente falta o daemon de sincronização, e isso é normal — quem deve sincronizar é o host. O problema surge quando o próprio host não está sincronizado e você não percebe, porque está acostumado a que no notebook do desenvolvedor tudo vem sincronizado de fábrica.

Ausência do daemon de sincronização

A causa mais banal e mais comum. Em imagens mínimas de servidor, o daemon de sincronização de horário pode não estar instalado ou não estar rodando. A máquina inicializa, pega o horário do RTC e depois vive em cima de um quartzo com desvio, sem correção. Dia após dia, o desvio vai acumulando.

Imagens montadas à mão ou clonadas são especialmente perigosas. O engenheiro configurou tudo numa máquina de referência, tirou a imagem, distribuiu em cem nós — mas o daemon de sincronização não foi ativado lá. Os cem nós começam a divergir silenciosamente, cada um para o seu lado. Enquanto o desvio é pequeno, tudo funciona. Depois de uma semana, os quartzos mais rápidos saem da janela de tolerância e você tem falhas flutuantes, não reproduzíveis, em parte do parque.

Ajuste manual e RTC travado

Às vezes o horário é quebrado por um humano. Alguém configurou a data manualmente para um teste e esqueceu de voltar. Alguém desligou a sincronização porque ela atrapalhava um experimento específico. Um problema à parte é a bateria do RTC gasta em um servidor físico: após reiniciar, o relógio volta para um passado distante e, até a primeira sincronização, o TLS não funciona de jeito nenhum.

Gestão dupla do horário

Um caso sutil que costuma ser esquecido. Às vezes dois mecanismos brigam pelo horário ao mesmo tempo: o guest agent do hypervisor e o daemon de sincronização dentro do SO. Eles puxam o relógio para lados diferentes, e você tem oscilações de horário de um lado para o outro. Isso se manifesta como falhas intermitentes que não se consegue capturar. A regra é simples: exatamente um mecanismo deve ser responsável pelo horário.

Diagnóstico em um minuto: fechando o diagnóstico rápido

Vamos à prática. Seu objetivo é entender em sessenta segundos se a culpa é do horário. Aqui vai o roteiro passo a passo que usamos na Proxeon ao analisar incidentes.

Primeiro passo: veja o seu horário em UTC

Antes de tudo, descubra o que o seu relógio pensa, em UTC mesmo, para eliminar confusão com fuso horário:

date -u

Anote o valor. Agora compare com uma referência.

Segundo passo: compare com uma fonte externa

O jeito mais confiável é perguntar o horário a um servidor de tempo pela rede e ver o desvio. Se o chrony estiver instalado:

chronyc tracking

Na saída, procure a linha System time — ela mostra o desvio do relógio do sistema em relação à referência. Um valor como 0.000030 seconds é o ideal. Se for systemd-timesyncd:

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

Outro truque rápido é uma consulta pontual a um servidor de tempo sem alterar o relógio:

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

Ele vai imprimir a correção estimada. Se o módulo dela for grande — aí está a resposta.

Terceiro passo: confira pelo header HTTP Date

Um insight que economiza muito tempo. Quase todo servidor web retorna no response o header Date com o horário atual em UTC. Compare-o com o seu relógio, direto pelo seu proxy:

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

Compare com date -u. Se a divergência for de segundos, está tudo bem. Se for de minutos, aí está a sua causa. A beleza do método é que ele não exige daemons instalados e funciona até dentro de um contêiner pelado, onde não há nada além de curl.

Qual faixa de divergência é considerada normal

Referências práticas, fruto da experiência:

  • Até 1 segundo — ótimo, não precisa fazer nada. Um sistema saudável e sincronizado mantém frações de segundo.
  • 1 a 5 segundos — aceitável para TLS e para a maioria dos JWTs, mas já é zona de atenção. Assinaturas de requisição e TOTP ainda seguram, mas a margem derrete.
  • 5 a 30 segundos — alerta. O TOTP começa a falhar, janelas estreitas de assinatura entram em risco. A sincronização claramente não está funcionando direito.
  • Mais de 30 segundos — crítico. Assinaturas, tokens de curta duração e, em desvios maiores, o TLS também falham. Conserte imediatamente.
  • Minutos e horas — catástrofe, geralmente consequência de congelamento, snapshot ou bateria de RTC morta.

Regra de ouro: se o desvio for maior que cinco segundos, o horário deve ser tratado como o principal suspeito em qualquer falha de TLS, tokens e assinaturas.

Configuração da sincronização: para que ela realmente funcione

Diagnosticar é pouco — é preciso tratar e evitar a repetição. Vamos ver as duas ferramentas principais no Linux e, o mais importante, como garantir que a sincronização esteja de fato ativa, e não apenas instalada. Essa é a diferença-chave que muita gente ignora.

systemd-timesyncd: a opção simples

Para a maioria das máquinas clientes e nós leves, o cliente embutido no systemd dá conta. Ele faz sincronização simples por protocolo de tempo. Como ativar:

timedatectl set-ntp true

Verificação de que a sincronização realmente está acontecendo:

timedatectl status

Procure duas linhas. System clock synchronized: yes significa que o sistema se considera sincronizado. NTP service: active significa que o daemon está rodando. As duas devem estar positivas. Se synchronized: no com active — o daemon está rodando, mas ainda não conseguiu falar com o servidor, ou ele está indisponível.

Detalhes sobre o servidor específico:

timedatectl show-timesync --all

Aqui dá para ver a qual servidor se conectou e qual desvio obteve. É justamente esse comando que separa a sincronização de verdade da decorativa.

chrony: a opção séria

Para servidores em que a robustez importa, especialmente VMs com risco de congelamento, o chrony é preferível. Ele lida melhor com saltos de horário e converge mais rápido após uma parada. Instale pelo gerenciador de pacotes e depois suba o serviço. A verificação principal é este comando:

chronyc tracking

Interpretação das linhas-chave da saída:

  • Reference ID — a que fonte está vinculado. Se estiver 00000000 ou uma linha dizendo que nenhuma fonte foi escolhida, não há sincronização.
  • Stratum — o nível de distância dos relógios de referência. É normal ver um número pequeno.
  • System time — o desvio atual do relógio do sistema. É o seu indicador principal.
  • Last offset e RMS offset — correções recentes e médias, mostrando a estabilidade.

Lista de fontes e o estado delas:

chronyc sources -v

Um asterisco à esquerda do servidor significa que é ele o escolhido como fonte ativa. Se nenhuma fonte tem marca de escolha, o daemon está instalado, mas não sincroniza — armadilha clássica.

Como distinguir sincronização instalada de sincronização funcionando

Esse é o insight pelo qual vale a pena ler a seção. O fato de instalar o pacote e até de o serviço estar rodando não garante sincronização. O serviço pode estar girando e não ter acesso aos servidores de tempo — por exemplo, o firewall bloqueando pacotes de saída na porta necessária, ou um ambiente fechado sem servidor de tempo interno.

A verificação real consiste em três perguntas. Primeira: há uma fonte ativa escolhida? Veja a marca em sources ou o Reference ID em tracking. Segunda: qual é o desvio atual? System time deve estar em frações de segundo. Terceira: ele atualiza? Rode a verificação duas vezes com intervalo e confirme que os números estão vivos, e não parados. Se as três respostas forem positivas — a sincronização funciona de verdade.

Monitorar o desvio como métrica

A abordagem profissional é não esperar o incidente, mas acompanhar o desvio continuamente. Exporte o valor de System time para o seu sistema de monitoramento como uma métrica comum. Configure um alerta quando passar, digamos, de dois segundos, e um alarme aos cinco. Assim você fica sabendo do problema antes de as assinaturas e tokens caírem. O custo desse monitoramento é quase zero, e o retorno é enorme: um incidente noturno evitado já paga tudo.

Contêineres e relógio: o que é herdado e o que não é

A conteinerização merece uma análise profunda à parte, porque é onde os engenheiros têm mais equívocos. Vamos colocar as coisas nos trilhos: o que o contêiner recebe do host e o que não recebe.

O que é herdado: o próprio horário

Fato-chave: o contêiner compartilha o kernel do host e, portanto, o relógio do sistema. Dentro do contêiner, date -u mostra exatamente o mesmo horário absoluto que no host. O contêiner não tem contador de tempo próprio. Isso é fundamental. Daí decorre a conclusão principal: para o contêiner ver o horário correto, é preciso sincronizar o host, e não tentar configurar sincronização dentro do contêiner.

O que não é herdado: o fuso horário

Já a exibição do horário é outra história. O fuso horário é definido por configurações dentro do contêiner, geralmente um arquivo de zona e uma variável de ambiente. A imagem base muitas vezes vem com UTC, o que, aliás, é uma boa prática para servidores. Se dentro do contêiner o horário local parecer diferente do host — quase sempre é diferença de fuso, e não de horário real. Confira o absoluto via UTC antes de entrar em pânico.

Por que não se deve rodar daemon de tempo em contêiner

Erro comum de iniciantes é enfiar o daemon de sincronização dentro do contêiner. Isso está errado por dois motivos. Primeiro, alterar o horário do sistema é uma operação privilegiada que afeta todo o kernel e, portanto, todos os contêineres no host e o próprio host. Por padrão, o contêiner não pode fazer isso, e ainda bem. Dar esse privilégio só para sincronizar é abrir uma brecha e criar conflito.

Segundo, simplesmente não é necessário: o horário já chega do host. A arquitetura correta é um host sincronizado, muitos contêineres vendo automaticamente o horário certo. Se você tem um orquestrador com vários nós, a sincronização deve ser garantida em cada nó-host, e não em cada pod.

A armadilha do notebook do desenvolvedor

Um alerta à parte sobre uma situação traiçoeira. No notebook do desenvolvedor tudo funciona: os contêineres veem o horário certo, porque o SO da estação de trabalho vem sincronizado de fábrica. O engenheiro monta a imagem, tudo verde. A imagem vai para o servidor, onde o host não está sincronizado — e aí começam as falhas. Lição: teste o comportamento com o relógio bagunçado, e não só com ele perfeito. Desloque o horário de propósito num ambiente de teste e veja como a aplicação reage.

Verificação do horário em um contêiner em execução

Comando rápido para espiar dentro de um contêiner em execução e conferir o horário absoluto:

docker exec -it my_container date -u

Se ele bater com date -u no host — está tudo bem, procure o problema em outro lugar. Se o contêiner de alguma forma mostrar um horário absoluto diferente, é sinal de configuração não padronizada, potencialmente perigosa, que deve ser revisada imediatamente.

Erros típicos: o que não se deve fazer

A experiência de analisar incidentes se acumula numa lista de pedras em que a gente tropeça de novo e de novo. Vamos passar por elas para que você as evite.

Erro um: culpar o proxy por reflexo

Começamos com isso e vamos repetir. A palavra certificate ou signature num erro ao operar via proxy gera automaticamente suspeita da rede e do gateway. Não ceda. A primeira ação diante desses erros é conferir o horário, e não trocar o endpoint. Isso leva dez segundos e corta a causa oculta mais frequente.

Erro dois: mexer no fuso em vez do horário

O engenheiro vê um horário local estranho nos logs e muda o fuso. O sintoma nos logs muda, mas a criptografia continua caindo do mesmo jeito, porque o tempo absoluto real em UTC continua bagunçado. Diagnostique sempre via date -u e comparação com uma referência, e não pela exibição local.

Erro três: achar que instalar a sincronização resolve

Instalou o pacote, viu que o serviço está rodando, fechou a tarefa. Uma semana depois, falhas de novo, porque o serviço não tinha acesso aos servidores de tempo. Instalação não é igual a sincronização. Sempre verifique o desvio real e a existência de uma fonte escolhida.

Erro quatro: ajustar o relógio à força em produção

Um salto brusco do horário do sistema via comando de ajuste direto pode quebrar processos em execução que contam com a monotonicidade do tempo: timeouts expiram, sessões se rompem, o agendador dispara de forma equivocada. O correto é deixar o daemon de sincronização ajustar suavemente. Correção brusca só é admissível em desvios enormes e pontuais, e mesmo assim com consciência.

Erro cinco: ignorar o congelamento de VMs

A equipe não leva em conta que migrações, snapshots e pausas criam desvios instantâneos. Para esses ambientes, é preciso um daemon resiliente a saltos e monitoramento de desvio após operações de manutenção. Se as suas falhas correlacionam em horário com backups ou migrações — aí está a resposta.

Erro seis: gestão dupla do horário

O guest agent do hypervisor e o daemon interno rodam ao mesmo tempo. O relógio pula, as falhas são intermitentes e não se reproduzem. Escolha um mecanismo e desligue o outro. Isso cura os bugs flutuantes mais desgastantes.

Erro sete: janelas estreitas demais sem margem

Se você desenvolve uma API com assinatura de requisição, não faça uma janela de tolerância de trinta segundos sem motivo forte. Uma margem razoável de alguns minutos reduz drasticamente a sensibilidade a pequenas dessincronizações dos clientes, sem sacrificar a proteção contra replay. Equilíbrio entre rigor e resiliência é uma decisão de engenharia, não um dogma.

Ferramentas e recursos

Vamos reunir o arsenal que vale ter à mão. Todas as ferramentas são padrão e legais, para operação normal de engenharia.

Linha de comando

  • date -u — olhada instantânea no tempo absoluto. Primeiro comando a rodar a qualquer suspeita.
  • timedatectl — status de sincronização e fuso em sistemas com systemd.
  • chronyc tracking e chronyc sources — diagnóstico profundo do chrony: desvio, fontes, estabilidade.
  • curl -sI ... | grep -i date — conferência de horário pelo header HTTP do response, funciona até onde não há daemons. Ideal para contêineres pelados e verificação via gateway.

Verificações por linguagem

  • Em Python: uma linha com utcnow e timestamp para conferência direto do ambiente de execução da aplicação.
  • Em Node: uma linha com toISOString e Date.now, para ver o horário pelos olhos do seu próprio runtime.
  • Decodificar o JWT sem validar assinatura, para ver com os próprios olhos os campos exp, nbf, iat e compará-los com o horário atual. Isso elimina adivinhações: você literalmente vê se o token venceu pelo seu relógio ou não.

O que monitorar continuamente

  • O desvio do relógio do sistema como métrica numérica com limites de atenção e alarme.
  • O status de haver uma fonte de tempo escolhida — indicador booleano de saúde da sincronização.
  • A frequência de erros TLS e de tokens por nó — um pico em um nó específico geralmente aponta para o relógio bagunçado dele.

Infraestrutura Proxeon

Ao operar via gateways Proxeon, recomendamos embutir a verificação de horário no script de inicialização dos seus nós de trabalho. Uma linha de conferência do header Date pelo gateway na inicialização — e você captura a dessincronização antes da primeira requisição de trabalho. É barato e reduz radicalmente a fração de chamados de suporte em que a raiz acaba sendo o relógio do lado do cliente, e não o proxy.

Casos e resultados

A teoria ganha vida em histórias reais. Vamos trazer casos generalizados da prática — números arredondados, detalhes descaracterizados, mas os padrões são absolutamente reais.

Caso um: desastre noturno do scraper após o backup

A equipe coletava dados via proxy 24 horas por dia. Toda noite, por volta das três, começava uma parede de erros certificate is not yet valid, e de manhã tudo se resolvia sozinho. Os engenheiros culparam o pool de proxies por duas semanas, trocaram endpoints, escreveram reclamações. A resposta veio quando alguém notou a correlação: as falhas começavam exatamente durante o backup noturno das VMs.

O hypervisor congelava a VM por um minuto e meio a dois minutos para tirar um snapshot consistente. Após o descongelamento, o relógio ficava atrasado por esses minutos, e o guest agent demorava a ajustá-lo. Na janela entre o descongelamento e a correção, o TLS rejeitava certificados novos como ainda não válidos — porque, pelo relógio atrasado, eles começavam a valer no futuro. A solução foi migrar para o chrony, com convergência rápida após salto, e monitorar o desvio imediatamente após as operações de backup. As falhas noturnas desapareceram totalmente, e o tempo de diagnóstico de problemas semelhantes futuros caiu de dias para minutos.

Caso dois: cem nós divergindo entre si

A organização distribuiu um parque de cem nós de trabalho a partir de uma única imagem. Na primeira semana, tudo funcionou. Depois começaram falhas flutuantes de assinatura de requisição em nós aleatórios — request timestamp too skewed. Não reproduzível: reinicia a tarefa e ela pode passar em outro nó.

A causa — a sincronização de horário não estava ativada na imagem. Os cem nós derivavam, cada um pelo seu quartzo. Os mais rápidos, em uma semana, passaram da janela de tolerância da assinatura. Uma varredura massiva de chronyc tracking em todo o parque mostrou desvios de frações de segundo a quinze segundos. Após ativar e verificar a sincronização real em todos os nós, além de adicionar a métrica de desvio ao monitoramento, as falhas cessaram. A conclusão da equipe: ao distribuir em massa, verificar não o fato de estar instalado, mas o fato de estar sincronizado.

Caso três: o desenvolvedor que ninguém entendia

Um engenheiro reclamava que localmente a autorização por TOTP no painel de controle não passava, embora funcionasse para todos. Ele digita o código correto, o sistema rejeita. Suspeitaram de problemas na conta dele.

Descobriram que ele, uma semana antes, tinha ajustado manualmente o horário do sistema da sua estação de trabalho para testar outro aplicativo e esquecido de voltar, e ainda tinha desligado a sincronização. O relógio saiu quase um minuto. O TOTP, com janela de trinta segundos, parou de coincidir. Ativar a sincronização automática resolveu tudo na hora. Moral: a tolerância estreita do TOTP é um detector embutido de dessincronização. Se os códigos não batem, olhe o relógio primeiro.

Caso quatro: contêiner com fuso alheio

Nos logs da aplicação no contêiner, o horário aparecia com três horas de diferença em relação ao host. Os engenheiros concluíram que o relógio do contêiner estava bagunçado e gastaram um dia tentando configurar sincronização dentro dele, quase dando privilégios extras ao contêiner.

A verificação de date -u dentro e fora mostrou o mesmo horário absoluto. O desvio era só na exibição: a imagem base tinha um fuso, o host tinha outro. A criptografia funcionava impecavelmente, porque em UTC tudo batia. Não havia problema real nenhum — só confusão cosmética nos logs. A lição custou um dia de trabalho: sempre distinga o tempo absoluto da sua exibição.

FAQ: respostas profundas para perguntas frequentes

O proxy pode bagunçar meu horário ou substituí-lo no TLS?

Em cenários normais de operação via gateway — não. O proxy repassa bytes entre você e o servidor de destino. A verificação da validade do certificado, dos campos exp e nbf, da janela de assinatura acontece do seu lado ou do lado do servidor final, com base nos relógios deles próprios. Por isso, diante de erros que parecem temporais, o suspeito principal é o relógio local do nó de trabalho, e não o gateway. O proxy só alonga a cadeia e desloca psicologicamente a suspeita para o meio.

Quão preciso o horário deve ser para tudo funcionar?

Para TLS a margem costuma ser grande — as janelas de validade dos certificados são medidas em dias, e mesmo um desvio de minutos geralmente passa despercebido, exceto em momentos na própria borda da renovação. Para JWT, tudo depende da vida útil do token: em tokens curtos, segundos já fazem diferença. Para assinaturas de requisição, a janela típica é de minutos, mas é melhor manter o desvio dentro de um segundo. O TOTP é o mais exigente — dezenas de segundos. Recomendação universal: mantenha o desvio dentro de um segundo, e você fica protegido contra todos os mecanismos citados de uma vez.

Por que o certificado mostra datas válidas, mas o cliente diz que ele ainda não é válido?

Porque o cliente compara as datas do certificado não com uma verdade absoluta, mas com o seu relógio local. Se o seu relógio está atrasado e mostra um momento anterior ao campo notBefore, para o cliente o certificado ainda não começou. As datas do próprio certificado, nesse caso, estão impecáveis. A resposta está sempre em conferir o seu date -u com uma referência. Essa é a fonte mais comum de travamento dos engenheiros.

É preciso instalar daemon de sincronização dentro do contêiner?

Não. O contêiner usa o relógio do kernel do host, então quem precisa ser sincronizado é o host. Instalar daemon dentro do contêiner é inútil e exige privilégios perigosos para alterar o horário do sistema, afetando todo o host. O modelo correto é um host sincronizado e vários contêineres vendo automaticamente o horário certo. Em orquestrador, a sincronização é garantida em cada nó-host.

Como distinguir um problema de horário de um problema real de proxy ou rede?

Comece pela verificação de horário — são dez segundos. Confira o date -u com uma referência e com o header HTTP Date via seu gateway. Se o desvio for pequeno e os erros de TLS e tokens persistirem — aí sim parta para a diagnóstico de rede. Se o desvio for grande — você achou a causa. O sinal-chave de problemas temporais: os erros contêm as palavras not yet valid, expired, skewed, signature com certificados sabidamente vivos e tokens frescos.

O que fazer logo após descongelamento ou migração de VM?

Garanta que o daemon de sincronização ajustou o relógio rapidamente. Para ambientes com congelamentos, o chrony é preferível, pois lida bem com saltos. Verifique chronyc tracking e confirme que o System time voltou a frações de segundo. Boa prática é forçar uma verificação de desvio após operações de manutenção e não disparar requisições assinadas críticas antes de o relógio convergir.

Um fuso horário errado afeta o funcionamento de TLS e tokens?

Não, desde que o tempo absoluto em UTC esteja correto. Toda a criptografia opera em UTC, e o fuso é só exibição para humanos. Um fuso errado vai te confundir nos logs, mas não vai derrubar TLS, JWT ou assinatura. É justamente por isso que o diagnóstico deve ser feito via UTC, e não via horário local. Confundir fuso com tempo absoluto é armadilha clássica.

Como embutir a verificação de horário no fluxo de trabalho via proxy?

Adicione ao script de inicialização do nó uma linha de conferência: requeira o header Date via seu gateway Proxeon e compare com o date -u local. Se a divergência passar do limite, interrompa a inicialização e dispare um alerta. Além disso, exporte o desvio do relógio do sistema para o monitoramento como uma métrica permanente com limites. Essas duas medidas capturam a esmagadora maioria dos incidentes de horário antes de virarem falhas de TLS e tokens.

Por que eu recebo

Sobre o autor

Andrey Kokh

Andrey Kokh

Leading Expert and Business Consultant

Experiência profissional: 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.
Formação: Higher School of Economics. Faculty of Economics, Master's Program
Especialização:
Strategic Consulting Digital Transformation Change Management Business Strategy Innovation Management Organizational Development Lean Management Agile Transformation

Compartilhe este artigo: