首页 > 解决方案 > 使用 SSL 的 Nginx 子域重定向不起作用

问题描述

我有一个域example.com。我想在其子域上运行多个应用程序并在它们上启用 https。

我使用 certbot 为*.example.comexample.com域创建了证书。

有三个应用程序处理来自不同子域的请求。

  1. 应用程序app1处理来自子域abc.example.com 的请求。
  2. 应用程序app2处理来自[some_name].example.com形式的子域的请求。
  3. 应用程序仅处理来自example.comapp3的请求。

我面临以下问题。

  1. 当我尝试从浏览器访问域abc.example.com时,它会重定向到www.abc.example.com,然后出现无效证书错误。
  2. 使用服务器名称的正则表达式会导致所有请求被重定向到app1
  3. 当我尝试从浏览器访问域example.com时,它会重定向到www.www.abc.example.com,这是一个无效域。

我不确定似乎是什么问题。它是服务器名称的正则表达式吗?另外,还有其他更好的方法可以用于这种情况吗?任何帮助表示赞赏。

注意: 应用程序作为 docker 容器托管在同一个 docker 网络中。


以下是 nginx 配置文件。

server {
  listen 80;
  listen [::]:80;
  charset utf-8;
  access_log off;
  server_name example.com;

  location / {
    rewrite ^ https://$host$request_uri? permanent;
  }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com;

  server_tokens off;
  ssl on;

  ssl_certificate /etc/letsencrypt/live/example.com-0001/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com-0001/privkey.pem;

  ssl_buffer_size 8k;

  ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_prefer_server_ciphers on;

  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  ssl_ecdh_curve secp384r1;
  ssl_session_tickets off;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8;

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


server {
  server_name www.example.com;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_tokens off;

  ssl on;

  ssl_buffer_size 8k;
  ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  ssl_ecdh_curve secp384r1;
  ssl_session_tickets off;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8 8.8.4.4;

  ssl_certificate /etc/letsencrypt/live/example.com-0001/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com-0001/privkey.pem;

  location / {
    proxy_pass http://app3:80;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

server {
  listen 80;
  listen [::]:80;
  charset utf-8;
  access_log off;
  server_name abc.example.com;

  location / {
     rewrite ^ https://$host$request_uri? permanent;
  }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name abc.example.com;

  server_tokens off;
  ssl on;

  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  ssl_buffer_size 8k;

  ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_prefer_server_ciphers on;

  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  ssl_ecdh_curve secp384r1;
  ssl_session_tickets off;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8;

  location / {
    proxy_pass http://app1:80;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

server {
  listen 80;
  listen [::]:80;
  charset utf-8;
  access_log off;
  server_name ~^(?!abc|www).+\.example\.com$ ~^www\.(?!abc|www).+\.example\.com$;

  location / {
    rewrite ^ https://$host$request_uri? permanent;
  }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name ~^(?!abc|www).+\.example\.com$ ~^www\.(?!abc|www).+\.example\.com$;

  server_tokens off;
  ssl on;

  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  ssl_buffer_size 8k;

  ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_prefer_server_ciphers on;

  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  ssl_ecdh_curve secp384r1;
  ssl_session_tickets off;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8;

  location / {
    proxy_pass http://app2:80;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

标签: dockersslnginxdocker-compose

解决方案


感谢@Steffen Ullrich提供的线索,我终于得到了这个工作。

我删除了对www.example.comwww.*.example.com的所有重定向。

具体来说,以下服务器块。

server {
  server_name www.example.com;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_tokens off;

  ssl on;

  ssl_buffer_size 8k;
  ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

  ssl_ecdh_curve secp384r1;
  ssl_session_tickets off;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8 8.8.4.4;

  ssl_certificate /etc/letsencrypt/live/example.com-0001/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com-0001/privkey.pem;

  location / {
    proxy_pass http://app3:80;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

此外,我将通配符服务器名称的正则表达式从~^(?!abc|www).+\.example\.com$ ~^www\.(?!abc|www).+\.example\.com$更改为~^(?!api|www)\w+\.example\.com$


推荐阅读