Nginx로 SSL을 통해 www가 아닌 ​​www를 www로 리디렉션


25

https://example.comhttps://www.example.com 으로 리디렉션하려고 할 때 오류가 발생했습니다 .

https://example.com으로 이동하면 리디렉션되지 않고 page / 200 상태를 반환합니다.

나는 이것을 원하지 않고 https://www.example.com 으로 리디렉션하기를 원합니다 .

http://example.com으로 이동하면 https://www.example.com으로 리디렉션됩니다.

누가 내가 잘못 가고 있는지 말해 줄 수 있습니까?

이것이 내 기본 및 기본 SSL 구성 파일입니다.

default.conf

server {
    listen 80;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

default-ssl.conf

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}
server {
    server_name www.example.com;

    listen 443;
    root /home/app/myproject/current/public;
    index index.html index.htm;

    error_log /srv/www/example.com/logs/error.log info;
    access_log /srv/www/example.com/logs/access.log combined;

    ssl on;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
    ssl_prefer_server_ciphers on;

    client_max_body_size 20M;


    try_files $uri/index.html $uri.html $uri @app;


    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

1
2 개의 conf 파일을 만드는 요점은 무엇입니까?
Sandip Subedi

우려 사항을 구분할 때 비 SSL 구성은 너무 작아서 SSL 전용 구성과 분리하는 것이 가장 좋았습니다.
Thomas V.

답변:


34

listenfile에 지시문 이 누락되었습니다 default-ssl.conf. listen 443;이 지시어에 추가

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

기본적으로이 지시문을 생략하면 nginx는 포트 80 에서 수신 대기한다고 가정합니다. 여기 에이 기본 동작에 대한 문서 가 있습니다.


편집 : @TeroKilkanen의 의견에 감사드립니다.

여기 default-ssl.conf에 대한 완전한 설정

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    return 301 https://www.example.com$request_uri;
}

주석 : ssl on;지시문 listen 443 ssl;nginx 문서의 권장 사항으로 대체 할 수 있습니다 .


4
또한 설정해야 ssl_certificate하고 ssl_certificate_key이 블록에 지시를하고 사용 listen 443 ssl;하므로이 SSL 가상 호스트입니다.
Tero Kilkanen

현재의 내용을 게시하십시오 default-ssl.conf. 아마도 오타 나 재정렬 문제로 인해 발생했을 수 있습니다.
masegaloeh

이 문제는 당황 스럽습니다. \ 범인은 / etc / nginx / sites-enabled에서 중복 된 nginx 구성이고, /etc/nginx/sites-enabled/default-ssl.backup이 default-ssl의 리디렉션을 방해했습니다. 바보 같은 오류.
Thomas V.

그래서 나는 2 개의 인증서를 발행해야했습니다 : www-domain 및 www가 아닌 ​​다른 사람을 위해
vladkras

이 말 포트 5007에 달성 할 수있는 방법 : example.com:5007을example.com:5007
CP3O

5

if 문을 던져 넣으십시오. curl.exe -I에서 결과를 확인했으며 https://www.example.com 이외의 모든 사례 는 301로 처리됩니다. SSL은 301 URL 리디렉션을 받기 전에 확인되기 때문에 까다 롭습니다. 따라서 인증서 오류가 발생합니다.

개인적으로 도메인에서 www를 제거하는 것을 좋아하지만 귀하의 질문에 대답하기 위해 아래 코드를 작성했습니다.

server {
listen 443 ssl;
listen [::]:443 ssl; # IPV6

server_name example.com www.example.com; # List all variations here

# If the domain is https://example.com, lets fix it!

if ($host = 'example.com') {
  return 301 https://www.example.com$request_uri;
}

# If the domain is https://www.example.com, it's OK! No changes necessary!

... # SSL .pem stuff
...
}

server {
listen 80;
listen [::]:80;

# If the domain is http://example.com or https://www.example.com, let's change it to https!

server_name example.com www.example.com;
return 310 https://www.example.com$request_uri;
}

3

내가하는 방법은 https의 www로 리디렉션되는 SSL 서버 블록 내부에 if 문을 사용하는 것입니다

ssl_certificate /srv/www/example.com/keys/ssl.crt;
ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
ssl_prefer_server_ciphers on;
client_max_body_size 20M;

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}

