57 votes

Lets Encrypt avec un proxy inverse nginx

Introduction

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

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

Par exemple, l'application X, qui utilise le port 7547 et tourne sur sub.domain.com, a 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 letsencrypt et de faire fonctionner les différents services sous https ?

93voto

Snow Lizard Points 11

Oui, vous pouvez faire en sorte que nginx envoie des requêtes par proxy à des serveurs HTTP, et qu'il réponde lui-même aux clients par HTTPS. Dans ce cas, vous devez vous assurer que la connexion nginx<->proxy n'est pas susceptible d'être reniflée par l'attaquant prévu. Approches suffisamment sûres pourrait inclure :

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

Il est peu probable que l'utilisation d'un proxy vers un autre hôte sur l'internet public soit suffisamment sûre.

Voici des instructions pour obtenir un certificat Let's Encrypt en utilisant le même serveur web que celui que vous utilisez comme proxy.

Demande de certificat initial auprès de Let's Encrypt

Modifiez votre server pour autoriser le sous-répertoire .well-known pour ê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 est l'endroit où les serveurs de Let's Encrypt chercheront les réponses aux défis qu'ils posent.

Vous pouvez alors utiliser la fonction certbot pour demander un certificat à Let's Encrypt à l'aide de l'option 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 sont désormais installés dans le dossier /etc/letsencrypt/live/sub.domain.com/

Configurer nginx pour qu'il utilise votre certificat

Créez d'abord une nouvelle clause serveur comme suit :

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 désormais en consultant la page suivante https://sub.domain.com y https://www.sub.domain.com dans votre navigateur (et tout autre navigateur que vous souhaitez spécifiquement prendre en charge) et vérifiez qu'ils ne signalent pas d'erreurs de certificat.

Recommandé : voir aussi raymii.org : Sécurité SSL forte sur nginx et testez votre configuration à l'adresse SSL Labs .

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

Une fois que vous avez confirmé que votre site fonctionne avec l'application https:// de l'URL, plutôt que d'offrir à certains utilisateurs un contenu non sécurisé parce qu'ils sont allés sur la page http://sub.domain.com les redirige vers la version HTTPS du site.

Remplacer l'ensemble du port 80 server clause avec :

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

Vous devez également décommenter cette ligne dans la configuration du port 443, afin que les navigateurs se souviennent qu'ils ne doivent 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 en utilisant le nouveau certificat (qui aura le même chemin que votre certificat existant) :

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

certbot ne tentera de renouveler que 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 en effectuant un essai à blanc, qui contactera les serveurs de Let's Encrypt pour effectuer un test réel de contact avec votre domaine, mais aussi en effectuant un essai à l'aveugle. ne le fera pas stocker les certificats qui en résultent :

certbot --dry-run renew

Vous pouvez également imposer un renouvellement anticipé avec :

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

Remarque : vous pouvez effectuer des essais à blanc autant de fois que vous le souhaitez, mais les renouvellements réels sont soumis aux conditions suivantes Limites de taux de Let's Encrypt .

2voto

fghj Points 176

Oui, vous pouvez utiliser nginx en tant que point final de https et coopérer avec les backends via http. Par exemple, ma configuration :

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 let's encrypt vous devez pointer tous les sous-domaines lorsque vous obtenez le certificat, et si cela pose un problème, alors vous choisissez l'url https://host/service au lieu de https://service.host

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X