nginx blocos de localização não analisados conforme esperado

1

Estou tendo um problema estranho com uma configuração nginx. Eu tenho o seguinte bloco de servidores:

server {
  listen 80;
  listen [::]:80;

  server_name stats.example.com;
  root /usr/share/nginx/html;

  location = /foobar {
    return 403;
  }

  # ACME challenge configuration for Letsencrypt
  location ^~ /.well-known/acme-challenge/ {
    try_files $uri =404;
  }

  return 301 https://stats.example.com$request_uri;
}

Este é um bloco simples que deve redirecionar qualquer tráfego que não seja https para sua contraparte https. Eu tentei criar uma exceção para o "Desafio ACME" que o Certbot for Letsencrypt usa para validar um domínio antes de emitir um certificado. Eu tenho uma configuração semelhante em vários servidores e geralmente funciona sem problemas, mas neste servidor em particular, não parece analisar os blocos de localização corretamente. Para verificar o bloco do servidor, também adicionei o local /foobar personalizado, apenas para ter certeza de que, quando eu o atingisse, ele deveria lançar um 403.

Mas os dois blocos de localização parecem não funcionar. Sempre que eu solicito algo de um deles, ele retorna o 301 para o URL https, conforme definido na última linha do bloco de servidores:

% curl -I 'http://stats.example.com/foobar'
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Mon, 01 May 2017 11:25:10 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://stats.example.com/foobar

Ele faz o mesmo com as URLs de desafio da ACME, e é por isso que não consigo emitir um certificado para esse domínio usando o Certbot. O que estou perdendo aqui? Por que os blocos de localização não retornam o 403 ou o arquivo real (ou 404)? Por que o 301 é aplicado aqui para todos os URLs?

    
por Oldskool 01.05.2017 / 13:30

1 resposta

2

Eu descobri o problema depois de depurar e tentar mais algumas soluções. Aparentemente, a regra 301 é analisada pelo nginx antes de qualquer manipulação de bloco de localização, portanto, a 301 sempre foi a primeira e a última regra a ser aplicada a todas as URLs. Eu criei um bloco de localização "pega-tudo" separado que serve o 301 se nenhum outro local corresponder, então minha configuração final agora se parece com isso:

server {
  listen 80;
  listen [::]:80;

  server_name stats.example.com;
  root /usr/share/nginx/html;

  # ACME challenge configuration for Letsencrypt
  location ^~ /.well-known/acme-challenge/ {
    try_files $uri =404;
  }

  location / {    
    return 301 https://stats.example.com$request_uri;
  }
}

Agora consegui emitir o certificado usando o Certbot.

    
por 01.05.2017 / 14:25

Tags