server {
    listen 443 default_server ssl;
    server_name www.example.com;

    # redirect https://example.com to https://www.example.com
    # mainly for SEO purposes etc
    #we will use a variable to do that
    set $redirect_var 0;

    if ($host = 'example.com') {
      set $redirect_var 1;
    }
    if ($host = 'www.example.com') {
      set $redirect_var 1;
    }

    if ($redirect_var = 1) {
      return 301 https://www.example.com$request_uri;
    } 

    try_files $uri/index.html $uri.html $uri @app;

    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

물론, nginx 설정 파일에서 if 문을 사용하고자 할 때마다; https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/를 읽어야합니다.


조건 if ($host = 'www.example.com')이 필요하지 않습니다.
Karl.S

2

2018 년 지금 나는 간단한 해결책을 찾고있는 경우에 대비 하여이 기회를 새롭게 제공하기로 결정했습니다.

상대적으로 새로운 이민자로서 이것을 받아들이는 것은 가능한 한 간단하게 만드는 것입니다. 기본적으로 http://example.comhttps://example.comhttps : // www .example.com 으로 리디렉션하려고합니다 . 그리고 당신은 http://example.com 을 리디렉션하는 데만 성공합니다 .

이것은 두 개의 서버 블록 만 필요로하는 매우 간단한 작업입니다 (단일 구성 파일에서 간단히 설명합니다)

# 1. Server block to redirect all non-www and/or non-https to https://www
server {
    # listen to the standard http port 80
    listen 80; 

    # Now, since you want to route https://example.com to http://www.example.com....
    # you need to get this block to listen on https port 443 as well
    # alternative to defining 'ssl on' is to put it with listen 443
    listen 443 ssl; 

    # define server_name
    server_name example.com *.example.com; 

    # DO NOT (!) forget your ssl certificate and key
    ssl_certificate PATH_TO_YOUR_CRT_FILE;
    ssl_certificate_key PATH_TO_YOUR_KEY_FILE; 

    # permanent redirect
    return 301 https://www.example.com$request_uri;  
    # hard coded example.com for legibility 
}
# end of server block 1. nearly there....

# 2. Server block for the www (primary) domain
# note that this is the block that will ultimately deliver content
server {
    # define your server name
    server_name www.example.com; 

    # this block only cares about https port 443
    listen 443 ssl;

    # DO NOT (!) forget your ssl certificate and key
    ssl_certificate PATH_TO_YOUR_CRT_FILE;
    ssl_certificate_key PATH_TO_YOUR_KEY_FILE; 

    # define your logging .. access , error , and the usual 

    # and of course define your config that actually points to your service
    # i.e. location / { include proxy_params; proxy_pass PATH_TO_SOME_SOCKET; }
}
# End of block 2.
# voilà! 

이제 모두 http://example.comhttps://example.com 로 리디렉션해야 https://www.example.com . 기본적으로이 설정은 www가 아닌 ​​및 / 또는 http가 아닌 모든 것을 https : // www로 리디렉션 합니다.


-1

모든 요청을 https://www.example

SSL 포트 (일반적으로 443) 및 기본 http 포트 80에서 리디렉션 및 기본 도메인에 대한 서버 블록을 만듭니다.

# non-www to ssl www redirect
server {
  listen 80; 
  listen 443 ssl;
  server_name example.com;
  return 301 https://www.example.com$request_uri;
  # ... ssl certs
}

# ssl setup for www (primary) domain
server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com;
  if ($scheme = http) {
    return 301 https://www.example.com$request_uri;
  }
  # ... the rest of your config + ssl certs
}

저장하고 따르십시오 sudo nginx -s reload

리디렉션됩니다

http://example      301 -> https://www.example
https://example     301 -> https://www.example
http://www.example  301 -> https://www.example
https://www.example 200

;if 절의 두 번째 서버 블록에 a가 없습니다 . 그것은해야한다return 301 https://www.example.com$request_uri;
루카스 Oppermann

1
그러나 그조차도 효과가 있습니까? 그것은 수신 할 수 있습니다 http443?
루카스 Oppermann

당신이 바로, 내가 80을 듣고 실종되는 것은에서 추가 필자.
lfender6445
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.