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


25

https://example.com 을 https://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.com 및 https://example.com 을 https : // 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.com 및 https://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
그러나 그조차도 효과가 있습니까? 그것은 수신 할 수 있습니다 http에 443?
— 루카스 Oppermann

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