Bloqueie o acesso direto ao IP do servidor web via HTTPS

5

Semelhante a this e < href="https://stackoverflow.com/questions/29104943/how-to-disable-direct-access-to-a-web-site-by-ip-address"> esta pergunta Eu quero bloquear usuários de usar o IP para acessar meu servidor.

Para HTTP (porta 80) isso funciona bem, mas não para HTTPS. Portanto, os usuários ainda podem inserir https://<myip> para acessar o servidor da Web e o nginx retorna o certificado padrão. BTW eu uso HTTP2 em meus blocos de servidores "usuais" (com meus nomes de domínio), então eu uso:

listen 443 ssl http2;
listen [::]:443 ssl http2;

Eu tentei isso para bloquear o acesso ip HTTPS agora:

server {
   listen 443 ssl;
   listen [::]:443 ssl;

   server_name _;
   return 444;
}

No entanto, infelizmente, isso bloqueia todas as solicitações HTTPS, independentemente de o domínio ser usado ou não. Eu sei que pode ser necessário bloquear clientes não-SNI, como é claro, eles não entregam o nome de domínio usado para o servidor, então estou bem com isso. (Eu quero dizer clientes que não suportam o SNI são velhos de qualquer maneira ...)

Eu geralmente prefiro bloquear isso no nginx, mas se você tiver algumas idéias sobre como bloquear isso no nível do firewall (iptables) eu também ficaria feliz em apreciá-las também. E se você quiser argumentar porque o bloqueio com o iptables é melhor, você também pode fazer isso e me convencer a bloquear também o HTTP [ou todos os outros] pedidos para o IP também. Geralmente, eliminar a conexão é bom (como faz o código de status nginx 444).

No entanto, há um requisito: não quero mencionar explicitamente o endereço IP do servidor na configuração, pois ele é um IP dinâmico e o servidor usa um serviço de DNS dinâmico.

Então, resumindo, aqui está o que eu quero alcançar:

  • bloqueia o acesso via IP
  • permitir acesso por meio do nome de domínio
  • não há problema em bloquear clientes não-SNI
  • não há problema em usar um bloqueio de firewall para isso
  • deixar cair a conexão está bem
  • sem mencionar o endereço IP do servidor
  • sem exposição do nome de domínio via HTTPS

Editar: outra tentativa falhada. Tentei seguir esta sugestão e usar este snippet de configuração, que parece logicamente bom:

if ($host != "example.com") {
        return 444;
}

Ele também funciona basicamente, mas quando eu acesso "https: //" eu vejo que nginx em primeiro lugar já envia o certificado HTTPS (contendo o nome do domínio) e somente quando pulo o aviso de conexão, vejo que ele bloqueia o acesso . Isso é lógico, pois o nginx só pode ler o cabeçalho do Host quando a conexão HTTPS estiver lá, mas neste momento o nginx já envia o certificado do servidor contendo o nome do domínio, portanto o usuário agora tem o nome de domínio e pode se reconectar usando o IP inteiro bloqueando inútil. Também estou um pouco preocupado com o aspecto de desempenho dessa solução, pois faz com que o nginx verifique o cabeçalho do host para cada solicitação, portanto, ainda estou procurando uma solução aqui.

    
por rugk 04.08.2016 / 22:53

2 respostas

3

Hoje, encontrei o mesmo problema com esse bloco:

server {
  listen 443 ssl default_server;
  server_name <SERVER-IP>;
  return 444;
}

O nginx-logs diz:

no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking

Como você mencionou, isso parece desabilitar os outros blocos de servidores também. É possível corrigir isso usando um certificado (autoassinado) para o endereço IP do servidor. Eu fiz isso usando o openssl:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt -subj '/CN=<SERVER-IP>'

Em seguida, altere o bloco do servidor para:

server {
    listen 443 ssl default_server;
    server_name <server-ip>;
    ssl_certificate         /path/to/certificate.crt;
    ssl_certificate_key     /path/to/privateKey.key;
    return 444;
}

Quando alguém usa o SERVER-IP via https para acessar o servidor, o nginx apresenta o certificado (autoassinado) e NÃO o certificado de nome de domínio que você deseja ocultar.

A propósito, faça seu server-block-with-IP o default_server. Dessa forma, um cliente que tenha o SNI desativado obterá o certificado IP e NÃO o certificado de nome de domínio. Isso também pode ser testado com o openssl (a opção -servername, que ativará o SNI, é omitida):

openssl s_client -connect <SERVER-IP>:443
    
por 26.05.2018 / 02:03
2

Tente isto - o bit default_server é a parte importante. Se não funcionar, por favor atualize sua pergunta mostrando a configuração para outros servidores ouvindo em 443 / SSL.

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server; # not sure if you want/need it here as well. Try both ways.

 server_name _;
 return 444;
}
    
por 04.08.2016 / 23:14