Chuyển hướng không www sang www qua SSL với Nginx


25

Tôi gặp lỗi khi cố gắng chuyển hướng https://example.com sang https://www.example.com .

Khi tôi truy cập https://example.com , nó không chuyển hướng và trả về trang / 200 trạng thái.

Tôi không muốn điều này, tôi muốn nó chuyển hướng đến https://www.example.com .

Khi tôi truy cập http://example.com , nó sẽ chuyển hướng đến https://www.example.com

Ai đó có thể cho tôi biết tôi đang đi sai ở đâu?

Đây là tập tin cấu hình mặc định và ssl mặc định của tôi:

mặc định

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

mặc định-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
Điểm tạo 2 conf file là gì?
Sandip Subedi

Tách biệt các mối quan tâm, cấu hình không SSL nhỏ đến mức có vẻ tốt nhất để tách nó khỏi cấu hình chỉ SSL.
Thomas V.

Câu trả lời:


34

Bạn đang thiếu listenchỉ thị trong tập tin default-ssl.conf. Thêm listen 443;vào chỉ thị này

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

Theo mặc định, nếu bạn bỏ qua lệnh này, nginx cho rằng bạn muốn nghe trên cổng 80. Dưới đây là tài liệu về hành vi mặc định này.


Chỉnh sửa: Cảm ơn bình luận từ @TeroKilkanen.

Đây là cấu hình hoàn chỉnh cho ssl.conf mặc định của bạn

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

Sidenote : Bạn có thể thay thế ssl on;chỉ thị bằng listen 443 ssl;khuyến nghị từ tài liệu nginx .


4
Bạn cũng cần thiết lập ssl_certificatessl_certificate_keychỉ thị trong khối này và sử dụng listen 443 ssl;để nó là SSL vhost.
Tero Kilkanen

Xin vui lòng gửi nội dung hiện tại default-ssl.conf. Có thể một số vấn đề chính tả hoặc sắp xếp lại gây ra điều đó.
masegaloeh

Điều này thật đáng xấu hổ: \ Thủ phạm là một cấu hình nginx trùng lặp trong / etc / nginx / được kích hoạt trang web, /etc/nginx/sites-enables/default-ssl.backup đã can thiệp vào bất kỳ chuyển hướng nào trong ssl mặc định. Lỗi ngớ ngẩn.
Thomas V.

vì vậy tôi đã phải phát hành 2 certs: cho www-domain và không phải www
vladkras

Làm thế nào điều này có thể đạt được trên cổng 5007: example.com
giáp007

5

Chỉ cần đưa ra một tuyên bố if và bạn nên đi trên con đường của bạn. Tôi đã kiểm tra kết quả trong curl.exe -I và tất cả các trường hợp ngoài https://www.example.com được coi là 301. SSL rất khó bởi vì nó được kiểm tra trước khi bạn nhận được chuyển hướng URL 301. Do đó, bạn nhận được lỗi chứng chỉ.

Cá nhân, tôi thích xóa www khỏi tên miền nhưng tôi đã viết mã dưới đây để trả lời câu hỏi của bạn.

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

Cách tôi làm là sử dụng câu lệnh if bên trong khối máy chủ ssl chuyển hướng đến https của www

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

Tất nhiên, bất cứ khi nào bạn muốn sử dụng câu lệnh if trong tệp cấu hình nginx; bạn nên đọc: https://www.nginx.com/resource/wiki/start/topics/depth/ifisevil/


điều kiện if ($host = 'www.example.com')không cần thiết
Karl.S

2

Bây giờ là năm 2018 và tôi đã tìm ra cách để đổi mới trong trường hợp ai đó đang tìm kiếm một giải pháp đơn giản.

Tôi coi đây là một người mới tương đối là làm cho mọi thứ đơn giản nhất có thể. Về cơ bản, bạn muốn chuyển hướng cả http://example.comhttps://example.com sang https : // www .example.com. Và bạn chỉ thành công trong việc chuyển hướng http://example.com

Đây là một hoạt động khá đơn giản chỉ cần hai khối máy chủ (tôi sẽ trình bày ngắn gọn về điều này trong một tệp cấu hình duy nhất)

# 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à! 

Bây giờ cả http://example.comhttps://example.com nên chuyển hướng đến https://www.example.com . Về cơ bản, thiết lập này chuyển hướng mọi thứ không phải www và / hoặc không https sang https: // www .


-1

Để chuyển hướng tất cả các yêu cầu đến https://www.example

tạo khối máy chủ cho chuyển hướng và tên miền chính trên cổng SSL của bạn (thường là 443) cũng như cổng http mặc định 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
}

lưu và làm theo sudo nginx -s reload

Điều này sẽ chuyển hướng

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

Bạn đang thiếu một ;khối máy chủ thứ hai trong mệnh đề if. Nó nên làreturn 301 https://www.example.com$request_uri;
Lukas Oppermann

1
Tuy nhiên, điều đó thậm chí sẽ làm việc? Nó có thể nghe cho httptrên 443?
Lukas Oppermann

bạn nói đúng, tôi đang thiếu nghe 80, tôi đã thêm nó vào.
lfender6445
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.