为所有服务器名称解析服务器 IP 提供 Nginx SSL 证书

为所有服务器名称解析服务器 IP 提供 Nginx SSL 证书

假设我在 DNS 中配置了 2 个子域(因此使用我的服务器的 IP 地址对两个子域进行 ping 操作并进行回复),并且对于这些子域,我有 2 个不同的 TLS 证书。

我已经这样配置了 nginx:

# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}

# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
  default upgrade;
  ''      '';
}

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

access_log /var/log/nginx.log;
error_log /var/log/nginx_errors.log;

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

server {
  listen 80 default_server;
  server_name _; # This is just an invalid value which will never trigger on a real hostname.
  return 503;
  server_tokens off; # Hide the nginx version
}


upstream sub1.domain.tld {
  server 172.17.0.27:5000;
}

server {
  server_name sub1.domain.tld;
  server_tokens off; # Hide the nginx version

  listen 443 ssl;
  ssl_certificate /etc/nginx/ssl/sub1.domain.tld.crt;
  ssl_certificate_key /etc/nginx/ssl/sub1.domain.tld.key;

  location / {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/htpasswd/sub1.htpasswd;
    proxy_pass http://sub1.domain.tld;
  }
}

此时,如果我转到,https://sub1.domain.tld一切正常。现在,如果我尝试访问https://sub2.domain.tld尚未配置的,因此不应回复,它会接受连接并向我显示证书问题,因为它与服务器名称不匹配,因此似乎使用此配置,Nginx 会将所有请求的证书发送到 443 端口。

我应该如何更改我的配置以便访问https://sub2.domain.tld失败(例如出现 503 错误)直到我通过添加新server指令对其进行配置?

答案1

您可以像这样添加另一个服务器块:

server {
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate /etc/nginx/ssl/default.crt;
    ssl_certificate_key /etc/nginx/ssl/default.key;

    return 503;
}

对于默认证书,您可以制作自签名证书。这将在客户端上触发无效证书错误,如 Steffen 所述。如果用户接受证书,则他将收到 503 状态代码。

答案2

如果您在特定 IP 上侦听 TCP 端口 443,即使您仅为解析到此 IP 地址的某些域配置了 SSL,它也会在此端口上接受新的 TCP 连接。一旦建立 TCP 连接,它将进行 SSL 握手并选择最合适的证书,如果使用 SNI(即客户端在 SSL 握手中发送预期的主机名),则为匹配的证书;如果无法确定请求的主机名或未为此名称配置证书,则为另一个证书。

这意味着,您要么需要拥有可在此 IP 地址上访问的所有域的证书,要么接受访问没有适当证书的域将导致证书无效等错误。这并非 nginx 所特有的,而是因为 SSL 是 TCP 之上的一层,有关请求主机的信息仅在已建立的 TCP 连接内传输。

相关内容