Consente di crittografare con un proxy inverso nginx


45

introduzione

Ho un server di sviluppo (attualmente in esecuzione Ubuntu 14.04 LTS), che utilizzo da un po 'di tempo per ospitare vari strumenti di sviluppo su porte diverse. Poiché le porte possono essere difficili da ricordare, ho deciso di utilizzare la porta 80 per tutti i miei servizi e di eseguire il port forwarding internamente, in base al nome host.

Invece di scrivere domain.com:5432, posso semplicemente accedervi tramite sub.domain.com

Ad esempio l'applicazione X, che utilizza la porta 7547 ed è in esecuzione su sub.domain.com ha la seguente configurazione nginx:

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}

La domanda

Data l'attuale struttura di configurazione, che ho scelto, è possibile utilizzare letsencrypt ed eseguire i diversi servizi in https?


3
Ho scritto un post sul blog su questo argomento: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime
Tom Busby

Risposte:


81

Sì, puoi avere richieste proxy nginx ai server HTTP e quindi rispondere ai client tramite HTTPS. Nel fare ciò, vorrai essere sicuro che è improbabile che il nginx <-> proxy connect venga annusato da chiunque sia l'attaccante atteso. Approcci sufficientemente sicuri potrebbero includere:

  • inoltro allo stesso host (come fai tu)
  • inoltro ad altri host dietro il firewall

Inoltro a un altro host su Internet pubblico è improbabile che sia abbastanza sicuro.

Ecco le istruzioni per ottenere un certificato Let's Encrypt usando lo stesso server web che stai usando come proxy.

Richiesta del certificato iniziale da Let's Encrypt

Modifica la tua serverclausola per consentire alla sottodirectory .well-knowndi essere servita da una directory locale, ad esempio:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known è dove i server Let's Encrypt cercheranno le risposte alle sfide che pone.

È quindi possibile utilizzare il client certbot per richiedere un certificato da Let's Encrypt utilizzando il plug-in webroot (come root):

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

La chiave, il certificato e la catena di certificati verranno ora installati /etc/letsencrypt/live/sub.domain.com/

Configurazione di nginx per utilizzare il certificato

Innanzitutto crea una nuova clausola del server in questo modo:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

Ricarica nginx:

service nginx reload

Verifica che HTTPS funzioni ora visitando https://sub.domain.come https://www.sub.domain.comnel tuo browser (e qualsiasi altro browser che desideri supportare in modo specifico) e verificando che non riportino errori di certificato.

Consigliato: rivedere anche raymii.org: forte sicurezza SSL su nginx e testare la configurazione presso SSL Labs .

(Consigliato) Reindirizzare le richieste HTTP a HTTPS

Dopo aver verificato che il tuo sito funziona con la https://versione dell'URL, piuttosto che alcuni utenti hanno pubblicato contenuti non sicuri perché sono andati a http://sub.domain.com, reindirizzarli alla versione HTTPS del sito.

Sostituisci l'intera serverclausola port 80 con:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

Ora dovresti anche decommentare questa linea nella configurazione della porta 443, in modo che i browser ricordino di non provare nemmeno la versione HTTP del sito:

add_header Strict-Transport-Security "max-age=31536000";

Rinnova automaticamente il tuo certificato

È possibile utilizzare questo comando (come root) per rinnovare tutti i certificati noti a certbot e ricaricare nginx utilizzando il nuovo certificato (che avrà lo stesso percorso del certificato esistente):

certbot renew --renew-hook "service nginx reload"

certbot tenterà solo di rinnovare i certificati che hanno più di 60 giorni, quindi è sicuro (e consigliato!) eseguire questo comando molto regolarmente e, se possibile, automaticamente. Ad esempio, è possibile inserire il seguente comando /etc/crontab:

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

Puoi testare i rinnovi con una versione a secco, che contatterà i server di gestione temporanea Let's Encrypt per fare un vero test di contatto con il tuo dominio, ma non memorizzerà i certificati risultanti:

certbot --dry-run renew

Oppure puoi forzare un rinnovo anticipato con:

certbot renew --force-renew --renew-hook "service nginx reload"

Nota: puoi eseguire la corsa a secco tutte le volte che vuoi, ma i rinnovi reali sono soggetti ai limiti di velocità Let's Encrypt .


Il tuo soluton non sembra funzionare per me. Ho sostanzialmente la stessa configurazione. Funziona con goopen.tk, ma non con www.goopen.tk
Alko,

3
@Alko, le istruzioni per la risposta sono corrette e riguardano questo problema. Quando si utilizza certboto qualsiasi altro strumento, non si può dimenticare di specificare il dominio in formato www e non www per funzionare.
Paulo Coghi - Ripristina Monica il

Sotto location /.well-known, è necessario lasciare .well-knownfuori il percorso. Usa alias /var/www/sub.domain.com, nonalias /var/www/sub.domain.com/.well-known
gldraphael il

1
Qualcuno può spiegarmi perché vorresti usare "rewrite ^ https: // $ host $ request_uri? Permanente;" qui invece di "return 301 https: // $ nome_server $ request_uri;"
ZaxLofful,

Ho scoperto che avevo bisogno di virgolette attorno al percorso in posizione. location '/.well-known' {. Non sono sicuro se questa è una versione della versione o solo la mia configurazione, ma nel caso in cui qualcun altro sia bloccato.
Frank V,

2

Sì, puoi utilizzare nginxcome end point di https e collaborare con i backend tramite http. Ad esempio la mia configurazione:

server {
        server_name host;
        listen 443 ssl;
...
 location /svn/ {
            auth_ldap off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_pass http://localhost:1080/svn/;
            proxy_redirect http://localhost:1080/ https://host/;
        }
...
}

Ma come so, con crittografiamo devi puntare tutti i sottodomini quando ottieni il certificato, e se questo è un problema, allora scegli url https://host/serviceinvece dihttps://service.host

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.