Как разместить несколько сайтов и сервисов за одним внешним IP
Как работает reverse proxy, зачем нужен split DNS, где выпускаются и продлеваются сертификаты, что ломает WebSocket и крупные загрузки, и что резервировать в конфигурации.
Внешний IP-адрес обычно один, а сервисов, которые нужно опубликовать, — десятки: корпоративное облако, вики, система задач, мониторинг, сайты. Пробрасывать каждому свой порт неудобно и небезопасно: адреса вида `example.com:8443` неудобны людям, а каждый открытый порт — отдельная точка входа.
Рабочая схема — один вход, маршрутизация по доменному имени.
Как это работает
Все домены указывают на один внешний адрес. На нём стоит reverse proxy — он принимает соединение, завершает TLS, смотрит на имя запрошенного узла и передаёт запрос нужному внутреннему сервису.
┌──────────────────────────┐
cloud.example.com ─┐ │ reverse proxy │ ─→ 127.0.0.1:8080 облако
wiki.example.com ─┼→│ один внешний адрес, │ ─→ 127.0.0.1:8081 вики
git.example.com ─┤ │ TLS, маршрутизация │ ─→ 127.0.0.1:8082 git
shop.example.com ─┘ │ по имени узла │ ─→ 127.0.0.1:3000 сайт
└──────────────────────────┘Ключевой момент: имя узла передаётся в заголовке запроса, поэтому один адрес и один порт 443 обслуживают любое количество сервисов. Внутренние приложения при этом слушают только локальный интерфейс и наружу не выставлены вовсе.
Что нужно настроить
Шаг 1
DNS: все имена на один адрес
Для каждого сервиса заводится своя A-запись, указывающая на внешний адрес. Отдельных адресов не требуется.
Шаг 2
Сертификаты
Выпускаются на конкретные имена. Проверка обычно проходит по HTTP: proxy отдаёт файл подтверждения из общего каталога, поэтому правило для него настраивается один раз для всех доменов.
Шаг 3
Маршрутизация по имени
На каждый домен — свой блок конфигурации с адресом внутреннего сервиса. Ошибка здесь приводит к тому, что запрос уходит не туда, — об этом ниже.
Шаг 4
Заголовки для приложения
Внутренний сервис должен знать исходное имя узла, адрес клиента и протокол. Без них ломаются редиректы и в логах видно только адрес proxy.
Шаг 5
Отдельные правила для особых случаев
WebSocket, крупные загрузки, длинные ответы — им нужны свои настройки таймаутов и лимитов.
Шаг 6
Split DNS для внутренней сети
Чтобы адреса совпадали внутри офиса и снаружи.
Split DNS: одинаковые адреса внутри и снаружи
Проблема: сотрудник в офисе открывает `wiki.example.com`, запрос уходит на внешний адрес и возвращается обратно через провайдера. В части конфигураций такой разворот не работает вовсе, и внутри сети сервис оказывается недоступен.
Решение — split DNS: внутренний DNS-сервер отдаёт для тех же имён внутренний адрес proxy, внешний отдаёт внешний.
| Откуда запрос | Что отдаёт DNS | Маршрут |
|---|---|---|
| Из офиса | Внутренний адрес proxy | Напрямую внутри сети |
| Извне | Внешний адрес | Через провайдера на тот же proxy |
Так и сотрудники, и удалённые пользователи, и документация используют один адрес. Без этого появляются два комплекта ссылок, и половина из них где-нибудь не работает.
Типичные проблемы
Запрос попадает не на тот сервис
Если для запрошенного имени нет подходящего блока конфигурации, proxy отдаёт запрос первому подходящему по своим правилам — обычно первому в порядке загрузки. Внешне это выглядит как «мой домен показывает чужой сайт».
Особенно неприятен вариант, когда чужой блок отвечает постоянным редиректом: такой ответ кешируется браузерами и поисковиками, и последствия переживают исправление конфигурации.
Профилактика: заводить конфигурацию домена до того, как на него переключается DNS, и явно задавать блок по умолчанию для необслуживаемых имён.
Сломанный WebSocket
Чаты, панели мониторинга и совместное редактирование используют постоянное соединение. Без передачи заголовков смены протокола соединение обрывается, а приложение выглядит «подвисающим» без ошибок в интерфейсе.
Ограничение размера загрузки
У proxy есть лимит размера тела запроса, обычно небольшой по умолчанию. Пользователь пытается загрузить файл в облако и получает ошибку, хотя само приложение настроено правильно. Лимит нужно выставлять на обеих сторонах.
Истёкший сертификат
Автопродление настроено, но после обновления сертификата proxy не перечитал конфигурацию и продолжает отдавать старый. Или продление тихо не сработало, и об этом никто не узнал до предупреждения в браузере.
Профилактика: хук перезагрузки после продления и отдельная проверка в мониторинге по сроку действия сертификата, а не по факту запуска задания.
Потеря реального адреса клиента
Если не передавать исходный адрес, приложение видит только адрес proxy. Ломаются ограничения по количеству запросов, геолокация и разбор инцидентов по логам.
Безопасность
- Внутренние сервисы слушают только локальный интерфейс. Иначе публикация через proxy не мешает обратиться к ним напрямую по порту.
- Разделять публичное и внутреннее. Часть сервисов не должна быть доступна из интернета вовсе — их публикуют только внутри сети или через VPN.
- Ограничение частоты запросов на публичных адресах: снижает эффект перебора и простых атак.
- Заголовки безопасности задаются приложением или proxy, но в одном месте — дублирование приводит к тому, что заголовок уходит дважды.
- Отключить выдачу версии сервера и листинг каталогов.
- Логи по каждому домену отдельно — иначе разбор инцидента превращается в поиск по общей куче.
Что резервировать
Конфигурация публикации — это тоже данные, и их потеря означает, что схему придётся собирать заново по памяти.
- конфигурационные файлы proxy целиком, включая общие фрагменты;
- сертификаты и закрытые ключи, вместе с настройками автопродления;
- зоны DNS — внутренние и внешние;
- перечень «домен → внутренний сервис → порт» в понятном человеку виде.
Последний пункт часто недооценивают. При восстановлении с нуля именно эта таблица экономит больше всего времени: конфигурацию можно собрать заново, а вот вспомнить, какой сервис на каком порту жил, — сложно.
Как убедиться, что эти копии действительно разворачиваются, — в материале о тестовом восстановлении.
Порядок публикации нового сервиса
- Поднять сервис локально, привязать к локальному интерфейсу.
- Завести A-запись домена на внешний адрес и внутреннюю запись в split DNS.
- Создать блок конфигурации proxy до переключения трафика.
- Выпустить сертификат, проверить автопродление и хук перезагрузки.
- Проверить: HTTPS отвечает, HTTP уходит редиректом, WebSocket работает, крупный файл загружается.
- Добавить сервис в мониторинг: доступность, срок сертификата, время ответа.
- Внести в резервное копирование конфигурацию и обновить таблицу «домен → сервис».
Шестой пункт закрывает самый частый сценарий: сервис опубликовали, а узнают о его недоступности от пользователей. Что именно стоит проверять — в разборе мониторинга серверов.