Substituir uma autoridade de certificação VPN não é trocar um ficheiro. No momento em que a nova AC assina o seu primeiro certificado, cada validador que ainda só confia na antiga tem de decidir, e os anfitriões que nunca recebem a nova âncora continuam a rejeitar pares válidos. Já vi isto falhar nos dois sentidos: a gateway aprendeu a nova AC e os clientes não, pelo que as novas ligações falhavam, enquanto os túneis já estabelecidos permaneciam e faziam a falha parecer um problema de encaminhamento. Eis o que muda, pela ordem em que os erros aparecem.

Uma substituição, duas alterações separadas

Uma autoridade de certificação é um nome, uma chave pública e a chave privada que assina. Os validadores nunca confiam em «a AC» de forma abstrata. Confiam num certificado concreto que já está num armazenamento de confiança, e só aceitam um emissor se uma cadeia de assinaturas chegar a essa cópia guardada. Substituir a AC altera, portanto, duas coisas que falham de forma independente: que âncoras são aceites e que identidades de pares foram emitidas sob elas.

A maioria das implementações de VPN valida nos dois sentidos. O cliente autentica o certificado da gateway e a gateway o do cliente. Uma rotação que só atualiza o pacote do cliente deixa o servidor a rejeitar todo o cliente que ainda apresente uma identidade da AC antiga, e o inverso é igualmente comum. Inventarie primeiro os pontos de aplicação: armazenamentos de confiança dos clientes, o ficheiro ca da gateway, qualquer proxy que termine TLS à sua frente e a sonda que verifica o ponto final a partir de fora.

O que um validador verifica, por ordem

A validação de caminho sobe do certificado do par pelos intermediários até atingir uma âncora de confiança. Em cada passo verifica a assinatura, confirma que cada certificado está dentro da sua janela de validade e confirma que as restrições básicas e o uso da chave permitem ao emissor assinar. Só então a aplicação olha para o certificado folha: os nomes alternativos do sujeito têm de cobrir o nome marcado, e o uso alargado da chave tem de permitir autenticação de servidor ou de cliente.

Para repetir esse percurso offline, aponte -CAfile ao pacote exato que vai implementar e não ao armazenamento do sistema. Caso contrário está a testar o anfitrião, não a alteração:

openssl verify -CAfile new-ca.crt gateway.crt
openssl verify -CAfile new-ca.crt -untrusted intermediate.crt client.crt
openssl x509 -in gateway.crt -noout -subject -issuer -dates
openssl s_client -connect gw.example.net:443 -CAfile new-ca.crt

Esse comando só funciona contra um ouvinte TLS simples como a página de administração HTTPS da gateway; o canal de controlo do OpenVPN precede o TLS, pelo que o s_client não consegue inspecionar o aperto de mão do túnel.

As regras de construção de caminho por trás desses erros estão em RFC 5280 secção 6. Explicam as falhas que de outro modo parecem arbitrárias: um intermediário expirado de que ninguém se lembrava, um certificado cujo uso da chave proíbe assinar, ou uma restrição de nome que exclui o anfitrião que está a testar.

Porque é que o túnel antigo continua a funcionar

O TLS e o OpenVPN mantêm viva uma sessão estabelecida depois de o aperto de mão terminar. Nada revalida o certificado do par por pacote, pelo que um cliente ligado antes da alteração continua a passar tráfego até renegociar, se voltar a ligar ou o túnel cair. É precisamente esta lacuna que faz com que uma substituição de AC pareça correta durante uma hora e depois falhe no pior momento: um portátil acorda, uma atribuição NAT expira, uma gateway reinicia.

A retoma de sessão estica ainda mais a ilusão. Um bilhete de sessão TLS permite ao cliente voltar sem reenviar certificados, e a retoma salta a validação de caminho porque o primeiro aperto de mão já a fez. O teste honesto é, por isso, um aperto de mão completo num processo novo. Reinicie o cliente em vez de religar o túnel, e num perfil de teste considere desativar os bilhetes para que o caminho de retoma não possa esconder uma cadeia quebrada.

Mantenha a camada de chave estática separada disto. O tls-auth acrescenta um HMAC ao canal de controlo, o tls-crypt cifra-o e autentica-o, e nenhum transporta material de certificado, pelo que rodar qualquer um deles é uma alteração separada com o seu próprio modo de falha. As implementações que confundem os dois acabam com um cliente cuja chave estática está bem, cujo certificado está desatualizado e cuja mensagem de erro não menciona nenhum dos dois.

A armadilha de reutilizar o nome do sujeito

É tentador reutilizar o nome distinto do antecessor para que nada a jusante tenha de mudar. Isso mantém a linha do emissor estável na interface e destrói o único sinal de que precisa. Dois certificados com sujeitos idênticos e chaves diferentes não se distinguem pelo nome, pelo que um pacote com as duas âncoras dá ao validador dois candidatos e nenhuma regra para escolher.

A construção de caminho pode então escolher o errado, reportar «não é possível obter o certificado do emissor local» quando a âncora correta está presente, ou ter sucesso num anfitrião e falhar noutro com o mesmo pacote, porque a ordem dos candidatos diferia. Se o nome tiver de ser reutilizado, mantenha as duas âncoras em ficheiros separados durante a transição e carregue-as explicitamente, e só as funda quando cada par apresentar o novo emissor. Caso contrário, dê à substituição um nome comum distinto — um sufixo de geração ou de data chega — para que os registos e os textos de erro digam sob que autoridade foi emitido o par que falha.

Uma rotação que não derruba a rede

Para uma substituição planeada, aceite as duas âncoras durante uma janela limitada em vez de mudar num único passo. Emita a nova AC e os seus intermediários, coloque a nova âncora no pacote de cada validador ao lado da antiga, e só depois comece a emitir certificados de pares a partir dela. Os pares com identidades antigas validam contra a âncora antiga; os novos funcionam contra a nova.

Feito nessa ordem, cada passo é reversível. A falha que evita é a mudança simultânea, em que um cliente que perdeu a atualização do pacote encontra uma gateway que já retirou a âncora antiga, o aperto de mão morre e nenhum registo diz que lado está desatualizado.

Retire na direção oposta. Reemita cada identidade que tem de sobreviver, confirme que cada uma apresenta a nova cadeia e só então remova a âncora antiga dos pacotes. Retire a chave privada da AC antiga de serviço, porque um emissor que ainda pode assinar significa que a rotação não terminou. Guarde os certificados e os registos de emissão para auditoria. Um emissor perdido é restaurado para a mesma confiança; uma exposição exige novas identidades e nenhum regresso à âncora antiga.

Verifique o resultado, não a lista de ficheiros

Um ficheiro de confiança no diretório esperado prova pouco. A aplicação pode ler outro caminho, outro formato ou uma cópia dentro de um pacote que uma atualização substitui. Verifique o comportamento nos dois extremos, não a existência de um ficheiro.

Confirme que uma ligação nova com uma identidade nova tem sucesso e depois confirme que uma identidade emitida pela AC retirada é recusada. Esse segundo teste é o que as pessoas saltam, e o único que mostra que a autoridade antiga já não concede acesso. Onde a implementação depende de CRL ou OCSP, verifique que os pontos de distribuição dos novos certificados se resolvem e que os pares que consultam alcançam o respondedor.

Termine com um cliente que nunca se ligou: apague o estado do seu perfil, ligue-o e leia a cadeia negociada. Um par que retoma uma sessão em cache relatará alegremente que a migração funcionou quando não validou nada.

Artigos relacionados