Вопрос или проблема
Я использую стандартный пакет nginx на Debian Bookworm. Обычно я использую только HTTPS-соединения для этого сервиса, и все работает нормально. По умолчанию для HTTP-порта 80 установлен редирект на протокол HTTPS.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_tokens off;
return 301 https://$host$request_uri;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log error;
}
server {
listen 80;
listen [::]:80;
server_name xyz;
server_tokens off;
location / {
root /var/www/html/;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log error;
}
// vhosts с конфигурациями listen 443 здесь опущены, они работают
У меня есть IoT-клиент, который не поддерживает HTTPS, и я настроил его на использование HTTP и добавил VHost для этого домена, чтобы он не перенаправлял запрос на HTTPS. Но этот запрос никогда не обрабатывается. Используя curl
, я получаю такой ответ:
# curl -v http://localhost/
* Попытка 127.0.0.1:80...
* Подключено к localhost (127.0.0.1) порт 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
* Получен HTTP/0.9, когда это не разрешено
* Закрытие соединения 0
curl: (1) Получен HTTP/0.9, когда это не разрешено
В журналах journald, а также в журналах доступа или ошибок nginx отсутствуют сообщения.
Затем я попробовал “хардкорный” telnet
на порт 80 и получил более странный результат:
# telnet localhost 80
Попытка ::1...
Подключено к localhost.
Эскейп-символ '^>'.
GET / HTTP/1.1
Соединение закрыто удаленным хостом.
Таким образом, сразу после первой строки Nginx закрывает соединение (ответ HTTP/0.9 приходит от самого curl).
Поскольку я не мог установить заголовок Host:
в запросе, этот запрос никогда не проверяет никакую конфигурацию виртуального хоста.
У меня нет идеи, что не так. Сервер должен хотя бы дождаться заголовка Host перед закрытием соединения. Файл /etc/nginx/nginx.conf
не изменен.
Ответ или решение
Анализ проблемы: закрытие соединения Nginx
При использовании сервера Nginx на Debian Bookworm с необработанными HTTP-запросами, мы сталкиваемся с проблемой закрытия соединения. Рассмотрим более детально, что происходит и как это можно исправить.
Описание проблемы
Указанный конфигурационный файл Nginx содержит два блока server
, которые обрабатывают запросы на HTTP (порт 80). Первый блок перенаправляет все запросы на HTTPS с помощью return 301
, что приводит к тому, что все запросы попадают в переадресацию. Второй блок определяет виртуальный хост на тот же порт 80, но не настроен для перенаправления.
Когда вы пытаетесь ввести в действие ваш IoT-клиент, который не поддерживает HTTPS, вы получаете сообщение об ошибке:
* Received HTTP/0.9 when not allowed
* Closing connection 0
Это говорит о том, что запрос не был корректно обработан сервером.
Возможные причины
-
Отсутствие заголовка "Host": Во время работы через
telnet
, когда вы отправляете запрос без заголовка "Host", сервер может не распознать его как допустимый HTTP-запрос. Nginx ожидает, что все HTTP-запросы будут иметь заголовок "Host", который указывает на имя сервера. Без этого заголовка Nginx может завершить соединение, так как не может определить, какому виртуальному хосту следует направить запрос. -
Настройки конфигурации: Ваш конфигурационный файл выглядит корректным, но наличие блока по умолчанию для порта 80 может вызывать путаницу. Если ваш IoT-клиент не включает заголовок "Host", запрос будет проигнорирован или, как в этом случае, соединение будет закрыто.
Рекомендации по исправлению
-
Отладка через telnet: Чтобы правильно протестировать с помощью
telnet
, вы можете вручную добавить заголовок "Host" в запрос, например:GET / HTTP/1.1 Host: localhost
Это должно помочь проверить работу конфигурации виртуальных хостов, и вы сможете увидеть ожидаемый результат.
-
Упрощение конфигурации: Если ваш IoT-клиент не поддерживает HTTPS, рассмотрите возможность упрощения конфигурации Nginx. Один из вариантов — убрать блоки, которые создают конфликт. Например, перенаправление может быть удалено в том случае, если клиент никогда не должен быть перенаправлен на HTTPS.
-
Дополнительная конфигурация виртуального хоста: Убедитесь, что у вас есть отдельная конфигурация для виртуального хоста, который обрабатывает запросы от IoT-клиента. Она должна иметь параметр
server_name
, который соответствует запросам от клиента, а также обработку для необходимых путей. -
Логи: Проверьте настройки логирования. Убедитесь, что уровень журналирования достаточно подробный, чтобы фиксировать запросы и ошибки. Использование уровня "debug" может оказаться полезным.
Заключение
Проблема, связанная с закрытием соединения в Nginx, часто возникает из-за отсутствия необходимого заголовка "Host" или конфигурационных несоответствий. Следуя предложенным рекомендациям, вы сможете устранить проблему и добиться правильной обработки запросов от вашего IoT-клиента. Убедитесь, что ваш сервер Nginx настроен в соответствии с требованиями используемых клиентских приложений и соблюдены все условия, чтобы избежать ненужных разрывов соединений.