Назад | Перейти на главную страницу

Как перезаписать (большинство) поддоменов в nginx на виртуальный путь для API / прокси

У меня есть настройка клиента, в которой неизвестное количество компаний может создавать учетные записи, подобные company.app.com.

Серверный сервер их как : 5000/company/...., так как же выполнить перезапись (а не перенаправление!) в nginx? Вот что у меня есть:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl        on;
    ssl_certificate         /etc/ssl/certs/cert.pem;
    ssl_certificate_key     /etc/ssl/private/key.pem;

    server_name ????.app.com; <-- How?
    
    charset    utf-8;
    
    location / {
        proxy_pass         http://0.0.0.0:5000;
        proxy_http_version 1.1;
        proxy_set_header   Connection "";
        proxy_connect_timeout       300;
        proxy_send_timeout          300;
        proxy_read_timeout          300;
        send_timeout                300;            
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

Теперь проблема в том, что мне нужно исключить небольшой список поддоменов (www, dash, mail), как это сделать?

Можно запечатлеть часть Host заголовок / поле TLS SNI в переменную в server_name как это:

server_name ~^(?<company>.+)\.app\.com;

Позже переменную можно будет использовать в proxy_pass место назначения:

proxy_pass http://192.168.100.100:5000/$company/;

Полезно знать правила сопоставления, которые объясняются в документация по именам серверов nginx.

Мой комментарий был бы очень скучным по поводу комментария, извините.

В отношении документации NGINX:

Подстановочный знак может содержать звездочку только в начале или конце имени и только на границе с точкой. Имена «www..example.org »и« w.example.org »недействительны. Однако эти имена можно указать с помощью регулярных выражений, например, «~ ^ www .. +. Example.org $» и «~ ^ w..example.org $ ». Звездочка может соответствовать нескольким частям имени. Имя ".example.org »соответствует не только www.example.org но www.sub.example.org также.

При поиске виртуального сервера по имени, если имя соответствует более чем одному из указанных вариантов, например совпадают имя подстановочного знака и регулярное выражение, будет выбран первый подходящий вариант в следующем порядке приоритета:

  • точное имя
  • самый длинный подстановочный знак, начинающийся со звездочки, например «* .Example.org»
  • самое длинное подстановочное имя, оканчивающееся звездочкой, например «Почта. *»
  • первое подходящее регулярное выражение (в порядке появления в файле конфигурации)

Специальное имя с подстановочным знаком в форме «.example.org» может использоваться для соответствия как точному имени «example.org», так и имени подстановочного знака «* .example.org».

Поскольку NGINX поддерживает подстановочные знаки, это может быть примерно так:

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl        on;
ssl_certificate         /etc/ssl/certs/cert.pem;
ssl_certificate_key     /etc/ssl/private/key.pem;

server_name *.app.com;

charset    utf-8;

location / {
    proxy_pass         http://0.0.0.0:5000;
    proxy_http_version 1.1;
    proxy_set_header   Connection "";
    proxy_connect_timeout       300;
    proxy_send_timeout          300;
    proxy_read_timeout          300;
    send_timeout                300;            
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}
}

или даже:

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl        on;
ssl_certificate         /etc/ssl/certs/cert.pem;
ssl_certificate_key     /etc/ssl/private/key.pem;

server_name *corp.app.com;

charset    utf-8;

location / {
    proxy_pass         http://0.0.0.0:5000;
    proxy_http_version 1.1;
    proxy_set_header   Connection "";
    proxy_connect_timeout       300;
    proxy_send_timeout          300;
    proxy_read_timeout          300;
    send_timeout                300;            
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}
}

Оба должны работать.