【问题标题】:Nginx forwarding to another server block when it shouldn'tNginx 不应该转发到另一个服务器块
【发布时间】:2015-04-17 17:29:21
【问题描述】:

我的 nginx 服务器上有 3 个不同的站点,每个站点都有自己的服务器块。为了安全起见,我将只使用 domain1.com、domain2.com 和 domain3.com 而不是真正的域。 Domain3 仍在等待转让给我的所有权,因此它根本无法运行。

问题是每当您访问 domain1.com 时,它都会将我转发到 domain2.com。据我所知,没有任何东西说 domain1.com 应该转发到 domain2.com。我清除了我的 DNS 缓存以及所有浏览器缓存和 cookie。

这里是 domain1.com 的 server_block 配置

#This is for redirecting everyone from www.domain.com to domain.com
server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

    server_name www.domain1.com;

    return 301 https://domain1.com$request_uri;
}

server {
    #listen 80 default_server;
    #listen [::]:80 default_server ipv6only=on;

    listen 443;

    server_name domain1.com;

    #keepalive_timeout 70;

    root /var/www/domain1.com/html;
    index index.php index.html index.htm;

    ssl on;
        ssl_certificate /etc/nginx/ssl/domain1.com/ssl.crt;
        ssl_certificate_key /etc/nginx/ssl/domain1.com/ssl.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        # Uncomment to enable naxsi on this location
        # include /etc/nginx/naxsi.rules
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/domain1.com/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
    #location /RequestDenied {
    #   proxy_pass http://127.0.0.1:8080;    
    #}

    #error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    #error_page 500 502 503 504 /50x.html;
    #location = /50x.html {
    #   root /usr/share/nginx/html;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
    #   # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    #
    #   # With php5-cgi alone:
    #   fastcgi_pass 127.0.0.1:9000;
    #   # With php5-fpm:
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #   deny all;
    #}
}

domain2.com配置如下:

#This is for redirecting everyone from www.domain.com to domain.com
server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80  ipv6only=on; ## listen for ipv6

    server_name www.domain2.com;

    return 301 https://domain2.com$request_uri;
}
server {
    #listen 80;
    #listen [::]:80  ipv6only=on;

    listen 443;
    server_name domain2.com;

    ssl on;
    ssl_certificate /etc/nginx/ssl/domain2.com/ssl.crt;
    ssl_certificate_key /etc/nginx/ssl/domain2.com/ssl.key;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers HIGH:!aNULL:!MD5;

    ssl_prefer_server_ciphers on;

    root /var/www/domain2.com/html;
    index index.php index.html index.htm;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        # Uncomment to enable naxsi on this location
        # include /etc/nginx/naxsi.rules
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/domain2.com/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
    #location /RequestDenied {
    #   proxy_pass http://127.0.0.1:8080;    
    #}

    #error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    #error_page 500 502 503 504 /50x.html;
    #location = /50x.html {
    #   root /usr/share/nginx/html;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
    #   # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    #
    #   # With php5-cgi alone:
    #   fastcgi_pass 127.0.0.1:9000;
    #   # With php5-fpm:
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #   deny all;
    #}
}

根据nginx -t 没有配置问题。任何帮助将不胜感激!

access.log

【问题讨论】:

  • 当您在尝试访问其他域时重定向到错误域时,请发布access.log 条目。它发生在 http 和 https 上吗?
  • @DmitryVerkhoturov 这里是access.log pastebin的链接

标签: nginx configuration server


【解决方案1】:

警告:

您可能知道的一个问题是使用 TLS 为多个网站提供服务。 TLS 握手实际上是在发送 HTTP 请求之前完成的,而 HTTP 请求是包含主机名的部分。这意味着 nginx 必须选择一个用于握手的 TLS 证书,如果它不知道要选择哪个证书,它就不会总是使用正确的证书。 This is documented here。这通常通过using different IPs for each websiteSNI (more on SNI in nginx here) 解决。我一直在为 Nginx 上的 SNI 苦苦挣扎,但也许你可以让它工作。如果 SNI 已经为您工作,则忽略此答案的这一部分。


问题:

问题似乎在于您只在端口 80 (HTTP) 上侦听 www.* 主机名。如果客户端尝试连接到domain1.com:80 (HTTP)(请注意缺少www.),则您没有服务器在端口80 (HTTP) 上侦听domain1.comnginx will use the first server in its configuration to handle unknown/unmatched hostnames.

在您的终端中尝试以下操作:

curl -v http://www.domain1.com
curl -v https://domain1.com
curl -v http://domain1.com
curl -v https://www.domain1.com

这将显示 HTTP 请求和响应标头。您将看到前两个 http://www.domain1.com(端口 80)和 https://domain1.com(端口 443)按预期工作。但是,最后两个 http://domain1.com(端口 80)和 https://www.domain1.com(端口 443)不能按预期工作,因为它们不匹配任何服务器块(端口/主机名错误)。


