Nginx. Como rejeito uma solicitação ao servidor virtual ssl não listado?

12

Eu tenho um certificado SSL curinga e vários subdomínios no mesmo ip. Agora, quero que o meu nginx manipule apenas os nomes de servidor mencionados e elimine a conexão de outros, para que pareça que nginxnão está sendo executado por nomes de servidores não listados (sem responder, rejeitar, inoperante, sem um único byte em resposta). Eu faço o seguinte

ssl_certificate         tls/domain.crt;
ssl_certificate_key     tls/domain.key;

server {
  listen 1.2.3.4:443 ssl;
  server_name validname.domain.com;
  //
}

server {
  listen 1.2.3.4:443 ssl;
  server_name _;
  // deny all;
  // return 444;
  // return 404;
  //location {
  //  deny all;
  //}
}

Eu tentei quase tudo no último bloco de servidores, mas sem sucesso. Recebo resposta válida do servidor virtual conhecido ou código de erro. Por favor ajude.

andbi
fonte

Respostas:

7

Não funciona dessa maneira: o handshake SSL acontece antes do HTTP; portanto, o nome no certificado será avaliado no navegador antes que você possa redirecionar ou fazer qualquer outra coisa dentro da configuração do nginx.

cjc
fonte
isso é ruim, mas tenho que admitir) Obrigado.
andbi
3
Isso não é verdade: você pode fazer outra coisa em nível inferior, como interromper a conexão sem nenhuma resposta, conforme explicado em outras respostas.
19414 collimarco
12

A resposta por cjc já apontou corretamente o problema ao tentar corresponder os nomes de host quando o SSL está ativado. No entanto, é possível fazê-lo, assim:

server {
    ...

    if ($host !~* ^validname\.domain\.com$ ) {
        return 444;
    }
    ...
}

Nota: sim, é verdade que geralmente ifé mau , mas é seguro usá if-lo neste caso. (Leia a página vinculada se precisar se convencer.)

Ao contrário do que foi sugerido, apenas adicionar o seguinte bloco não funcionará:

server {
    listen 80;
    listen 443 ssl;
    return 444;
}

porque um certificado SSL correspondente validname.domain.comnão corresponde a um nome de domínio aleatório. Eu tentei e o nginx agiu como se o bloco não estivesse presente.

Isso também não funcionará:

server {
    listen       443;
    server_name    _;
    return 444; 
}

porque fará com que todas as conexões HTTPS na porta 443 falhem, mesmo aquelas que devem passar. Eu tentei este também. wgetrelatou um erro de handshake SSL.

Louis
fonte
4

A maioria das respostas aqui são sobre por que não funciona, não como fazê-lo funcionar.

Aqui está como - você precisa tornar esse servidor abrangente um 'default_server' e precisa fornecer caminhos para cert / key para que ele possa descriptografar a solicitação de entrada SSL e corresponder ao cabeçalho Host:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404;
}

Observe o ssl_certificate / ssl_certificate_key lá. Se eles não forem especificados, o nginx ainda tentará usar esse servidor_servidor padrão e falhará, pois não pode aceitar a conexão ssl sem uma chave / certificado. Pode-se usar qualquer certificado / chave, por exemplo, autoassinado. ...

Para gerar um certificado autoassinado:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 

Consulte também /server//a/841643/87439

andreycpp
fonte
1
Você já tentou isso? Como você cria um certificado SSL que corresponde ao nome do servidor "_"?
Tim
Sim, esta solução funciona para mim. Eu tive o mesmo problema exato e descobri na documentação que o nginx precisa de um certificado / chave, pois não analisa o TLS SNI. Você pode usar qualquer certificado / chave, por exemplo, autoassinado.
30517 Andreycpp
1

Eu implementei a solução acima hoje e funcionou muito bem. Todos os URLs não especificados são descartados agora. Colocar esse código do servidor antes da entrada real do servidor virtual foi fundamental - todos os URLs malformados agora passam para esse servidor 'padrão'.

... 
server {
     listen       443;
     server_name    _;
     return 444; }

server {
     listen       443;
     server_name  [URL]
david sexton
fonte
0

Você deve conseguir lidar com isso, tornando o servidor que lida com os itens não listados o primeiro bloco de servidor em sua configuração.

http {
    ...

    server {
        listen 80;
        listen 443 ssl;
        return 444;
    }

    server {
        server_name validname.domain.com;
        ...
    }
}

Todos os domínios não identificados especificamente serão tratados por este bloco de servidor.

Dayo
fonte
1
Ele não funciona
AmirHossein