Chainage de reverse proxy - Hébergement - Réseaux grand public / SoHo
Marsh Posté le 10-07-2024 à 13:15:21
Bonjour,
Comme ce n'est pas aussi simple que de seulement modifier la ligne "proxy_pass" sur serveur1 pour utiliser du HTTPS, voici la documentation officielle de Nginx à ce sujet :
https://docs.nginx.com/nginx/admin- [...] -upstream/
Bonne lecture !
Marsh Posté le 10-07-2024 à 23:41:10
Merci !
Je galère dans l'application au niveau des certificats/clefs.
Sur serveur 2 j'ai fait :
Dans la conf nginx serveur 1, j'ai ajouté :
Citation : |
Et dans la conf de serveur 2, j'ai utilisé les mêms fichiers de crt/key, juste modifié les directives nginx (sur serveur 1 les protocoles TLS et les ciphers sont gérés par certbot) :
Citation : |
Et j'ai une belle 502 du serveur 1, qui me dit dans les logs
SSL_do_handshake() failed (SSL: error:0A00010B:SSL routines::wrong version number) while SSL handshaking to upstream, client IP_DU_SERVEUR2
Je ne capte pas ce qui foire.
Marsh Posté le 11-07-2024 à 15:21:07
Le message d'erreur semble indiquer que serveur2 sur le port 8888 répond bien mais avec un protocole qui n'est pas du HTTPS.
Et pour cause, la configuration de serveur2 contient "listen 8888" .
Or, si tu bouquines la documentation de Nginx : http://nginx.org/en/docs/http/ngx_ [...] tml#listen , au moins jusqu'au moment où ça commence à parler de QUIC, tu t'apercevras peut-être du problème.
Spoiler : listen 8888 ssl; |
Marsh Posté le 11-07-2024 à 23:19:37
Anonymous Coward a écrit : Le message d'erreur semble indiquer que serveur2 sur le port 8888 répond bien mais avec un protocole qui n'est pas du HTTPS.
|
Merci pour ton aide !
J'ai vu après quelques heures de recherche et de die & retry qu'en effet il manquait la directive ssl. Mais ça ne résolvait pas l'erreur.
J'avais conclus aussi que nginx serveur 2 ne faisait pas du https.
Et c'est en fait ma méthode de génération de certificat qui était foireuse (en plus de la directive ssl manquante). J'essaie de comprendre pourquoi.
Premier mauvais point, mon serveur 2 a un FQDN localhost.localdomain, et dans ma génération de certificat sur serveur 2, je mettais subdomain.mondomain. Même si c'était raccord par rapport au server_name de nginx serveur 2, ça ne marchait pas. Est-ce que subdomain.mondomain était résolu quelque part et donc pointait sur serveur 1, j'en sais rien. Mais en changeant cela, ça a fonctionné.
Deuxième mauvais point, ma chaine de génération doit être mauvaise. Si je fais
Citation : sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt |
A la place de toute ma chaine de CSR & co : cela fonctionne.
J'arrive a priori (tcpdump est assez illisible comparé à mon premier essai où je voyais les entête HTTP sur seveur 2, donc j'en déduis que c'est chiffré) à avoir du https entre serveur 1 et serveur 2, uniquement avec nginx-selfsigned.key et nginx-selfsigned.crt
J'essaie de capter pourquoi la première méthode de génération des certificats que j'ai utilisé ne marchait pas. Car quand bien même c'était débile d'avoir un chiffrement côté serveur par un certificat et une clef qui se retrouvait aussi chez le client, ça aurait du marcher!
Et maintenant, pour faire comme dans la doc Securing HTTP Traffic to Upstream Servers, je m'escrime à essayer de faire de la validation de certificat client (déposé sur serveur 1) par serveur 2. Et même en utilisant le proxy_ssl_certificate , le serveur 2 me fait une 400 - No required SSL certificate was sent.
Mais je me rapproche de la solution.
Marsh Posté le 12-07-2024 à 15:56:23
Je suis ravi de constater que tu commences à bien savoir t'en dépatouiller.
Un serveur en HTTPS doit mettre à disposition la chaîne complète de certificats X.509 . D'où le nom " fullchain ".
Par exemple, il y a cet outil très pratique qui te permet d'explorer la chaîne de certificats pour un site tel que www.google.fr : https://www.digicert.com/help/
Tu peux voir que le "issuer" du certificat le plus bas de la chaîne est égal à la valeur "subject" du certificat d'au-dessus.
Concrètement, on peut générer un fullchain.pem en concaténant un fichier .crt de la CA, l'éventuel .crt de la CA intermédiaire et le .crt pour le serveur final. Du genre :
cat server.crt ca.crt >fullchain.pem |
( .pem ou .crt , c'est la même chose. Voir https://en.wikipedia.org/wiki/Priva [...] ail#Format )
( server.crt doit être en premier - http://nginx.org/en/docs/http/ngx_ [...] ertificate )
Pour un certificat auto-signé, la chaîne ne contient que le seul certificat auto-signé. Cela simplifie les choses.
Pour créer un certificat auto-signé avec openssl, je ferais :
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -sha256 -days 3653 -subj "/CN=serveur2.local" |
Ensuite, tu peux voir les informations du certificat avec :
openssl x509 -in cert.pem -noout -text |
Normalement, les champes Issuer et Subject du certificat sont identiques.
Je peux alors utiliser cert.pem pour la directive ssl_certificate et key.pem pour la directive ssl_certificate_key .
Marsh Posté le 18-07-2024 à 11:09:00
Pour l'authentification par certificat, je sèche.
Sur mon serveur 2, si je fais
Citation : curl -k --insecure --connect-to localhost:8888 https://localhost:8888 -v |
J'ai le serveur qui me répond No required SSL certificate was sent.
Normal car je ne passe pas de certificat. (le -k --insecure me sert à ne pas avoir d'erreur sur le fait que le certificat du serveur soit autosigné)
Lorsque je fais
Citation : curl -k --insecure --connect-to localhost:8888 https://localhost:8888--cert /etc/nginx/certificate/user.crt --key /etc/nginx/certificate/user.key |
Là cela fonctionne : j'ai bien l'appli en backend qui répond.
Et là ou je ne comprends pas, c'est que si je passe par le reverseproxy du serveur 1 qui a pourtant les bonnes directives, ça me fait toujours No required SSL certificate was sent.
Citation : |
EDIT : Je me demande si c'est possible sans modifier le code et tout recompiler d'après https://forum.nginx.org/read.php?2, [...] msg-258464
Marsh Posté le 19-07-2024 à 15:14:44
kray a écrit :
|
Il devrait être possible de faire quelquechose du genre :
curl --insecure --connect-to nomdedomaine.fr:443:127.0.0.1:8888 https://nomdedomaine.fr/ -v |
Le message "No required SSL certificate was sent." signifie qu'un serveur web demander un certificat TLS client avant de te laisser accéder à l'éventuelle page web.
Voir https://stackoverflow.com/a/69352444
Or, comme la configuration de TLS sur serveur2 a l'air de ne pas exiger de certificat TLS client, c'est peut-être le backend vers lequel serveur2 renvoie qui fait cette demande. Il faudrait vérifier avec, sur serveur2, un curl vers localhost:3000 .
Un tuto sur nginx paramétré pour demander un certificat client : https://fardog.io/blog/2017/12/30/c [...] ith-nginx/ . On voit bien qu'un certificat SSL/TLS client est demandé via la directive ssl_client_certificate .
Marsh Posté le 10-07-2024 à 08:55:36
Bonjour,
J'ai la situation suivante :
Client <==> Serveur 1 <==> Serveur 2 ( Docker avec les app)
Serveur 2 est mon serveur @home qui héberge mes applications sur un docker.
Serveur 1 est mon frontal hébergé en DC qui fait uniquement reverse proxy
Je veux passer les flux en HTTPS sur toute la chaine du client au serveur 2. Le serveur 2 fera la terminaison TLS, puisque mes applis sur docker ne gèrent pas nativement SSL/TLS.
J'arrive à faire du TLS entre Client et serveur 1 avec Serveur 1 qui héberge les certificats let's encrypt. (reverse proxy nginx)
Serveur 2 a un certificat autosigné.
Le flux arrive bien de client à l'appli de serveur 2, en TLS point de vue client. Mais j'ai l'impression que le lien serveur 1 <=> serveur 2 est en clair. En effet, que je mette les certificats ou pas dans la conf nginx du reverse proxy Serveur2, le flux a la même tronche via tcpdump (je vois les entêtes HTTP, je m'attendrai à tout voir chiffré).
Qu'ai je loupé pour que le flux entre serveur 1 et serveur 2 soit bien chiffré ?
Reverse Serveur 1
upstream monas {
server IP_DU_SERVEUR2:8888;
}
server {
server_name subdomain.domain.fr;
access_log /var/log/nginx/subdomain.access.log ;
error_log /var/log/nginx/subdomain.error.log warn;
index index.php;
location ^~ /.well-known/acme-challenge/ {
root /srv/subdomain/certs;
}
location / {
proxy_pass http://monas;
#proxy_redirect off;
proxy_set_header Host $http_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_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Url-Scheme $scheme;
proxy_pass_header Authorization;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/subdomain.domain.fr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/subdomain.domain.fr/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = subdomain.mondomaine) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name subdomain.mondomaine;
listen 80;
return 404; # managed by Certbot
}
Serveur 2
server {
server_name subdomain.domain.fr;
access_log /var/log/nginx/subdomain.access.log ;
error_log /var/log/nginx/subdomain.error.log warn;
index index.php;
location / {
proxy_pass http://localhost:3000;
#proxy_redirect off;
proxy_set_header Host $http_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_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Url-Scheme $scheme;
proxy_pass_header Authorization;
}
listen 8888
ssl_certificate /etc/nginx/conf.d/fullchain.pem;
ssl_certificate_key /etc/nginx/conf.d/privkey.pem;
}
---------------
I guess my real ennemy is me