LINUX.ORG.RU
ФорумAdmin

Странная работа виртуальных хостов NGINX

 ,


1

2

Приветствую,

Помогите разобраться, пожалуйста.

Имеется хост, на котором в докере вертится основной сервис, публикуется NGNXом, развернутом в том же контейнере. само по себе все работает ок.

Задача стоит в том, чтобы запустить еще серверы в отдельных контейнерах, скажем, сервис first и сервис second. Они запущены и прокинуты на хосте, на http://host:3000 и http://host:4000 соответственно. Все пока еще работает ок. Но, разумеется, я хочу полноценно опубликовать все наружу в виде https://first.host и https://second.host. настраиваю конфиг first, подкладываю сертификат и ключ - все опять же пока работает. https://host отражается корректно и https://first.host - отражается корректно и со своими сертификатами. А вот дальше чудеса. Настраиваю конфиг second, абсолютно идентичный с first, естественно изменен хост обращения, адрес локации и сертификаты свои. Запускаю и начинается. https://first.host и https://second.host показываются нормально. Но https://host почему-то цепляет сертификат от second (и, разумеется, ругается в браузере). Ладно, думаю, подсуну сертификат вайлдкарт. В таком случае https://host попросту открывает не страницу основного сервиса, а страницу https://second.host.

Сломал голову. Есть идеи?

Читайте документацию https://nginx.org/ru/docs/http/configuring_https_servers.html#name_based_https_servers

в общем случае:

браузер получит сертификат сервера по умолчанию, т.е. www.example.com, независимо от запрашиваемого имени сервера. Это связано с поведением протокола SSL. SSL-соединение устанавливается до того, как браузер посылает HTTP-запрос, и nginx не знает имени запрашиваемого сервера. Следовательно, он лишь может предложить сертификат сервера по умолчанию.

По ссылке и варианты, как на это можно повлиять, если несколько хостов на одном IP.

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 3)
Ответ на: комментарий от vvn_black

Бред какой-то написан. SNI придумали сто лет назад и nginx его прекрасно поддерживает из коробки без каких-либо ухищрений.

Вот мой конфиг:

server {
  listen 443 ssl;
  server_name vbezhenar.com;

  ssl_certificate /etc/letsencrypt/live/vbezhenar.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/vbezhenar.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/vbezhenar.com/chain.pem;
  include /etc/nginx/ssl.conf;

  root /var/www/html;
}

server {
  listen 443 ssl;
  server_name www.vbezhenar.com;

  ssl_certificate /etc/letsencrypt/live/vbezhenar.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/vbezhenar.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/vbezhenar.com/chain.pem;
  include /etc/nginx/ssl.conf;

  return 301 https://vbezhenar.com$request_uri;
}

server {
  listen 443 ssl default_server;

  ssl_certificate /etc/letsencrypt/live/vbezhenar.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/vbezhenar.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/vbezhenar.com/chain.pem;
  include /etc/nginx/ssl.conf;

  return 301 https://vbezhenar.com/;
}

server {
  listen 443 ssl http2;
  server_name alpine.vbezhenar.com;

  ssl_certificate /etc/letsencrypt/live/alpine.vbezhenar.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/alpine.vbezhenar.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/alpine.vbezhenar.com/chain.pem;
  include /etc/nginx/ssl.conf;

  return 301 https://vbezhenar.com/;
}

Всё просто работает как ожидается.

vbr ★★★
()
Последнее исправление: vbr (всего исправлений: 1)

… Но, разумеется, я хочу полноценно опубликовать все наружу в виде https://first.host и https://second.host

Вы можете экспортировать 443-е порты разных контейнеров только на разные интерфейсы - разные IP-шники. Если на хосте только один внешний интерфейс, то и слушающий наружу Nginx-контейнер должен быть тоже один. Доступ ко второму контейнеру можно организовать только через первый контейнер в режиме reverse proxy.

vinvlad ★★
()

… ну а если вы все домены законфигурили в одном контейнере и непонятки возникают именно в этом контейнере, то надо выкладывать сюда конфигурацию Nginx

vinvlad ★★
()

Ты не очень понятно описал. Покажи конфиг. Ну и сразу рекомендую выкинуть ненужный докер. Хотя бы nginx запускать без него.

firkax ★★★★★
()

Так, а для https://host ты вхост сделал? Если не сделал, сделай фоллбек-вхост с именем вроде _ на который будут падать все запросы к несконфигурированным вхостам и рули оттуда сертами и редиректами

slowpony ★★★★★
()

Попробую уточнить.

на хосте есть несколько контейнеров со своими задачами. Один основной (OnlyOffice Community Server), остальные дополнительные и их планируется еще больше.

443 порт хоста хватает сразу основной контейнер, попытки настроить nginx, установленный на хосте или на новом контейнере, или установить NPM не помогли, все равно отвечает сайт из контейнера.

Как нарулен nginx OOCS мне не очень понятно, в sites-enabled лежит следующий конфиг:

http://pastie.org/p/6JpMsvZGLDy9PYUmQu02rt

для направления обращений на субдомены, я делал дополнительные конфигурации сайтов типа такого:

http://pastie.org/p/4LhtyYhGePtwvVwZvKhR9x

Пробовал и на каждый субдомен сертификаты использовать, и вайлдкарт - результат один.

Прошу прощения, если сумбурно и непонятно.

geopluz
() автор топика
Ответ на: комментарий от vinvlad

я пытаюсь привязывать к 443 портам субдоменов http-сайты на кастомных портах, которые опубликованы на хосте. Хотя настройка nginx производится в одном из контейнеров, да. Конфиги я ниже положил. До настройки SSL я публиковал дополнительные сайты на 80 порту субдоменов - все открывалось. Проблема вылезла при попытке вывесить из на 443.

