Gestion de nginx 400 Erreur "La simple requête HTTP a été envoyée au port HTTPS"

115

J'exécute une application Sinatra derrière passager / nginx. J'essaie de le faire répondre aux appels http et https. Le problème est que lorsque les deux sont définis dans le bloc serveur, les appels https reçoivent normalement une réponse, mais http génère une erreur 400 "La requête HTTP simple a été envoyée au port HTTPS". Ceci est pour une page statique, donc je suppose que Sinatra n'a rien à voir avec cela. Des idées pour résoudre le problème?

Voici le bloc serveur:

server {
        listen 80;
        listen 443  ssl;
        server_name localhost;
        root /home/myhome/app/public;
        passenger_enabled on;

        ssl on;
        ssl_certificate      /opt/nginx/ssl_keys/ssl.crt;
        ssl_certificate_key  /opt/nginx/ssl_keys/ssl.key;
        ssl_protocols        SSLv3 TLSv1;
        ssl_ciphers          HIGH:!aNULL:!MD5;

        location /static {
            root  /home/myhome/app/public;
            index  index.html index.htm index.php;
        }

        error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 /500.html;

        access_log /home/myhome/app/logs/access.log;
        error_log /home/myhome/app/logs/error.log;
}
Johnny
la source
Dans mon cas, l'URL du navigateur: my.example.com:443ne fonctionnait pas. Changer cela au lieu de cela a https://my.example.comfonctionné. Bizarre, je n'ai jamais eu ce problème avec Apache.
Sebastian
1
ssl on;dit à NGINX de serveur TOUT contenu via SSL. Utilisez l'indicateur "ssl" à la fin de votre listen 443;exemple listen 443 ssl;si votre serveur délivre à la fois le trafic http et https, et supprimez la ssl on;directive.
Stphane

Réponses:

195

J'ai rencontré un problème similaire. Cela fonctionne sur un serveur et pas sur un autre serveur avec la même configuration Nginx. J'ai trouvé la solution à laquelle Igor a répondu ici http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Oui. Ou vous pouvez combiner des serveurs SSL / non SSL dans un seul serveur:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}
bobojam
la source
Selon ce que dit rapam iosif, assurez-vous d'inclure égalementssl off;
aceofspades
20
Il vous suffit de supprimer la ligne ssl on;(pas besoin d'ajouter ssl off). De plus, comme je ne me souviens plus de la version de Nginx, il n'est plus nécessaire de l'utiliser defaulten listen 443ligne. La configuration OP était donc correcte, il suffit de la supprimer ssl onet cela devrait fonctionner.
laurent
@bobojam, n'hésitez pas à inclure l'explication de ma réponse, afin que la vôtre soit plus complète. J'ai demandé à l'auteur de l'OP d'accepter votre réponse.
Alexander Azarov
2
Comment résout-il l'objectif SSL en commentant ssl on. @ La réponse de MichaelJ.Evans ci-dessous est une bien meilleure solution.
Neel
1
Ne semble pas fonctionner avec plusieurs fichiers de configuration. Dit qu'il y a 2 valeurs par défaut en double. Utilisez la solution d'Alexandre.
Ryall
39

Les réponses ci-dessus sont incorrectes dans la mesure où la plupart écrasent le test «est cette connexion HTTPS» pour permettre de servir les pages via http indépendamment de la sécurité de la connexion.

La réponse sécurisée utilisant une page d'erreur sur un code d'erreur http 4xx spécifique à NGINX pour rediriger le client pour qu'il réessaye la même requête vers https. (comme indiqué ici /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

Le PO doit utiliser:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$host:$server_port$request_uri;

  [....]
}
Michael J. Evans
la source
1
Vous voulez probablement $ server_name au lieu de $ host, le server_name étant vraisemblablement défini sur le CN que le certificat SSL authentifie. De cette façon, l'utilisateur n'obtiendra pas d'écran d'alarme s'il est entré via une adresse IP ou un hôte local.
George
J'essayais de l'implémenter sur mon installation locale de GitLab , mais j'ai utilisé l' insertion de paramètres NGINX personnalisés dans la méthode de blocage du serveur GitLab , ce qui a nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"fait l'affaire
Aaron C
17

L'erreur dit tout en fait. Votre configuration indique à Nginx d'écouter sur le port 80 (HTTP) et d'utiliser SSL. Lorsque vous pointez votre navigateur vers http://localhost, il essaie de se connecter via HTTP. Puisque Nginx attend SSL, il se plaint de l'erreur.

La solution de contournement est très simple. Vous avez besoin de deux serversections:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}
Alexandre Azarov
la source
7
Vous n'avez pas besoin de deux sections de serveur. Supprimez la ligne "ssl on" et modifiez les lignes d'écoute selon la réponse de @ bobojam.
toxaq
12

J'ai eu exactement le même problème, j'ai un peu la même configuration que votre exemple et je l'ai fait fonctionner en supprimant la ligne:

ssl on;

Pour citer la doc:

Si les serveurs HTTP et HTTPS sont égaux, un seul serveur qui gère à la fois les requêtes HTTP et HTTPS peut être configuré en supprimant la directive «ssl on» et en ajoutant le paramètre ssl pour le port *: 443

Remiz
la source
1
Avez-vous une chance d'avoir le lien vers doc?
Adam Parkin
12

Selon l' article de Wikipédia sur les codes d'état . Nginx a un code d'erreur personnalisé lorsque le trafic http est envoyé au port https (code d'erreur 497)

Et selon les documents nginx sur error_page , vous pouvez définir un URI qui sera affiché pour une erreur spécifique.
Ainsi, nous pouvons créer un uri auquel les clients seront envoyés lorsque le code d'erreur 497 est déclenché.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

Cependant, si un client fait une demande via une autre méthode à l'exception d'un GET, cette demande sera transformée en GET. Ainsi, pour conserver la méthode de requête par laquelle le client est entré; nous utilisons des redirections de traitement d'erreur comme indiqué dans la documentation nginx sur error_page

Et c'est pourquoi nous utilisons la 301 =307redirection.

En utilisant le fichier nginx.conf montré ici, nous pouvons avoir http et https écouter sur le même port

Komu
la source
cela fonctionne pour moi - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft
7

Voici un exemple pour configurer HTTP et HTTPS dans le même bloc de configuration avec le support d' ipv6 . La configuration est testée dans Ubuntu Server et NGINX / 1.4.6 mais cela devrait fonctionner avec tous les serveurs.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

N'incluez pas ssl once qui peut provoquer une 400erreur. La configuration ci-dessus devrait fonctionner pour

http://example.com

http://www.example.com

https://example.com

https://www.example.com

J'espère que cela t'aides!

Madan Sapkota
la source
4

si vous utilisez phpmyadmin, ajoutez: fastcgi_param HTTPS activé;

Rodrigo Gregorio
la source
4

En fait, vous pouvez le faire avec:

ssl off; 

Cela a résolu mon problème d'utilisation de nginxvhosts; maintenant, je peux utiliser SSL et HTTP ordinaire. Fonctionne même avec des ports combinés.

rapan iosif
la source
Fonctionne pour moi sur nginx / 1.6.3 :)
djthoms