要更详细地解决问题,以下命令应输出以下内容:


$ curl -v http://www.domain1.com
[...]
< HTTP/1.1 301 Moved Permanently
[...]
< Location: https://domain1.com/
[...]

这很好。您有一台服务器在端口 80 (HTTP) 上侦听 www.domain1.com。这与您的重定向服务器配置相匹配。如您所见,服务器的 HTTP 响应标头返回 HTTP 301 并指向新位置 https://domain1.com/。这是正确的,并且符合您要求重定向服务器执行的操作。


$ curl -v https://domain1.com
[...]
< HTTP/1.1 200 OK
[...]

这很好。您有一台服务器在端口 443 (HTTPS) 上侦听 domain1.com。这与domain1.com 的主服务器配置相匹配。可以看到,服务器的 HTTP 响应头返回HTTP 200,服务器返回请求的 HTML 页面。这是正确的,并且符合您要求主服务器配置为 domain1.com 执行的操作。


$ curl -v http://domain1.com
[...]
< HTTP/1.1 301 Moved Permanently
[...]
< Location: https://domain2.com/
[...]

这很糟糕。您没有在端口 80 (HTTP) 上侦听 domain1.com 的服务器。这与您的任何服务器配置都不匹配。由于此请求与您的任何服务器都不匹配,因此 nginx 不会执行您想要的操作。 nginx 只是默认使用它看到的第一个服务器配置,不幸的是这不是你想要的。它似乎使用了domain2.com 的重定向服务器,因为它返回一个301 重定向到domain2.com

这可以通过让domain1.com 的重定向服务器同时侦听到domain1.com 的端口80 (HTTP) 连接来解决(而不仅仅是www.domain1.com,就像它目前所做的那样)。如果不这样做,nginx 不知道该请求使用哪个服务器,并最终返回错误的东西。


$ curl -v https://www.domain1.com

这很糟糕。您没有在端口 443 (HTTPS) 上侦听 www.domain1.com 的服务器(您目前只有一个在端口 80 (HTTP) 上)。这与您的任何服务器配置都不匹配。由于此请求与您的任何服务器都不匹配,因此 nginx 不会执行您想要的操作。 nginx 只是默认使用它看到的第一个服务器配置,不幸的是这不是你想要的。

这可以通过让domain1.com 的重定向服务器同时侦听到www.domain1.com 的端口443 (HTTPS) 连接来解决(而不仅仅是端口80 (HTTP) www.domain1.com 连接,就像目前所做的那样)。如果不这样做,nginx 不知道该请求使用哪个服务器,并最终返回错误的东西。

解决方案:

您需要将您的domain1.com 配置更改为:

# For forwarding HTTP (port 80) connections to your website:
server {
    listen 80;
    server_name domain1.com www.domain1.com;
    return 301 https://domain1.com$request_uri;
}

# For forwarding HTTPS (port 443) connections to www.domain1.com:
server {
    listen 443 ssl;
    ... add the other SSL configuration options ...
    server_name www.domain1.com;
    return 301 https://domain1.com$request_uri;
}

# Your main server configuration:
server {
    ... keep it as you currently have it for your domain1.com server ...
}

你的domain2.com 配置如下:

# For forwarding HTTP (port 80) connections to your website:
server {
    listen 80;
    server_name domain2.com www.domain2.com;
    return 301 https://domain2.com$request_uri;
}

# For forwarding HTTPS (port 443) connections to www.domain2.com:
server {
    listen 443 ssl;
    ... add the other SSL configuration options ...
    server_name www.domain2.com;
    return 301 https://domain2.com$request_uri;
}

# Your main server configuration:
server {
    ... keep it as you currently have it for your domain2.com server ...
}

【讨论】:

    【解决方案2】:

    我真的找到了……

    server {
        server_name domain2.com  www.domain2.com;
        rewrite ^(.*) https://domain2.com$1 permanent;
    }
    

    .

    server {
        server_name domain1.com www.domain1.com;
        rewrite ^(.*) https://domain1.com$1 permanent;
    }
    

    基本上需要发生的是,对于传入的 www 或无 www 请求,它需要重写它而不是转发。在此之后,我只需指定 listen 443 ssl; 和标准域名即可!

    【讨论】:

    • 其实你不需要rewrite它。您应该使用return 301 而不是rewrite(因为rewrite ... permanent 只是一种较慢的return 301 方式)。这里的关键区别实际上是您的server_name,而不是rewrite 规则。请注意,您有一个server_name 同时监听domain1.com www.domain1.com这就是的关键。您的原件只收听www.domain1.com。如果您将原始服务器配置更改为使用 both domain1.com www.domain1.com,它将起作用。
    猜你喜欢
    • 2016-01-20
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2021-07-07
    相关资源
    最近更新 更多