Trasformare un sito http Apache in un sito https sicuro tramite proxy inverso Nginx

Oct 12 2020

Devo supportare un vecchio sito WordPress in esecuzione su un server web Apache. Per rendere le cose più sicure, questo server Apache si trova in un container Docker ed è accessibile al mondo tramite la configurazione del proxy inverso Nginx. Questo sito è attualmente servito tramite http e vorrei spostarlo su https.

Penso di avere due opzioni:

  1. Il certificato SSL è installato per il sito Nginx e lo fa proxy_passper il semplice sito http sul contenitore 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;
         }
    }
    

    In questo scenario dal punto di vista del server Apache, sta ancora servendo il sito su http

  2. Questo è più laborioso: il certificato SSL è installato sia sul server gateway Nginx che sul sito Apache proxy. Poi sarebbe bisogno di cambiare httpper httpsnel proxy_passvalore di configurazione.

Vorrei che tutto andasse bene con il primo scenario. Ma il fatto che Apache senta di servire roba su http introduce alcuni problemi: ci sono alcuni reindirizzamenti di URL nascosti che mi piacerebbe davvero non riconfigurare / eseguire il debug. E quei reindirizzamenti URL fanno qualcosa di simile: se l'URL richiesto è http://www.example.com, viene riscritto (stato http 301) come http://www.example.com/main. Questo reindirizzamento viene ricevuto dal browser e quindi, anche se la prima richiesta era su https, ora l'URL reindirizzato è http. Anche l'html dei siti contiene href a percorso completo del server alle proprie risorse (file JavaScript e CSS) che includono anche il riferimento al protocollo. Non è chiaro a questo punto se quegli href adottano il protocollo da come è stata fatta la richiesta, o se è hardcoded. Ad ogni modo, sfortunatamente questo non funziona senza un serio approfondimento.

Quindi, mi rimane l'opzione 2. Ho provato, funziona, posso impostare lo stesso certificato SSL sia su Nginx che su Apache containerizzato. Ma mi piacerebbe sapere se è davvero così che dovrebbe essere lasciato in funzione. Perché sebbene il server Apache ora sappia che il contenuto viene servito su https, ora avviene il doppio SSL-ing per ogni richiesta. Non mi sembra giusto.

Risposte

3 hardillb Oct 12 2020 at 20:48

Dovresti essere in grado di dire ad Apache che la richiesta in arrivo viene inviata tramite proxy da una richiesta HTTPS con la proxy_set_header X-Forwarded-Proto "https";dichiarazione nella prima configurazione

3 Mark Oct 12 2020 at 23:16

Puoi risolvere il problema nella tua opzione n. 1 (che, come hai detto, è un approccio molto migliore) impostando HTTP_X_FORWARDED_PROTO nella tua configurazione nginx con

proxy_set_header X-Forwarded-Proto $scheme;

e configurare WordPress per riconoscerlo aggiungendo questa riga a wp-config.php

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

Vedi anche l' articolo di supporto di Wordpress per una variazione di questa soluzione.

1 HermanB Oct 12 2020 at 22:57

Normalmente preferirei fare tutto il lavoro pesante sul proxy inverso e mantenere il sito di backend che viene esposto il più originale possibile.

Il tuo problema sembra essere essenzialmente che il backend (WordPress) genera e utilizza URI (assoluti) che differiscono da ciò che desideri che i visitatori utilizzino.

Puoi rimediare a ciò riscrivendo il contenuto (HTML) che WordPress genera in nginx con ngx_http_sub_module . Ciò ti consentirà anche di riscrivere gli URL assoluti con qualcosa di simile 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;                
    }