nginx: маршрутизация с подстановочными знаками SNI для поддомена, а также proxy+terminate другие

Вопрос или проблема

Моя ситуация:
У меня установлен nginx на ubuntu 24.04. Он имеет несколько конфигураций, в которых выступает как обратный прокси, завершающий соединения для TLS-доменов, локальных для этого сервера (например, wordpress). Для них настроены сертификаты с помощью Let’s Encrypt. Это работает хорошо. Примеры таких доменов: https://blog.domain/

Теперь я хочу добавить поддомен, например, https://*.A.domain/, и хочу, чтобы nginx посредством SNI перенаправлял все эти запросы на один upstream. Причина в том, что у меня на хосте работает kubernetes и я хочу, чтобы он контролировал этот поддомен, не требуя постоянной перенастройки "внешнего" nginx.

Я видел у других создание карт, например:

stream {
        map $ssl_preread_server_name $name {
                .A.domain $ssl_preread_server_name;
        }
        server {
                listen 0.0.0.0;
                proxy_pass 10.244.0.1:30443;
                ssl_preread on;
        }
}

в их блоке stream, но кажется, что я не могу понять, как сделать так, чтобы это не мешало, например, блогу на хосте, который имеет свой собственный блок server, как:

server {

   listen 443 ssl;
   http2 on;
   ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;
 ...

   server_name blog.domain;
   location {
 ...
     proxy_pass http://172.17.0.1:8181;
   }
}

Как я могу достичь этой цели совместного использования порта 443, чтобы домены, соответствующие условиям, завершались по SSL nginx, а несовпадающие (или совпадающие с поддоменом через SNI) пересылались дальше как TCP-прокси?

Ответ или решение

Настройка nginx для реализации SSL-приёма на свой адрес (SNI) с маршрутизацией wildcard для поддоменов, а также проксирование и завершение подключения для других доменов, является сложной, но важной задачей, особенно при наличии разнообразных приложений, работающих как на одном хосте, так и через внешние системы, такие как Kubernetes.

Теория

Nginx прежде всего используется для обработки HTTP/HTTPS-запросов. Однако конфигурация на уровне SSL/TLS часто требует нестандартных методов, особенно при работе с поддоменами через TLS SNI (Server Name Indication). SNI позволяет одному IP-адресу обслуживать несколько SSL-сертификатов для разных доменов, что критически для сценариев с множеством поддоменов.

Основные задачи:

  1. Обработка поддоменов (*.A.domain) c использованием SNI для маршрутизации на upstream Kubernetes.
  2. Обработка доменов без вмешательства в работу существующих проксирований, например, blog.domain.

Использование блока stream в Nginx позволяет маршрутизировать TCP/SSL-трафик на основе имени сервера (SNI) перед тем, как будет установлено шифрование, что важно, если нужно передать соединение как есть, не расшифровывая.

Пример

Вот пример конфигурации для реализации заданных задач:

Конфигурация для SNI маршрутизации:

  1. Stream Block для Поддоменов:
stream {
    map $ssl_preread_server_name $sni_host {
        .A.domain 10.244.0.1:30443; # IP и порт вашего Kubernetes ingress
    }

    server {
        listen 443;
        proxy_pass $sni_host;
        ssl_preread on;
    }
}
  1. HTTP Block для Обычных Доменов:
http {
    server {
        listen 443 ssl http2;
        server_name blog.domain;

        ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;

        location / {
            proxy_pass http://172.17.0.1:8181;
            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-Proto $scheme;
        }
    }
}

Применение

  1. Управление Поддоменами (.A.domain):

    • Блок stream позволяет принимать входящие соединения на уровне TCP без вмешательства в их шифрование, полезно для случаев, когда соединение должно быть передано незашифрованным.
    • map использует переменную $ssl_preread_server_name, чтобы направить входящие коннекшены на Kubernetes, благодаря IP и порту, которые вы указываете.
  2. Работа с Обычными Доменами (blog.domain):

    • Блок http обеспечивает обработку и маршрутизацию трафика, поступающего через обычные HTTPS-запросы, напрямую отнимая TLS-соединение для домена, указанного в server_name.
    • Сертификат и ключ предоставлены, чтобы обеспечить надёжное шифрование и авторизацию соединений.

Заключение

Интеграция nginx для работы c SNI и TCL-потоком требует чёткого понимания, как именно Nginx управляет соединениями на разных уровнях. В этом случае блок stream предоставляет гибкость для выполнения маршрутизации на основе имени сервера, что позволяет поддерживать современные требования к обработке поддоменов и обеспечит легкое управление с существующими конфигурациями.

Рекомендуется также регулярная проверка сертификатов и их обновление через Let’s Encrypt, чтобы обеспечить безопасность и доверие пользователей. В случае сложных архитектур, возможно потребуется установка и использование дополнительных инструментов мониторинга для отслеживания производительности и стабильности системы.

Оцените материал
Добавить комментарий

Капча загружается...