nginx 重定向所有子域(当它不应该时)

nginx redirecting all subdomains (when it shouldn't)

我有一个 nginx 服务器 运行。我希望它将 http://www.example.com 重定向到 https://www.example.com,但不要触及 http://foo.example.com.

等任何其他子域

出于某种原因,无论我在子域中添加什么,它仍然会被重新路由。我的网页显示在 www.example.com(它应该),但也在 foo.example.com 和 example.com(它不应该)

这是我的 example.com 配置文件:

server {
  listen 80;
  server_name www.example.com;

  # For debug
  add_header X-debug-message "listen:80, server_name:www.example.com, redirect:https://$host$request_uri" always;

  # Riderect
  return 301 https://$host$request_uri;
}

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

  # For debug
  add_header X-debug-message "listen:443, server_name:www.example.com, redirected:https://$host$request_uri" always;

  # SSL
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  root /var/www/example.com;

  # Redirect
  location / {
    proxy_pass http://192.168.1.224:80;
  }
}

前往 www.example.com 按预期显示我的网页。但是去 foo.example.com 也给了我我的网页 - 它不应该。 example.com 也给我网页。

在我的浏览器中打开 www.example.com,我看到以下 http header(如预期的那样):

X-debug-message: DEBUG: listen:443, server_name:www.example.com, redirected:https://www.example.com/

在我的浏览器中打开 foo.example.com,我看到以下 http header(与预期不同):

X-debug-message: DEBUG: listen:443, server_name:www.example.com, redirected:https://foo.example.com/

如何让我的 nginx 只重定向 www.example.com

  1. 确保 foo.yourdomain.com 的 dns 记录实际上是用 DNS 提供商

  2. 为子域创建第二个服务器块 'foo.example.com' 否则所有请求到端口 80 将被重定向到可用的服务器块,在您的情况下 www.example.com - 服务器块应如下所示:

         server {
            server_name foo.example.com;
            location / {
                 root path/to/foo/index.html;
                 index index.html index.htm;
                 proxy_http_version 1.1;
                 proxy_set_header Upgrade $http_upgrade;
                 proxy_set_header Connection 'upgrade';
                 proxy_set_header Host $host;
                 proxy_cache_bypass $http_upgrade;
                 try_files $uri $uri/ /index.html;
            }
    
          listen 443 ssl; # managed by Certbot
          ssl_certificate 
          /etc/letsencrypt/live/example.com/fullchain.pem; # n 
            managed by Certbot
          ssl_certificate_key 
          /etc/letsencrypt/live/nextoma.com/privkey.pem; # managed by 
          Certbot
          include /etc/letsencrypt/options-ssl-nginx.conf; # managed by 
          Certbot
          ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by 
          Certbot
        }
    
  3. 使用以下命令将 ssl 证书添加到 foo.example.com:

    certbot --nginx -d foo.example.com
    
  4. 重新启动 nginx 并再次检查 foo.example.com

谢谢大家的评论!

对于其他读者,以及未来的参考,这是我现在开明的理解。

nginx 将其 enabled-sites conf 中的第一个条目视为默认路由。因此,第一个条目

server {
    listen      80;
    server_name example.net www.example.net;
    ...
}

实际上被视为

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

所以,我的错误是将 *.example.com -> MyIP 添加到我的 DNS,并假设 nginx 只会 404 所有我没有明确定义的路由。事实上,它会寻找匹配 foo.example.com 的路由,如果不匹配,则将其路由到默认路由。

所以,我现在更改了我的 DNS 以明确处理我想要路由的所有子域,并且我在 nginx 中明确列出了所有子域。

现在 - 我如何实现我最初的计划 - 只路由 *.example.com 到我的 IP,并让 nginx 404 除了我明确定义的请求之外的所有请求 - 我仍然不明白。

在 DNS 中显式路由所有子域不太灵活,因为如果我想在内部测试新服务,我需要更新 DNS 并等待更改传播。但是,我想现在可以了。

您需要让第一个条目在 443 上侦听 HTTPS 和服务器名称 _ 和 return 404。

server {
        listen 443 ssl;
        server_name _;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ssl_certificate /etc/nginx/certs/nginx-selfsigned.crt;
        ssl_certificate_key /etc/nginx/certs/nginx-selfsigned.key;

        location / {
                return 404;
        }
}

通过在文件中将典型的 HTTP 重定向到 HTTPS(我将其作为最后一个条目):

server {
        listen 80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
}

然后所有 HTTP 请求都转换为对应的 HTTPS。然后,如果您请求一个尚未在 NGINX 配置文件中配置的子域,它将默认为 returns 404 的第一个条目。所有其他已配置的子域和根域,如果您将其作为条目,将正确解析。

您还可以保留通配符 DNS,这比必须将每个子域添加为条目更实用,正如您在回答中指出的那样。