nginx 400 "일반 HTTP 요청이 HTTPS 포트로 전송되었습니다"오류 처리


115

승객 / nginx 뒤에서 Sinatra 앱을 실행하고 있습니다. http 및 https 호출에 모두 응답하도록 노력하고 있습니다. 문제는 둘 다 서버 블록에 정의되어있을 때 https 호출이 정상적으로 응답되지만 http가 400 "일반 HTTP 요청이 HTTPS 포트로 전송되었습니다"오류를 생성한다는 것입니다. 이것은 정적 페이지 용이므로 Sinatra가 이것과 아무 관련이 없다고 생각합니다. 이 문제를 해결하는 방법에 대한 아이디어가 있습니까?

다음은 서버 블록입니다.

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

제 경우에는 브라우저의 URL이 my.example.com:443작동하지 않았습니다. 대신 https://my.example.com작동 하도록 변경하십시오 . 이상하게도 아파치에이 문제가 없었습니다.
Sebastian

1
ssl on;NGINX에 SSL을 통해 모든 콘텐츠 를 서버에 알립니다 . listen 443;예를 들어 listen 443 ssl;서버가 http 및 https 트래픽을 모두 제공하는 경우 끝에 "ssl"플래그를 사용 하고 ssl on;지시문을 제거하십시오 .
Stphane

답변:


195

비슷한 문제가 발생했습니다. 한 서버에서 작동하며 동일한 Nginx 구성을 가진 다른 서버에서는 작동하지 않습니다. 여기에서 Igor가 답변 한 솔루션을 찾았습니다. http://forum.nginx.org/read.php?2,1612,1627#msg-1627

예. 또는 SSL / 비 SSL 서버를 하나의 서버에 결합 할 수 있습니다.

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

무엇 이오 시프을 rapam 것은 말한다 당, 당신은 또한 포함해야ssl off;
aceofspades

20
줄만 제거하면됩니다 ssl on;(ssl을 추가 할 필요 없음). 또한, 나는 어떤 Nginx에 버전을 기억하지 않기 때문에, 사용에 더 이상 필요가 없습니다 defaultlisten 443라인. 따라서 OP 구성은 괜찮 았으며 제거 ssl on하기 만하면 작동합니다.
laurent

@bobojam은 내 답변의 설명을 자유롭게 포함하여 귀하의 답변이 더 완벽해질 것입니다. OP 작성자에게 답변을 받아달라고 요청했습니다.
Alexander Azarov

2
주석을 달아 SSL 목적을 어떻게 해결합니까 ssl on? 아래 @ MichaelJ.Evans 답변은 훨씬 더 나은 솔루션입니다.
Neel

1
여러 conf 파일에서 작동하지 않는 것 같습니다. 2 개의 중복 기본값이 있다고 말합니다. Alexander의 솔루션을 사용하십시오.
Ryall

39

연결 보안에 관계없이 http를 통해 페이지를 제공 할 수 있도록 '이 연결 HTTPS'테스트를 대부분 무시한다는 점에서 위의 답변은 올바르지 않습니다.

NGINX 특정 http 4xx 오류 코드의 오류 페이지를 사용하여 클라이언트가 https로 동일한 요청을 재 시도하도록 리디렉션하는 보안 답변입니다. (여기에 설명 된대로 /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

OP는 다음을 사용해야합니다.

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;

  [....]
}

1
아마도 $ host 대신 $ server_name을 원할 것입니다. server_name은 아마도 SSL 인증서가 인증하는 CN으로 설정되어있을 것입니다. 이렇게하면 사용자가 IP 또는 로컬 호스트를 통해 들어온 경우 겁 화면이 표시되지 않습니다.
조지

나는 GitLab의 로컬 설치에서 이것을 구현하려고 했지만 GitLab 서버 블록에 사용자 정의 NGINX 설정 삽입을 사용했습니다. 방법을 사용 nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"하여 트릭을 수행했습니다.
Aaron C

17

오류는 실제로 모든 것을 말합니다. 구성은 Nginx에 포트 80 (HTTP)에서 수신하고 SSL을 사용하도록 지시합니다. 브라우저를 http://localhost로 지정하면 HTTP를 통해 연결을 시도합니다. Nginx는 SSL을 예상하기 때문에 오류로 불평합니다.

해결 방법은 매우 간단합니다. 두 개의 server섹션 이 필요 합니다.

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

7
실제로 두 개의 서버 섹션이 필요하지 않습니다. "ssl on"줄을 제거하고 @bobojam의 대답에 따라 청취 줄을 변경합니다.
toxaq

12

나는 똑같은 문제가 있었고 귀하의 예와 동일한 구성이 있으며 줄을 제거하여 작동하게했습니다.

ssl on;

문서를 인용하려면 :

HTTP 및 HTTPS 서버가 동일하면 "ssl on"지시문을 삭제하고 * : 443 포트에 대한 ssl 매개 변수를 추가하여 HTTP 및 HTTPS 요청을 모두 처리하는 단일 서버를 구성 할 수 있습니다.


1
문서에 대한 링크가 있습니까?
Adam Parkin

12

상태 코드 에 대한 위키피디아 기사에 따르면 . http 트래픽이 https 포트로 전송 될 때 Nginx에 사용자 지정 오류 코드가 있습니다 (오류 코드 497).

그리고 error_page의 nginx 문서에 따르면 특정 오류에 대해 표시 될 URI를 정의 할 수 있습니다.
따라서 오류 코드 497이 발생할 때 클라이언트가 전송 될 URI를 만들 수 있습니다.

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

그러나 클라이언트가 GET을 제외한 다른 방법을 통해 요청하면 해당 요청은 GET으로 바뀝니다. 따라서 클라이언트가 들어온 요청 방법을 보존합니다. error_page의 nginx 문서에 표시된대로 오류 처리 리디렉션을 사용합니다.

이것이 우리가 301 =307리디렉션 을 사용하는 이유 입니다.

여기에 표시된 nginx.conf 파일을 사용하여 http 및 https가 동일한 포트에서 수신하도록 할 수 있습니다.


이것은 나를 위해 작동합니다-error_page 497301 = 307 89.89.89.89:7000$request_uri ;
ugali soft

7

다음은 ipv6을 지원하는 동일한 구성 블록에서 HTTPHTTPS 를 구성하는 예 입니다. 구성은 Ubuntu ServerNGINX / 1.4.6 에서 테스트 되었지만 모든 서버에서 작동합니다.

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

오류 ssl on가 발생할 수있는 항목은 포함하지 마십시오 400. 위의 구성은

http://example.com

http://www.example.com

https://example.com

https://www.example.com

도움이 되었기를 바랍니다!



4

실제로 다음과 같이 할 수 있습니다.

ssl off; 

이것은 nginxvhosts 사용에 대한 내 문제를 해결했습니다. 이제 SSL과 일반 HTTP를 모두 사용할 수 있습니다. 결합 된 포트에서도 작동합니다.


에 나를 위해 작품의 nginx / 1.6.3 :
djthoms
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.