使用Nginx通过SSL将非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

有人可以告诉我我要去哪里错吗?

这是我的默认和default-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 '17

分开考虑,非SSL配置是如此之小,以至于最好将其与仅SSL配置分开。
Thomas V.

Answers:


34

listen在file 中缺少指令default-ssl.conflisten 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;
}

旁注:您可以根据nginx文档中的建议将ssl on;指令替换listen 443 ssl;为。


4
您还需要在此块中设置ssl_certificatessl_certificate_key指令,并使用listen 443 ssl;它作为SSL vhost。
Tero Kilkanen 2014年

请张贴当前内容default-ssl.conf。可能是某些拼写错误或重新排序问题引起的。
masegaloeh 2014年

令人尴尬的是:\罪魁祸首是/ etc / nginx / sites-enabled,/ etc / nginx / sites-enabled / default-ssl中重复的nginx配置。backup干扰了default-ssl中的任何重定向。愚蠢的错误。
Thomas V.

所以我不得不签发2份证书:www域名和非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

我这样做的方法是在ssl服务器块内使用if语句重定向到www的https

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和/或非https重定向到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子句的第二个服务器块中缺少。应该是return 301 https://www.example.com$request_uri;
Lukas Oppermann

1
但是,那还能行吗?它可以侦听http443
卢卡斯·欧珀曼

你说得对,我很想念听80,香港专业教育学院在添加它。
lfender6445
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.