NGINX + RegEx 重定向:http://sub3.sub2.sub1.domain ---> https://sub1.domain

NGINX + RegEx 重定向:http://sub3.sub2.sub1.domain ---> https://sub1.domain

我如何使用正则表达式nginx一起,以便这些都将重定向到同一个端点?

  1. http:// sub1.example.com
  2. http:// sub2.sub1.example.com
  3. http:// sub3.sub2.sub1.example.com
  4. https:// sub1.example.com
  5. https:// sub2.sub1.example.com
  6. https://sub3.sub2.sub1.example.com

---- 全部解析至 ---> https:// sub1.example.com

我当前的配置(仅适用于情况 2、3 和 4):

# Default server configuration

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    
    #NOT WORKING: regex to limit subdomains:

    server_name ~^(.*)\.(?<subdomain>\w+).example\.com$;
    return 301 https://$subdomain.example.com$request_uri; 
}


server {    
    # SSL configuration
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    #
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    #
    root /var/www/html; 

    server_name *.example.com;
    
    location / { ..... localhost:3000
    

然后在另一个文件中:

server {
    # Redirect all http traffic to https
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;    

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

server {    
    # SSL configuration 
    listen 443 ssl;
    listen [::]:443 ssl;
    #
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    #
    
    root /var/www/html;

    server_name example.com www.example.com ;

    if ($http_x_forwarded_proto = "http") {
      return 301 https://$server_name$request_uri;
    }

    location / { .... localhost:8000

答案1

我可以通过使用 NGINX 的服务器匹配逻辑和正则表达式来解决情况 1-4。

Nginx 会按照这个顺序解析服务器名称(注意:Nginx 也针对该匹配顺序进行了优化,其中正则表达式最慢):

  1. 完全符合
  2. 领导 *
  3. 尾随 *
  4. 第一个正则表达式匹配

以下是服务器块的匹配和重定向顺序:

多级子域名 ---> 至单级子域名 --> 至 SSL

由于我的通配符 SSL 证书仅对 *.example.com 有效,因此仍然无法解决 5 和 6,而不会触发浏览器安全警告(firefox 和 safari 不会抛出这些错误)。根本没有办法解决这个问题。

  1. http:// sub1.example.com
  2. http:// sub2.sub1.example.com
  3. http:// sub3.sub2.sub1.example.com
  4. https:// sub1.example.com
  5. https:// sub2.sub1.example.com
  6. https://sub3.sub2.sub1.example.com

-------> https:// sub1.example.com

# Default server configuration
server {
    listen 80;
    listen [::]:80;
    listen 443;
    listen [::]:443;
    server_name ~^(.*)\.(?<subdomain>\w+).example\.com$;
    return          301 http://$subdomain.example.com$request_uri; 
}

server {
    listen 80;
    listen [::]:80;
    server_name ~^(?<subdomain>\w+).example\.com$;
    return          301 https://$subdomain.example.com$request_uri; 
}


server {    
    # SSL configuration
    #
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    #
    root /var/www/html; 
    
    location / { ..... localhost:3000

答案2

尝试更改 server_name 指令(在第一个文件中):

server_name ~^(.*?)\.?(?<subdomain>\w+).example\.com$;

正则表达式已从 略微更改(.*)\.(.*?)\.?

在括号中,我们现在只对捕获(最终)子域之前的文本进行惰性匹配。接下来,.捕获(最终)子域之前的字符现在是可选的。

答案3

对于 TLS 域,您需要拥有对所有域名有效的证书。

这意味着,fullchain.pem需要覆盖sub1.example.comsub2.sub1.example.comsub3.sub2.sub1.example.com

通配符证书在这里没有帮助,因为它仅覆盖一个级别(*.example.com覆盖sub1.example.comsub2.example.com)。

相关内容