geopluz
() автор топика
Ответ на: комментарий от geopluz

В целом это всё делается очень просто.

Ты делаешь по контейнеру на каждый сервис. Каким образом 443 порт хоста у тебя хватает контейнер, я не понимаю, такого не бывает. У контейнера свой IP. У хоста свой. В сервисе вообще https не нужен, только http. На какой-нибудь 8080 порт.

Также ты делаешь отдельный контейнер для нгинкса.

И вот для контейнера нгинкса ты делаешь маппинг порта на хостовый. Т.е. те, кто приходят на твой хост попадают в нгинкс.

А в нгинксе ты уже прописываешь сертификаты, получение их через LE. И реверс-проксируешь соединения на контейнеры. Нгинкс через server_name будет понимать, что куда должно идти.

Вместо нгинкса советую взять кадди. Проще с сертификатами будет. Но это опционально. Главное - принцип.

А ещё проще через кубернетес это всё сделать. Там вообще всё автоматом работает. Ингрессы прописываешь и всё.

vbr ★★★
()
Последнее исправление: vbr (всего исправлений: 4)
Ответ на: комментарий от geopluz

… на хосте есть несколько контейнеров со своими задачами. Один основной (OnlyOffice Community Server), остальные дополнительные и их планируется еще больше.

Если всё делать по уму, то тебе нужно законфигурить на хосте проект Docker Compose с внутренней bridge-сеткой и туда положить OOCS-контейнер и твои дополнительные контейнеры - так просто проще будет управлять всем этим барахлом. Открытыми наружу должны быть только порты 80 и 443 OOCS-контейнера. В папку sites-enabled OOCS-контейнера должны быть добавлены Nginx-конфигурации твоих дополнительных доменов, которые в режиме reverse proxy, или еще как, обеспечивают интерфейс к дополнительным контейнерам. Там же, в OOCS-контейнере, должны естественно лежать и сертификаты дополнительных доменов. Городить SSL в дополнительных контейнерах не требуется - достаточно 80-го порта и простого HTTP (или, к примеру, FastCGI для PHP-приложения), поскольку обмен между контейнерами осуществляется по внутренней Docker-сетке.

Ну и надо понимать, что когда HTTP/HTTPS запрос попадает на Nginx-сервер и Nginx не находит у себя соответствующего домена, то он обрабатывает этот запрос в контексте своего дефолтного виртуального хоста, в качестве которого выступает первая имеющаяся server-конфигурация.

Вот как-то так…

vinvlad ★★
()

https://first.host и https://second.host показываются нормально. Но https://host почему-то цепляет сертификат от second (и, разумеется, ругается в браузере).

Если конфигурации виртуальных хостов были подсунуты в основной OOCS-контейнер, то возможно, что second.host оказался первым при загрузке конфигурации Nginx и, соответственно, стал использоваться в качестве дефолтного. Дело в том, что в конфигурации OOCS вообще не указано имя домена, а просто лежит директива:

server_name  _;

Когда не было дополнительных виртуальных хостов, то эта конфигурация цеплялась просто как дефолтная. При добавлении кастомных виртуальных хостов она могла сдвинуться вниз при загрузке конфигурации - ну и начались проблемы с доступом.

vinvlad ★★
()
Ответ на: комментарий от vinvlad

Так примерно так все и есть. ngшnx в контейнере OOCSб туда забриджованы сетки других контейнеров. Проксировать не на http://host:3000, а на http://имяконтейнера:3000 я уже пробовал, это ничего не меняет.

В дополнительных контейнерах ничего не городил, все конфиграции обратных прокси лежат в sites-enabled nginx контейнера с OOCS.

geopluz
() автор топика
Ответ на: комментарий от vbr

Каким образом 443 порт хоста у тебя хватает контейнер, я не понимаю, такого не бывает.

Ну вот как выясняется, бывает. Я тоже планировал nginx наруливать или на хосте или в отдельном контейнере. Но все настройки там игнорировались, работал nginx «основного» контейнера.

Насчет кубернетс и кадди - возможно, это проще, но во-первых, я с ними совсем не знаком, а во вторых, у меня уже готов основной сервис и несколько дополнительных, они полностью функицональны, просто хочется, чтобы все было по https, но не хочется все заново наруливать с нуля.

geopluz
() автор топика
Ответ на: комментарий от vinvlad

Наверное, стоит попробовать заменить _ на имя домена, но тут может возникнуть другая задачка - сам сервис OOCS подразумевает создание теннатов, и кроме office.host могут появиться office2.host и office3.host. Насколько я понимаю, если я заменю _ на имя домена, мне придется в nginx создавать конфиги для каждого поддомена. Сейчас это не требуется, создаю теннант в интерфейсе и он работает. Но это меньшее из зол, в принципе, можно и создавать.

Спасибо за идею

geopluz
() автор топика
Ответ на: комментарий от geopluz

… но тут может возникнуть другая задачка

Чтобы не возникало каких-то конфликтов с OOCS, можно положить конфигурации кастомных доменов в отдельную директорию и подключить эту директорию к Nginx непосредственно в файле /etc/nginx/nginx.conf - что-то типа:

...
include /etc/nginx/sites-enabled/*;
include /etc/nginx/custom-sites/*;

Тогда дефолтной всегда будет OOCS-конфигурация

vinvlad ★★
()

Вопрос решился легко, хотя и немного костыльно.

Конфиг OOCS называется openoffice.

А хватается все из первого конфига по алфавиту, поэтому все конфиги, которые начинались с буквы до «О» становились дефолтными. Переименовал все до-ошные конфиги на после-ошные и все заработало.

Большое всем спасибо.

geopluz
() автор топика