Pourquoi un listen 443 default_server; Les règles nginx remplacent les règles déjà configurées (les règles http fonctionnent de manière normale)?

9

J'ai un nginx et différents sous-domaines:

a.mydomain.com
b.mydomain.com
c.mydomain.com

Nginx a 4 règles:

1) règle de réécriture:

server {
  listen 80
  server_name gl.udesk.org;

  root /nowhere;
  rewrite ^ https://a.mydomain.com$request_uri permanent;
}

2) règle https:

server {

  listen 443;
  server_name a.mydomain.com;

  root /home/a/a/public;

  ssl on;
  ssl_certificate conf.d/ssl/a.crt;
  ssl_certificate_key conf.d/ssl/a.key;
  ssl_protocols ...
  ssl_ciphers ...
  ssl_prefer_server_ciphers on;

  location ...
}

3) règle http par défaut:

server {
  listen 80 default_server;
  return 444;
}

4) règle https par défaut:

server {
  listen 443 default_server;
  return 444;
}

Donc si je lance nginx et:

  • Si je vais dans le navigateur pour http://a.mydomain.com, il redirige vers https://a.mondomaine.com , puis renvoie une erreur 107 (net :: ERR_SSL_PROTOCOL_ERROR): erreur de protocole SSL.
  • si je vais dans le navigateur à https://b.mydomain.com j'attends qu'il renvoie l'erreur 444. Mais au lieu de cela, il renvoie la même erreur 107 (net :: ERR_SSL_PROTOCOL_ERROR): erreur de protocole SSL.
  • et ainsi de suite pour tous les inscrits par les CNAME du fournisseur DNS (c'est-à-dire a, b, c)
  • toutes les versions http (par exemple, la règle 3 -) fonctionnent comme prévu:

Pourquoi les règles https de nginx sont-elles si difficiles à configurer et comment dois-je les configurer correctement pour obtenir le même comportement que pour la version http?

Mettre à jour:

Créer un nouveau certificat et ajouter:

ssl on;
ssl_certificate conf.d/ssl/default.crt;
ssl_certificate_key conf.d/ssl/default.key;

fonctionne maintenant, mais j'aurais une solution sans aucun certificat SSL nécessaire. Il suffit de réinitialiser toutes les connexions pour tous les sous-domaines https (port 443), à l'exception de https://a.mydomain.com, sans fournir de certificat.

statique
la source
2
Tu ne peux pas. SSL nécessite un certificat avant que le serveur Web sache quel domaine vous souhaitez . Il doit avoir un certificat à envoyer ou il ne peut pas établir la connexion pour parler au client.
Darth Android
2
@DarthAndroid: la magie s'appelle SNI - fr.wikipedia.org/wiki/Server_Name_Indication .
Shi
@Shi Je suis au courant de la SNI - Cela permet de choisir le serveur Web qui certificat à envoyer, mais il faut encore choisir un certificat. nginxn'est pas assez intelligent pour se rendre compte qu'il n'a pas besoin d'un certificat pour ce que l'utilisateur veut faire.
Darth Android

Réponses:

3

Ne mélangez pas le port 443 avec le port SSL! Nginx est complètement agnostique au port. Vous pouvez également proposer https via le port 80. Les versions nginx modernes permettent

listen 1234 ssl;

et vous n'avez pas besoin de la ssl on;ligne alors.

Mais si vous voulez servir https, vous devez spécifier un certificat. Votre serveur entre https lorsqu'il réécrit la requête http en requête https.

Vous obtenez l'ERREUR DE PROTOCOLE, car la négociation SSL est effectuée avant toute autre chose. Donc return 444n'est pas atteint. Et toute poignée de main SSL nécessitera un certificat et une clé privée pour alimenter les algorithmes de chiffrement avec la paire certificat / clé privée.

Ikrabbe
la source
3

La returndirective fait partie du module de réécriture. Si vous consultez la documentation , vous constaterez peut-être que cela fonctionne avec les demandes. Dans HTTPS, les demandes ne peuvent être effectuées qu’après la prise de contact.

Il existe une demande de fonctionnalité: https://trac.nginx.org/nginx/ticket/195 et une solution de contournement est fournie.

server {
    listen 443 ssl;
    server_name bbb.example.com;
    ssl_ciphers aNULL;
    ssl_certificate /path/to/dummy.crt;
    ssl_certificate_key /path/to/dummy.key;
    return 444;
}
VBart
la source
Notez que ce brisera clients HTTPS non-SNI capables (comme propre Nginx proxy_pass, à moins que vous définissez proxy_ssl_server_name on;) d'atteindre tout autre server_names(essentiellement , PORTER légitime server_namede ce que vous ne voulez laisser passer). Voir trac.nginx.org/nginx/ticket/195#comment:11 pour plus de détails.
nh2