Permet de chiffrer avec un proxy inverse nginx

45

introduction

J'ai un serveur de développement (fonctionnant actuellement sous Ubuntu 14.04 LTS), que j'utilise depuis un certain temps maintenant pour héberger divers outils de développement sur différents ports. Comme les ports peuvent être difficiles à retenir, j'ai décidé d'utiliser le port 80 pour tous mes services et d'effectuer la redirection de port en interne, en fonction du nom d'hôte.

Au lieu d'écrire domain.com:5432, je peux simplement y accéder via sub.domain.com

Par exemple, l'application X, qui utilise le port 7547 et s'exécute sur sub.domain.com, présente la configuration nginx suivante:

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 question

Compte tenu de la structure de configuration actuelle, que j'ai choisie, est-il possible d'utiliser letCrypt et d'exécuter les différents services sous https?

0x450
la source
3
J'ai écrit un article de blog sur ce sujet: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no- downtime
Tom Busby le

Réponses:

81

Oui, vous pouvez avoir des requêtes proxy nginx sur des serveurs HTTP, puis répondre aux clients via HTTPS. Ce faisant, vous voudrez vous assurer qu'il est peu probable que la connexion proxy nginx <-> soit détectée par tout attaquant attendu. Les approches suffisamment sûres pourraient inclure:

  • proxy par le même hôte (comme vous le faites)
  • proxy vers d'autres hôtes derrière votre pare-feu

La procuration auprès d'un autre hôte sur l'Internet public ne sera probablement pas assez sûre.

Voici les instructions pour obtenir un certificat Let's Encrypt en utilisant le même serveur Web que celui que vous utilisez en tant que proxy.

Demander votre certificat initial à Let's Encrypt

Modifiez votre serverclause pour permettre au sous-répertoire .well-knownd'être servi à partir d'un répertoire local, par exemple:

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 C’est là que les serveurs de Let's Encrypt chercheront les réponses aux défis qu’il soulève.

Vous pouvez ensuite utiliser le client certbot pour demander un certificat à Let's Encrypt en utilisant le plugin webroot (en tant que root):

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

Votre clé, votre certificat et votre chaîne de certificats seront désormais installés dans /etc/letsencrypt/live/sub.domain.com/

Configurer nginx pour utiliser votre certificat

Commencez par créer une nouvelle clause de serveur comme ceci:

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
        […]
    }
}

Recharger nginx:

service nginx reload

Vérifiez que le protocole HTTPS fonctionne maintenant en visitant https://sub.domain.comet https://www.sub.domain.comdans votre navigateur (et tous les autres navigateurs que vous souhaitez spécifiquement à l' appui) et vérifier qu'ils ne signalent pas les erreurs de certificat.

Recommandé: consultez également raymii.org: sécurité SSL renforcée sur nginx et testez votre configuration dans les laboratoires SSL .

(Recommandé) Rediriger les requêtes HTTP vers HTTPS

Une fois que vous avez confirmé que votre site fonctionne avec la https://version de l'URL, redirigez-le vers un contenu non sécurisé, car http://sub.domain.comredirigez-le vers un contenu non sécurisé car redirigez-le vers la version HTTPS du site.

Remplacez l'intégralité de votre serverclause du port 80 par:

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

Vous devez également maintenant supprimer la mise en commentaire de cette ligne dans la configuration du port 443, afin que les navigateurs se souviennent de ne même pas essayer la version HTTP du site:

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

Renouveler automatiquement votre certificat

Vous pouvez utiliser cette commande (en tant que root) pour renouveler tous les certificats connus de certbot et recharger nginx à l'aide du nouveau certificat (qui aura le même chemin que votre certificat existant):

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

certbot essaiera uniquement de renouveler les certificats datant de plus de 60 jours. Il est donc prudent (et recommandé!) d'exécuter cette commande très régulièrement , et automatiquement si possible. Par exemple, vous pouvez mettre la commande suivante dans /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"

Vous pouvez tester les renouvellements avec une exécution à sec, qui contactera les serveurs de transfert Let's Encrypt pour faire un test réel de contact avec votre domaine, mais ne stockera pas les certificats résultants:

certbot --dry-run renew

Ou vous pouvez forcer un renouvellement anticipé avec:

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

Remarque: vous pouvez exécuter le test autant de fois que vous le souhaitez, mais les vrais renouvellements sont soumis aux limites de débit de Let's Encrypt .

perplexité
la source
Votre solution ne semble pas fonctionner pour moi. J'ai fondamentalement la même configuration. Cela fonctionne pour goopen.tk, mais pas www.goopen.tk
Alko
3
@Alko, les instructions de réponse sont correctes et couvrent ce problème. Lorsque vous utilisez certbotou tout autre outil, vous ne pouvez pas oublier de spécifier votre domaine au format www et non-www pour fonctionner.
Paulo Coghi - Réintégrer Monica
Sous location /.well-known, vous devez laisser .well-knowndehors dans le chemin. Utilisez alias /var/www/sub.domain.com, pasalias /var/www/sub.domain.com/.well-known
gldraphael
1
Quelqu'un peut-il m'expliquer pourquoi vous voudriez utiliser "rewrite ^ https: // $ host $ request_uri? Permanent;" ici au lieu de "return 301 https: // $ server_name $ request_uri;"
ZaxLofful
J'ai trouvé qu'il me fallait des guillemets autour du chemin. location '/.well-known' {. Je ne sais pas s'il s'agit d'une version ou de ma configuration, mais au cas où quelqu'un d'autre serait bloqué.
Frank V
2

Oui, vous pouvez utiliser nginxcomme point final de https et coopérer avec les backends via http. Par exemple ma config:

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/;
        }
...
}

Mais comme je le sais, avec le cryptage, vous devez pointer tous les sous-domaines lorsque vous obtenez un certificat, et si cela pose un problème, vous choisissez alors l’URL https://host/serviceau lieu dehttps://service.host

fghj
la source