Eu quero reescrever todas as solicitações http no meu servidor web para serem solicitações https, comecei com o seguinte:
servidor { ouça 80; local / { reescrever ^(.*) https://mysite.com$1 permanente; } ...
Um problema é que isso elimina qualquer informação de subdomínio (por exemplo, node1.mysite.com/folder), como eu poderia reescrever o acima para redirecionar tudo para https e manter o subdomínio?
Maneira correta em novas versões do nginx
Acontece que minha primeira resposta a esta pergunta estava correta em determinado momento, mas se transformou em outra armadilha - para se manter atualizado, verifique Armadilhas de reescrita de impostos
Fui corrigido por muitos usuários do SE, então o crédito vai para eles, mas o mais importante, aqui está o código correto:
NOTA: A melhor maneira de fazer isso foi fornecida por https://serverfault.com/a/401632/3641 - mas é repetida aqui:
No caso mais simples, seu host será corrigido para ser o serviço para o qual você deseja enviá-los - isso fará um redirecionamento 301 para o navegador e a URL do navegador será atualizada de acordo.
Abaixo está a resposta anterior, que é ineficiente devido ao regex, um simples 301 é ótimo, como mostrado por @kmindi
Eu tenho usado o nginx 0.8.39 e superior e usei o seguinte:
Envia um redirecionamento permanente para o cliente.
Eu acho que a melhor e única maneira deve ser usar um redirecionamento HTTP 301 movido permanentemente assim:
O redirecionamento HTTP 301 movido permanentemente também é o mais eficiente, pois não há regex a ser avaliada, de acordo com os pitfails já mencionados .
O novo HTTP 308 Moved Permanently preserva o método Request e é suportado pelos principais navegadores . Por exemplo, usar
308
impede que os navegadores alterem o método de solicitação dePOST
paraGET
para a solicitação de redirecionamento.Se você deseja preservar o nome do host e o subdomínio, este é o caminho.
Isso ainda funciona se você não tiver DNS , pois também o estou usando localmente. Estou solicitando, por exemplo, com
http://192.168.0.100/index.php
e será redirecionado para exatamentehttps://192.168.0.100/index.php
.Eu uso
listen [::]:80
no meu host porque eubindv6only
configurei parafalse
, então ele também se liga ao soquete ipv4. mude paralisten 80
se você não quiser IPv6 ou quiser vincular em outro lugar.A solução de Saif Bechan usa o
server_name
que no meu caso é localhost, mas que não é acessível por uma rede.A solução de Michael Neale é boa, mas de acordo com os pitfails, existe uma solução melhor com o redirecionamento 301 ;)
Dentro do bloco do servidor, você também pode fazer o seguinte:
O acima não funcionou com novos subdomínios sendo criados o tempo todo. por exemplo, AAA.example.com BBB.example.com para cerca de 30 subdomínios.
Finalmente consegui uma configuração trabalhando com o seguinte:
Postei um comentário sobre a resposta correta há muito, muito tempo com uma correção muito importante, mas sinto que é necessário destacar essa correção em sua própria resposta. Nenhuma das respostas anteriores é segura de usar se em algum momento você configurou um HTTP não seguro e espera conteúdo do usuário, tem formulários, hospeda uma API ou configurou qualquer site, ferramenta, aplicativo ou utilitário para falar com seu site.
O problema ocorre quando uma
POST
solicitação é feita ao seu servidor. Se a resposta do servidor com um30x
redirecionamento simples, o conteúdo do POST será perdido. O que acontece é que o navegador/cliente atualizará a solicitação para SSL, mas fará o downgrade paraPOST
umaGET
solicitação. OsPOST
parâmetros serão perdidos e uma solicitação incorreta será feita ao seu servidor.A solução é simples. Você precisa usar um
HTTP 1.1 307
redirecionamento. Isso é detalhado na RFC 7231 S6.4.7:A solução, adaptada da solução aceita, é usar
307
em seu código de redirecionamento:Consegui fazer assim:
https://stackoverflow.com/a/36777526/6076984
Estou executando o ngnix atrás de um AWS ELB. O ELB está conversando com o ngnix por http. Como o ELB não tem como enviar redirecionamentos aos clientes, verifico o cabeçalho X-Forwarded-Proto e redireciono:
Se você
return 301 https://$host$request_uri;
for a resposta padrão na porta 80, seu servidor poderá mais cedo ou mais tarde entrar em uma lista de proxies abertos[1] e começar a ser abusado para enviar tráfego para outro lugar na Internet. Se seus logs estiverem cheios de mensagens como esta, você saberá que isso aconteceu com você:O problema é que
$host
vai ecoar de volta o que o navegador enviar noHost
cabeçalho ou até mesmo o nome do host da linha de abertura do HTTP, como esta:Por causa desse problema, algumas outras respostas aqui recomendam usar
$server_name
em vez de$host
.$server_name
sempre avalia o que você coloca naserver_name
declaração. Mas se você tiver vários subdomínios ou usar um curinga, isso não funcionará, porque$server_name
usará apenas a primeira entrada após aserver_name
declaração e, mais importante, apenas ecoará um curinga (não o expandirá).Então, como oferecer suporte a vários domínios mantendo a segurança? Em meus próprios sistemas, lidei com esse dilema listando primeiro
default_server
um bloco que não usa$host
, e depois listando um bloco curinga que usa:(Você também pode listar mais de um domínio no segundo bloco.)
Com essa combinação, os domínios sem correspondência serão redirecionados para algum lugar codificado (sempre
example.com
), e os domínios que corresponderem ao seu irão para o lugar certo. Seu servidor não será útil como um proxy aberto, então você não atrairá problemas.Se você está se sentindo mal-humorado, suponho que você também pode fazer com que o
default_server
bloco não corresponda a nenhum de seus domínios legítimos e sirva algo ofensivo. . . .[1] Tecnicamente "proxy" é a palavra errada, pois seu servidor não está saindo e atendendo as requisições dos clientes, apenas enviando um redirecionamento, mas não tenho certeza qual seria a palavra certa. Também não tenho certeza de qual é o objetivo, mas ele enche seus logs com ruído e consome sua CPU e largura de banda, então você pode parar com isso.
Parece que ninguém realmente acertou 100%. Para que as solicitações da porta 80 vão para seus equivalentes 443 para um servidor web inteiro, você precisa usar a diretiva listen , não a diretiva server_name para especificar o nome catch-all. Veja também https://nginx.org/en/docs/http/request_processing.html
E certifique-se de verificar o que já está em /etc/nginx/conf.d/ porque na maioria das vezes eu tive problemas em que o default.conf retornava alguns vhosts existentes. Minha ordem de trabalho com problemas do nginx é sempre começar removendo o arquivo padrão, colocando-o de volta comentando linha por linha para ver onde está errado.