Existe alguma maneira de configurar um Nginx sem um certificado público?
O objetivo aqui é: eu quero publicar uma API na Internet pública, mas todos os clientes da API (clientes na lista de permissões) devem fixar SSL no certificado público em seus aplicativos, em vez de obter o certificado ad hoc por solicitação. Portanto, não precisamos do nginx para publicar o certificado público.
Entendo que o certificado público é inofensivo para ser compartilhado publicamente, mas esta solicitação peculiar vem de nosso cliente corporativo. Eles até perguntaram se podemos colocar um certificado público inválido no nginx... então, quando um "invasor" que não possui o certificado público real verá a API como um erro, enquanto clientes genuínos com SSL fixados poderão usar a API normalmente.
Sua pergunta (e justificativa) para a pergunta feita não faz muito sentido tecnicamente. Posso fazer algumas declarações que espero que possam ser úteis para você -
Para configurar o NGinx sem um certificado público você usaria HTTP (ou seja, abandonar a criptografia). HTTPS foi projetado em torno da criptografia pública/privada, portanto não faria sentido para o Nginx não usá-lo.
É possível criar um certificado autoassinado e os usuários "fixá-lo". Você também pode criar sua própria CA com um certificado de CA autoassinado para poder emitir vários certificados.
Seus clientes corporativos não sabem o quanto não sabem. Um invasor simplesmente aceitaria o certificado inválido e continuaria. Um certificado criptografa a sessão entre o navegador e o servidor - não impede que um navegador acesse o conteúdo se não tiver um certificado público, nem significa que o servidor pode confiar no cliente.
Se você deseja aumentar a segurança, consulte os certificados do lado do cliente . Isso é quase o inverso do tipo de certificado de que você está falando. Na verdade, você executa sua própria CA e assina chaves públicas - e então exige que essas chaves sejam usadas quando um cliente está se comunicando com você (e isso é suportado pela maioria dos navegadores, mas não é trivial para você pensar na implantação - é é bastante prático) Isso basicamente valida os clientes para o servidor. Se todos os clientes estão se comunicando por meio de uma API - esta não é uma prática comum com APIs, mas deve lhe dizer algo - por que não usar apenas um certificado HTTPS normal e, em seguida, um segredo compartilhado?
Não é possível fazer autenticação de servidor baseada em certificado sem que o servidor forneça o certificado. Isso inclui a fixação de certificados no cliente - o que exige que o servidor também envie o certificado para verificá-lo em relação ao certificado fixado.
É possível permitir que o nginx use um certificado autoassinado ou emitido por uma CA privada. Não há nada de especial nisso, basta configurar este certificado. Quando os clientes verificam apenas se um certificado específico é servido, é possível que esse certificado autoassinado não contenha nenhuma informação real, como assunto, etc., ele precisa conter a chave pública, embora corresponda à chave privada.
Não é possível servir um certificado para alguns clientes (os bons) e outro diferente para outros clientes (os ruins), a menos que os clientes possam ser distinguidos antes que o certificado seja enviado dentro do handshake TLS. Tal distinção poderia ser feita exclusivamente com base em informações baseadas em TCP, como o endereço IP de origem. Ou os clientes podem usar algum nome de domínio não público oculto no SNI (ou seja, diferente daquele usado na pesquisa de DNS) que corresponda a uma configuração diferente no nginx.
O certificado do servidor não está realmente envolvido na configuração da criptografia TLS. Seu único propósito é verificar a conexão que foi configurada – o TLS poderia de fato funcionar sem certificados, e isso não impediria o invasor de estabelecer a conexão. Portanto o plano não funcionaria; é tecnicamente viável, mas totalmente inútil.
(Pode ser que seu cliente esteja se lembrando de como funcionavam as versões antigas de SSL e TLS; costumava ser algo comum usar a chave RSA do certificado diretamente como parte da troca de chaves TLS; mas não foi assim que funcionou para muitos anos. O TLSv1.3 nem tem mais essa opção.)
Isso também é completamente inútil pelas razões explicadas acima. Em primeiro lugar, o invasor não precisa do certificado – um certificado incorreto é algo que pode ser simplesmente ignorado pelo cliente TLS.
(Na verdade, você poderia lembrar ao cliente que provavelmente ele mesmo fez isso quando visitou um site com um certificado expirado e clicou em "Ignorar certificado"... Embora isso não seja realmente a mesma coisa - o certificado nesse caso era tecnicamente válido – seu cliente provavelmente não será capaz de perceber a diferença, então ainda poderá entender.)
Existem duas opções válidas que você pode usar:
Use certificados de cliente , também conhecidos como “ mTLS ” – uma escolha muito comum para APIs de acesso restrito. Isso exigiria que cada cliente API tivesse seu próprio certificado que envia ao servidor e que é verificado pelo servidor (pelo cliente usando sua própria chave privada para fornecer prova). Diga ao seu cliente que é isso que os bancos reais usam em suas APIs de pagamento.
Use a autenticação PSK , que é uma opção válida no TLSv1.3 e não usa nenhum certificado. (Acho que também pode ter sido uma opção válida no TLSv1.2, mas no AFAIK houve mudanças no TLSv1.3 que tornaram o PSK muito mais viável nessa versão.) Com esse modo, tanto o cliente quanto o servidor compartilham o que parece muito parecido com um nome de usuário e uma senha (a 'identidade PSK' e o próprio PSK), mas diferentemente das senhas normais, o PSK está realmente envolvido no estabelecimento da criptografia – sem fornecer um PSK válido é impossível fazer a conexão TLS.
Isenção de responsabilidade: SE minha resposta funcionar, isso envolve quebrar o TLS padrão. Eu trabalharia apenas com um cliente HTTP personalizado.
Sem discutir o mérito da sua abordagem (outras respostas fizeram isso), estou me perguntando se ... Você não poderia "simplesmente" fornecer um certificado diferente, um dos quais a chave pública não corresponde à sua chave privada. Pode haver um mecanismo que impedirá o funcionamento do nginx se você tentar fazê-lo. E você teria que garantir em seu cliente que pode configurar a pilha HTTP para ignorar completamente o certificado enviado pelo servidor e usar o certificado integrado.
Não tenho um conhecimento muito profundo de TLS, mas "imagino" que a chave de criptografia negociada para criptografar o tráfego (por exemplo, usando ECDH) será negociada usando a chave pública do servidor, chave pública que é ( acredito) contida no certificado.
Portanto, um cliente que estabelecesse um canal criptografado usando a chave pública no certificado enviado pelo seu servidor falharia, pois a chave privada no seu servidor não corresponderia à chave pública no certificado.