Transformar um site Apache http em um site https seguro por meio do proxy reverso Nginx

Oct 12 2020

Tenho que oferecer suporte a um antigo site WordPress em execução no servidor web Apache. Para tornar as coisas mais seguras, esse servidor Apache está em um contêiner Docker e pode ser acessado por todo o mundo por meio da configuração de proxy reverso Nginx. Este site é servido atualmente por http e eu gostaria de movê-lo para https.

Acho que tenho duas opções:

  1. O certificado SSL é instalado para o site Nginx e também proxy_passpara o site http simples no contêiner Apache:

    server {
        listen      443 ssl;
        server_name www.example.com;
    
        ssl_certificate /etc/nginx/ssl/letsencrypt/live/www.example.com/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/letsencrypt/live/www.example.com/privkey.pem;
    
        access_log  /var/log/nginx/example.com.access.log;
    
        location /  {
            proxy_pass       http://Apache2-PHP5.6:80;
            proxy_set_header Host            $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }
    }
    

    Neste cenário, do ponto de vista do servidor Apache, ele ainda está servindo o site via http

  2. Isso é mais trabalhoso: o certificado SSL é instalado no servidor Nginx do gateway e no site Apache com proxy. Em seguida, seria necessário alterar httppara httpso proxy_passvalor de configuração.

Eu gostaria que tudo estivesse bem com o primeiro cenário. Mas o fato de o Apache sentir que está servindo coisas por meio de http apresenta alguns problemas: existem alguns redirecionamentos de URL ocultos que eu realmente gostaria de não reconfigurar / depurar. E esses redirecionamentos de URL fazem algo assim: se a URL solicitada for http://www.example.com, ela será reescrita (status 301 http) como http://www.example.com/main. Esse redirecionamento é recebido pelo navegador e, portanto, embora a primeira solicitação tenha sido por https, agora o URL redirecionado é http. Além disso, o html do site contém hrefs de caminho completo de servidor para seus próprios recursos (arquivos JavaScript e CSS) que incluem também a referência de protocolo. Não está claro neste ponto se esses hrefs adotam o protocolo de como a solicitação foi feita ou se ele está codificado. De qualquer forma, infelizmente isso não funciona sem uma análise séria.

Então, fico com a opção 2. Eu tentei, funciona, posso configurar o mesmo certificado SSL no Nginx e no Apache em contêiner. Mas gostaria de saber se é realmente assim que deve continuar funcionando. Porque embora o servidor Apache agora saiba que o conteúdo está sendo servido por https, agora há SSL-ing duplo acontecendo para cada solicitação. Não parece certo.

Respostas

3 hardillb Oct 12 2020 at 20:48

Você deve ser capaz de dizer ao Apache que a solicitação de entrada está sendo proxy de uma solicitação HTTPS com a proxy_set_header X-Forwarded-Proto "https";declaração na primeira configuração

3 Mark Oct 12 2020 at 23:16

Você pode resolver o problema em sua opção # 1 (que, como você disse, é uma abordagem muito melhor) definindo HTTP_X_FORWARDED_PROTO em sua configuração nginx com

proxy_set_header X-Forwarded-Proto $scheme;

e configurar o WordPress para reconhecê-lo anexando esta linha a wp-config.php

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on';
}

Consulte também o artigo de suporte do Wordpress para obter uma variação dessa solução.

1 HermanB Oct 12 2020 at 22:57

Normalmente, eu preferiria fazer todo o trabalho pesado no proxy reverso e manter o site de back-end que fica exposto o mais original possível.

Seu problema parece ser basicamente que o backend (WordPress) gera e usa URIs (absolutos) que diferem do que você deseja que os visitantes usem.

Você pode remediar isso reescrevendo o conteúdo (HTML) que o WordPress gera no nginx com o ngx_http_sub_module . Isso também permitirá que você reescreva URLs absolutos com algo semelhante a:

    location / {    
         sub_filter 'http://example.com/' 'https://www.example.com/' ;
         sub_filter 'http://www.example.com/' 'https://www.example.com/' ;
         sub_filter_once off;
         proxy_pass       http://Apache2-PHP5.6:80;
         proxy_set_header Host            $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                
    }