Lidando com o erro nginx 400 “A solicitação HTTP simples foi enviada para a porta HTTPS”

115

Estou executando um aplicativo Sinatra por trás do passageiro / nginx. Estou tentando fazer com que ele responda às chamadas http e https. O problema é que, quando ambos são definidos no bloco do servidor, as chamadas https são respondidas normalmente, mas o http produz um erro 400 "A solicitação HTTP simples foi enviada para a porta HTTPS". Isso é para uma página estática, então estou supondo que Sinatra não tem nada a ver com isso. Alguma ideia de como consertar isso?

Este é o bloco do servidor:

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
fonte
No meu caso foi que o url no navegador: my.example.com:443não funcionou. Mudar isso em vez de https://my.example.comfuncionar. Estranho, nunca tive esse problema com o apache.
Sebastian
1
ssl on;diz ao NGINX para servir QUALQUER conteúdo por meio de SSL. Use a sinalização "ssl" no final do seu, listen 443;por exemplo, listen 443 ssl;se o seu servidor entregar tráfego http e https, e remova a ssl on;diretiva.
Stphane

Respostas:

195

Eu encontrei um problema semelhante. Ele funciona em um servidor e não em outro servidor com a mesma configuração Nginx. Encontrou a solução respondida por Igor aqui http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Sim. Ou você pode combinar servidores SSL / não SSL em um servidor:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}
bobojam
fonte
De acordo com o que o rapam iosif diz, certifique-se de incluir tambémssl off;
aceofspades
20
Você só precisa remover a linha ssl on;(não há necessidade de adicionar SSL off). Além disso, como não me lembro qual versão do Nginx, não há mais necessidade de usar defaulton- listen 443line. Então a configuração do OP estava OK, só precisa remover ssl one deve funcionar.
Laurent
@bobojam sinta-se à vontade para incluir a explicação da minha resposta, para que a sua seja mais completa. Pedi ao autor do OP para aceitar sua resposta.
Alexander Azarov
2
Como isso resolve o propósito do SSL comentando ssl on. A resposta de @MichaelJ.Evans abaixo é uma solução muito melhor.
Neel
1
Não parece funcionar com vários arquivos conf. Diz que há 2 padrões duplicados. Use a solução de Alexander.
Ryall
39

As respostas acima estão incorretas no sentido de que a maioria substitui o teste 'esta conexão é HTTPS' para permitir a exibição das páginas por http, independentemente da segurança da conexão.

A resposta segura usando uma página de erro em um código de erro http 4xx específico do NGINX para redirecionar o cliente para tentar novamente a mesma solicitação para https. (conforme descrito aqui /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

O OP deve usar:

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
fonte
1
Você provavelmente quer $ server_name em vez de $ host, o server_name presumivelmente sendo definido para o CN que o certificado SSL autentica. Dessa forma, o usuário não obterá uma tela assustadora se entrar através de um IP ou localhost.
George
Eu estava tentando implementar isso no meu local de instalação do gitlab , mas usou as configurações Inserção personalizada Nginx no bloco de servidor gitlab método assim nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"fez o truque
Aaron C
17

O erro diz tudo na verdade. Sua configuração diz ao Nginx para escutar na porta 80 (HTTP) e usar SSL. Quando você aponta seu navegador parahttp://localhost , ele tenta se conectar via HTTP. Como o Nginx espera SSL, ele reclama do erro.

A solução alternativa é muito simples. Você precisa de duas serverseções:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}
Alexander Azarov
fonte
7
Na verdade, você não precisa de duas seções de servidor. Remova a linha "ssl on" e altere as linhas de escuta de acordo com a resposta de @obojam.
toxaq
12

Eu tive exatamente o mesmo problema, tenho meio que a mesma configuração do seu exemplo e o fiz funcionar removendo a linha:

ssl on;

Para citar o documento:

Se os servidores HTTP e HTTPS forem iguais, um único servidor que lida com solicitações HTTP e HTTPS pode ser configurado excluindo a diretiva “ssl on” e adicionando o parâmetro ssl para a porta *: 443

Remiz
fonte
1
Alguma chance de você ter o link para o documento?
Adam Parkin
12

De acordo com o artigo da Wikipedia sobre códigos de status . O Nginx tem um código de erro personalizado quando o tráfego http é enviado para a porta https (código de erro 497)

E de acordo com a documentação do nginx em error_page , você pode definir um URI que será mostrado para um erro específico.
Assim, podemos criar um uri para o qual os clientes serão enviados quando o código de erro 497 for gerado.

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

No entanto, se um cliente fizer uma solicitação por meio de qualquer outro método, exceto GET, essa solicitação será transformada em GET. Assim, para preservar o método de solicitação por meio do qual o cliente entrou; usamos redirecionamentos de processamento de erro, conforme mostrado em documentação do nginx em error_page

E é por isso que usamos o 301 =307 redirecionamento.

Usando o arquivo nginx.conf mostrado aqui, podemos fazer com que http e https escutem na mesma porta

Komu
fonte
isso funciona para mim - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft
7

Aqui está um exemplo para configurar HTTP e HTTPS no mesmo bloco de configuração com suporte a ipv6 . A configuração é testada no Ubuntu Server e NGINX / 1.4.6, mas deve funcionar com todos os servidores.

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ão inclua, o ssl onque pode causar 400erro. A configuração acima deve funcionar para

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Espero que isto ajude!

Madan Sapkota
fonte
4

se usar phpmyadmin add: fastcgi_param HTTPS on;

Rodrigo Gregorio
fonte
4

Na verdade, você pode fazer isso com:

ssl off; 

Isso resolveu meu problema de usar nginxvhosts; agora posso usar SSL e HTTP simples. Funciona mesmo com portas combinadas.

Rapan Iosif
fonte
Funciona para mim em nginx / 1.6.3 :)
djthoms