Почему Nginx предпочитает default_server вместо блока server с точным соответствием хоста

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

Проверьте эту конфигурацию nginx. Если отправить запрос, например –
curl -H “Host: test.com” http://127.0.0.1:8200

Почему nginx использует второй серверный блок вместо первого блока (с точным совпадением хоста и протокола) и вызывает ошибку 400, сообщая, что обычный HTTP-запрос был отправлен на порт HTTPS.

  server {
    listen 8200;
    server_name test.com;

    location / {
      return 200 'Block1';
    }
  }

  server {
    listen 8200 ssl default_server;
    ssl_certificate /etc/ssl/server.cer;
    ssl_certificate_key /etc/ssl/server.key;

    location / {
      return 200 'Block2';
    }
  }

.

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

Когда дело доходит до конфигурации серверов Nginx, важно понимать, как обрабатываются запросы и какие параметры влияют на выбор соответствующего серверного блока. Ваша проблема заключается в том, что Nginx, обрабатывая запрос с заголовком Host: test.com, использует второй серверный блок, что приводит к ошибке 400 с сообщением о том, что "обычный HTTP-запрос был отправлен на HTTPS-порт". Давайте детально разберем эту ситуацию.

1. Структура конфигурации

В вашей конфигурации есть два серверных блока, которые прослушивают один и тот же порт 8200. Однако, они различаются по настройкам:

  • Первый серверный блок:

    server {
      listen 8200;
      server_name test.com;
    
      location / {
          return 200 'Block1';
      }
    }

    Этот блок не использует SSL и отвечает на запросы, направленные на test.com.

  • Второй серверный блок:

    server {
      listen 8200 ssl default_server;
      ssl_certificate /etc/ssl/server.cer;
      ssl_certificate_key /etc/ssl/server.key;
    
      location / {
          return 200 'Block2';
      }
    }

    Этот блок использует SSL и объявлен как default_server, что определяет его как сервер по умолчанию для этого порта.

2. Причины выбора второго серверного блока

a. Параметр default_server

Ключевым аспектом является то, что второй блок объявлен default_server. Этот параметр в Nginx означает, что если не найдено точного соответствия для входящего запроса, будет использован этот серверный блок. Поскольку оба блока прослушивают один и тот же порт (8200), это создает выигрышную роль для второго блока при множестве условий.

b. SSL и HTTP запросы

Когда вы отправляете запрос с использованием curl -H "Host: test.com" http://127.0.0.1:8200, Nginx видит, что ваш запрос предназначен для порта 8200. Поскольку второй блок является default_server, он получает приоритет, даже если у него нет соответствия с Host заголовком. Следовательно, запрос обрабатывается как HTTP, в то время как второй блок ожидает HTTPS соединение. Это и приводит к ошибке:

400 Bad Request
plain HTTP request sent to HTTPS port

3. Как это исправить

Чтобы исправить это поведение и заставить Nginx правильно обрабатывать запросы к test.com, у вас есть несколько опций:

  1. Используйте разные порты для HTTP и HTTPS:

    • Например, перенаправьте HTTP на 80 порт, а HTTPS на 443 или используйте иные порты для разделения этих потоков.
  2. Удалите параметр default_server из второго блока:

    • Это заставит Nginx искать точное соответствие перед выбором сервера по умолчанию.
  3. Настройте редирект:

    • Вы можете добавить редирект на уровне первого блока, перенаправляя все HTTP запросы на нужные адреса.

Заключение

Понимание принципа работы серверных блоков Nginx, параметра default_server и аспектов, связанных с SSL-соединениями, является ключевым для правильной настройки веб-сервера. Правильная архитектура конфигурации поможет избежать ошибок и обеспечит стабильность и безопасность ваших приложений.

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

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