Вопрос или проблема
Я перевел свой экземпляр AWS на публичный IPv6 адрес, чтобы избежать сборов за публичный IPv4, введенных некоторое время назад. У меня есть около шести доменов, размещенных на сервере EC2 с Nginx, с CloudFlare в качестве DNS и CDN. CloudFlare подключается к моему исходному серверу только по IPv6 и делает домены доступными как по IPv4, так и по IPv6.
Вебсайты корректно работают по https, но я заметил странное поведение с http-запросами. Когда я делал http-запрос к одному домену, он возвращал сайт другого из моих доменов. Мне потребовалось довольно много времени, чтобы выяснить, почему.
Например – я делаю curl example.com и получаю редирект на example2.com
curl -v http://example.com
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Content-Type: text/html
< Connection: keep-alive
< Location: https://example2.com
Вот конфиг Nginx – рассмотрите его как псевдокод, он может не пройти “nginx -t”.
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
root /var/www/example/;
}
server {
listen [::]:80;
server_name example2.com;
return 301 https://example2.com$request_uri;
}
server {
server_name example2.com;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example2.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example2.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
root /var/www/example2/;
}
Когда я изучил руководство по сопоставлению Nginx Location на Digital Ocean, я наконец-то разобрался в проблеме. Nginx сначала осуществляет сопоставление по порту прослушивания и протоколу, только если на этом порту прослушивания больше одного блока, тогда он сопоставляет по server_name.
Когда я перешел на IPv6, я обновил все https-серверы для прослушивания как на IPv4, так и на IPv6, но я пропустил обновление большинства доменов для http-редиректов на прослушивание IPv6. Как только я заставил серверы-редиректы прослушивать IPv6 наряду с IPv4, все начало работать как ожидалось.
Ключевые шаги в решении проблемы были:
- Использование другого сервера Linux с измененным файлом hosts, чтобы он указывал непосредственно на исходный сервер, а не на CloudFlare (не уверен, имело ли это большое значение)
- “curl -v http://example.com
- Чтение цифрового руководства – хотя оно не упоминает IPv6, это очень помогло
Вот рабочая псевдокод конфигурация
server {
# ЭТА СТРОКА БЫЛА ПРОБЛЕМОЙ
listen [::]:80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
root /var/www/example/;
}
server {
listen [::]:80;
server_name example2.com;
return 301 https://example2.com$request_uri;
}
server {
server_name example2.com;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example2.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example2.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
root /var/www/example2/;
}
Ответ или решение
Решение проблемы несоответствия блоков Nginx для IPv4 и IPv6
Проблема, с которой вы столкнулись, связана с работой Nginx в многопоточной среде, когда сервер обслуживает трафик как по IPv4, так и по IPv6. Давайте подробно разберем основные аспекты и шаги, которые помогут вам понять и исправить вашу конфигурацию сервера.
Понимание конфигурации Nginx
Nginx использует алгоритм выбора блоков сервера, опираясь на два базовых критерия: сначала по порту и протоколу, а затем по имени сервера. Это значит, что в случае одновременного наличия нескольких блоков для одного и того же порта, Nginx будет сопоставлять их на основе заданного server_name.
Проблема: пропущенные настройки
Вы правильно отметили, что основная проблема заключалась в том, что не все блоки редиректа для HTTP-трафика были настроены на прослушивание IPv6. Это привело к тому, что при отправке HTTP-запросов, например, на example.com
, Nginx неправильно обрабатывал запрос и перенаправлял его на другой домен, такой как example2.com
.
Шаги к решению
-
Проверка конфигурации Nginx:
Убедитесь, что все блоки для перенаправлений на HTTP (порт 80) настроены для прослушивания как IPv4, так и IPv6. Ваша доработанная конфигурация продемонстрировала, как это можно исправить:server { listen 80; listen [::]:80; server_name example.com; return 301 https://example.com$request_uri; } server { listen 80; listen [::]:80; server_name example2.com; return 301 https://example2.com$request_uri; }
-
Тестирование конфигурации:
Используйтеcurl
для проверки поведения вашего сервера после внесения изменений. Например:curl -v http://example.com
Это поможет вам убедиться, что HTTP-запросы обрабатываются корректно.
-
Использование локального сервера для тестирования:
Размещение отдельного сервера, который с помощью измененного файла hosts будет направлять запросы непосредственно на ваш основной сервер, позволяет вам избежать возможных проблем кэширования на уровне CDN, таких как CloudFlare. -
Документация и дополнительные ресурсы:
Как вы уже знаете, полезно всегда обращаться к официальной документации и руководствам. Даже если не все аспекты, такие как IPv6, подробно охвачены, это может дать понимание общей работы системы.
Заключение
Ваша ситуация подчеркивает важность детальной проверки конфигураций серверов, особенно в условиях работы с несколькими доменами и сетевыми протоколами. Исправив настройки прослушивания для HTTP-блоков, вы обеспечили корректное перенаправление для обоих доменов.
При дальнейшем мониторинге и тестировании работы вашего веб-сервера, не забудьте обратить внимание на логи Nginx для выявления возможных дополнительных проблем. Корректные и продуманные настройки сервера не только улучшат пользовательский опыт, но и помогут избежать лишних затрат.