0

How can I use regex and nginx together so that these will all redirect to the same endpoint?

  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

---- all resolve to---> https:// sub1.example.com

My current configuration (only works for cases 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
    

then in another file:

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

3 Answers3

0

Try this change of server_name directive (in the first file):

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

The regex has been altered slightly from (.*)\. to (.*?)\.?.

In the parentheses we now only do lazy matching of text before the captured (final) subdomain. Next, the . character before the captured (final) subdomain is now optional.

Jea
  • 101
  • 4
0

I am able to resolve cases 1-4, by using NGINX's server matching logic with regex.

Nginx will resolve server names in this order (Note: Nginx is also optimized for that matching order, with regex the slowest):

  1. exact match
  2. leading *
  3. trailing *
  4. first regex match

Here's the matching & redirect order of the server blocks below:

multilevel subdomains ---> to single-level subdomain --> to ssl

Still cannot resolve 5 & 6 without hitting the browser security warning (firefox and safari do not throw these errors), due to the fact that my wildcard ssl cert is only valid for *.example.com. There is simply no way around this.

  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
  • Did you try my answer? In case of regex it should match all six cases (see: https://regex101.com/r/GBRx3I/1). – Jea Jan 26 '21 at 07:29
0

For TLS domains, you need to have a certificate that is valid for all the domain names.

This means, fullchain.pem needs to cover sub1.example.com. sub2.sub1.example.com and sub3.sub2.sub1.example.com.

A wildcard certificate doesn't help here, because it covers only one level (*.example.com covers sub1.example.com and sub2.example.com.

Tero Kilkanen
  • 36,796
  • 3
  • 41
  • 63