reverse-proxy
Периметровая конфигурация HAProxy для сети kalinamall.ru: Exchange, RDS (веб/шлюз по HTTPS), 1С, почтовый шлюз KSMG. Прямой RDP (3389) через HAProxy не используется — клиенты идут через RDS на 443 (rds.kalinamall.ru).
TLS: на целевых серверах используются wildcard-сертификаты GlobalSign; HAProxy на 443 работает в режиме TCP + SNI и не терминирует TLS — сертификаты остаются на бэкендах.
Репозиторий: https://github.com/PTah/reverse-proxy
Клонирование на Ubuntu, обновление и доступ без постоянного ввода пароля
Установка Git
sudo apt update
sudo apt install -y git
Первое клонирование
Публичный репозиторий можно клонировать без логина и пароля:
cd ~
git clone https://github.com/PTah/reverse-proxy.git
cd reverse-proxy
Если репозиторий станет приватным или понадобятся push-правки с сервера, используйте один из способов ниже.
Обновление локальной копии
cd ~/reverse-proxy
git pull origin main
После git pull снова скопируйте при необходимости файлы в /etc/haproxy/ (см. раздел «Установка конфигурации»).
Как не вводить логин и пароль при каждом git pull / git push
Способ 1: SSH-ключ (предпочтительно)
-
Создайте ключ (имя файла можно своё):
ssh-keygen -t ed25519 -C "ubuntu-haproxy" -f ~/.ssh/id_ed25519_githubПарольную фразу можно задать или оставить пустой (на сервере оцените риски).
-
Покажите публичный ключ и добавьте его в GitHub: Settings → SSH and GPG keys → New SSH key.
cat ~/.ssh/id_ed25519_github.pub -
Проверьте доступ:
ssh -T git@github.com -
Клонируйте по SSH (или смените URL у уже существующего клона):
git clone git@github.com:PTah/reverse-proxy.git # уже склонировано по HTTPS — переключение: # git remote set-url origin git@github.com:PTah/reverse-proxy.git
Дальше git pull / git push идут по SSH без пароля GitHub (при необходимости один раз вводится только passphrase ключа, если вы её задали; её можно кешировать через ssh-agent).
Способ 2: HTTPS + Personal Access Token (PAT)
GitHub не принимает обычный пароль от аккаунта для операций git clone / git pull / git push по HTTPS. Вместо пароля нужно создать Personal Access Token (PAT) и вводить его там, где Git спрашивает пароль.
Создание классического токена (Tokens classic) — проще всего для Git
- Войдите на github.com под нужным аккаунтом.
- В правом верхнем углу откройте меню аватара → Settings (Настройки).
- В левой колонке прокрутите вниз до раздела Developer settings (Параметры разработчика) и откройте его.
- Выберите Personal access tokens → Tokens (classic).
- Нажмите Generate new token → Generate new token (classic).
- Заполните поля:
- Note — произвольное имя (например
ubuntu-haproxy-pull), чтобы потом понимать, зачем токен. - Expiration — срок действия (чем короче, тем безопаснее; для сервера часто выбирают ограниченный срок и потом перевыпускают).
- Select scopes — для приватного репозитория и
pull/pushвключите минимумrepo(полный доступ к репозиториям). Если нужен только чтение приватного репо, в классических токенах по-прежнему часто отмечаютrepo, т.к. узкого «только read» в classic нет; для только pull удобнее fine-grained (ниже).
- Note — произвольное имя (например
- Нажмите Generate token внизу страницы.
- Сразу скопируйте строку токена (начинается часто с
ghp_…). GitHub покажет её один раз; после ухода со страницы повторно не отобразит.
Fine-grained token (по желанию, гибче по правам)
- Те же Settings → Developer settings → Personal access tokens → Fine-grained tokens.
- Generate new token.
- Укажите имя, срок, в блоке Repository access выберите «только выбранный репозиторий» reverse-proxy (или «все» — по политике безопасности).
- В Permissions для чтения/обновления кода задайте Contents: Read-only или Read and write, при необходимости Metadata: Read.
- Создайте токен и скопируйте его (формат обычно
github_pat_…).
Использование PAT в Git на Ubuntu
- Username (логин): ваш логин GitHub (короткое имя пользователя), не e-mail, если Git явно просит username.
- Password: вставьте целиком PAT (не пароль от сайта).
Пример первого клонирования по HTTPS:
git clone https://github.com/PTah/reverse-proxy.git
# при запросе: Username = ваш_логин_github
# Password = вставить PAT
Чтобы не вводить PAT каждый раз
Токен хранится в открытом виде в ~/.git-credentials — используйте только на доверенных машинах:
git config --global credential.helper store
cd ~/reverse-proxy
git pull origin main
# один раз ввести Username + PAT — дальше подставятся из файла
Кеш в памяти на заданное время (секунды), без постоянной записи в файл:
git config --global credential.helper 'cache --timeout=28800'
После истечения срока кеша или срока действия токена на GitHub снова создайте новый PAT и при необходимости обновите сохранённые учётные данные (удалите строчку с github.com из ~/.git-credentials или снова выполните git pull и введите новый токен).
Способ 3: только чтение, репозиторий публичный
Для публичного репозитория git clone и git pull по HTTPS учётные данные не нужны — отдельная настройка не требуется.
Соответствие имён и адресов
| Служба | Внешнее имя (клиенты) | Внутренний хост / IP | Порт снаружи |
|---|---|---|---|
Microsoft Exchange (OWA https://ext.kalinamall.ru/owa, EWS, MAPI/HTTPS и т.д.) |
ext.kalinamall.ru |
fifth.kalinamall.ru — 192.168.160.42 | 443 (TCP/SNI) |
| Autodiscover | autodiscover.kalinamall.ru |
тот же Exchange — 192.168.160.42 | 443 (TCP/SNI) |
| RDS | rds.kalinamall.ru (443 на HAProxy) |
k6a-dc3.b26.kalinamall.ru — 192.168.160.40, служба 4430 | 443 (SNI → внутр. 4430) |
| 1С | erp.kalinamall.ru |
hp-serv.b26.kalinamall.ru — 192.168.160.150 | 443 |
| Почтовый шлюз (KSMG) | ksmg.kalinamall.ru |
ksmg.kalinamall.ru — 192.168.160.57 | 25 |
DNS: записи A для ext, autodiscover, rds, erp, ksmg должны указывать на публичный IP хоста с HAProxy. Имя autodiscover.kalinamall.ru должно быть в SAN wildcard *.kalinamall.ru или отдельно в сертификате на Exchange. |
Доступ по SSH к внутренним хостам (например Ubuntu 192.168.160.85) в этом репозитории не настраивается через HAProxy — организуйте отдельно (прямой проброс, VPN, бастион и т.д.).
В режиме TCP + SNI отдельные строки в HAProxy для путей вроде /owa не нужны: после согласования TLS клиент шлёт HTTP внутри шифрования, разбор путей делает IIS/Exchange на 192.168.160.42.
Установка HAProxy на Ubuntu 24.04 (Noble)
Для этого репозитория нужен HAProxy не ниже 2.4. Конструкции req_ssl_sni и tcp-request content accept (разбор ClientHello для SNI в TCP-режиме) входят в штатные сборки 2.8.x из Ubuntu 24.04 и во все актуальные ветки 3.x.
Вариант 1: пакет из репозитория Ubuntu (HAProxy 2.8.x)
Обычно этого достаточно для данного конфига:
sudo apt update
sudo apt install -y haproxy
haproxy -v
Проверьте, что версия 2.4+ (на Noble обычно 2.8.x).
Вариант 2: последняя ветка 3.x (PPA Vincent Bernat)
Актуальные пакеты HAProxy 3.3.x для Noble публикуются в PPA vbernat/haproxy-3.3 (номер микроверсии может обновляться; см. страницу PPA). Не подключайте одновременно несколько PPA с разными ветками HAProxy.
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:vbernat/haproxy-3.3
sudo apt update
sudo apt install -y haproxy
haproxy -v
sudo systemctl enable --now haproxy
Другие ветки того же автора (при необходимости): haproxy-3.2, haproxy-3.1, haproxy-3.0, а также haproxy-2.8 — всегда выбирайте одну строку версии.
Проверка синтаксиса конфига
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
Установка конфигурации из репозитория
-
Убедитесь, что установлен HAProxy 2.4+ (см. раздел выше).
-
Скопируйте
haproxy.cfgв/etc/haproxy/haproxy.cfg. Пример, если репозиторий лежит в домашнем каталоге:sudo cp ~/reverse-proxy/haproxy.cfg /etc/haproxy/haproxy.cfg -
Проверка и перезапуск:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg sudo systemctl reload haproxy
Проверка ssl verify none на бэкендах
В backend для 443 указано ssl verify none, чтобы health-check и при необходимости установка соединения не ломались на внутренних именах/SAN. Если вы выпустите внутренние доверенные CA и зададите их в системе, можно включить проверку (verify required + ca-file).
Порты на фаерволе
На хосте с HAProxy с интернета обычно открывают только то, что слушает конфиг: 25, 443 (и при использовании — 8404 для stats). Остальной трафик — по политике безопасности.
Порт 80 и Let’s Encrypt / ACME (на будущее)
Сейчас в haproxy.cfg порт 80 не используется. Ниже — что иметь в виду, если появится, например, Ubuntu во внутренней сети, на которую нужно выпускать сертификаты Let’s Encrypt с автообновлением.
Нужен ли для ACME именно порт 80?
Не всегда. У Let’s Encrypt (протокол ACME) есть несколько типов проверки владения доменом:
| Тип | Порт | Комментарий |
|---|---|---|
| HTTP-01 | 80 (HTTP) | Центр сертификации делает запрос вида http://ваш-домен/.well-known/acme-challenge/.... С интернета до отвечающего хоста порт 80 должен быть доступен (напрямую или через проброс на HAProxy). |
| DNS-01 | не нужен 80/443 | Запись в DNS; удобно, когда 80 снаружи открывать нельзя или сертификат для внутреннего имени. |
| TLS-ALPN-01 | 443 | Проверка по TLS; порт 80 не обязателен. |
Итого: при классическом Certbot + webroot/standalone с проверкой HTTP-01 порт 80 действительно участвует. При DNS-01 отдельный HTTP на 80 для выпуска не нужен.
Автообновление обычно делают certbot renew по systemd timer или cron — это на стороне машины с Certbot, не в HAProxy.
Если позже понадобится HTTP на 80 через этот HAProxy (например, HTTP-01)
- На пограничном роутере разрешить с интернета TCP 80 на IP хоста с HAProxy (или на тот хост, где будет отвечать ACME).
- В
haproxy.cfgдобавить отдельный HTTP-фронтенд на 80 и отправлять только путь проверки на бэкенд с ответом ACME (остальное — редирект на HTTPS, пустой ответ или отказ — по политике).
Пример: два Ubuntu в LAN и HTTP-01 через один периметровый HAProxy
Допустим, во внутренней сети два сервера Ubuntu, для обоих нужны публичные имена и периодическое обновление сертификатов Let’s Encrypt по HTTP-01:
| Имя (снаружи) | Внутренний IP |
|---|---|
| ubuntu1.kalinamall.ru | 192.168.160.90 |
| ubuntu2.kalinamall.ru | 192.168.160.60 |
DNS: записи A для ubuntu1.kalinamall.ru и ubuntu2.kalinamall.ru должны указывать на тот же публичный IP, что и для остальных сервисов за HAProxy (чтобы запросы Let’s Encrypt пришли на порт 80 этого хоста).
На каждой Ubuntu: поднимите HTTP на порту 80 (nginx/apache) с корнем для Certbot webroot (/.well-known/acme-challenge/…) или используйте схему выпуска с DNS-01, если открывать 80 не хотите. Автообновление — certbot renew + systemd timer (или cron) на соответствующей машине.
На HAProxy: один фронтенд на 80, маршрутизация по заголовку Host + путь ACME на разные бэкенды:
frontend fe_http
bind *:80
mode http
option httplog
acl path_acme path_beg /.well-known/acme-challenge/
acl host_u1 hdr(host) -i ubuntu1.kalinamall.ru
acl host_u2 hdr(host) -i ubuntu2.kalinamall.ru
use_backend be_acme_u1 if path_acme host_u1
use_backend be_acme_u2 if path_acme host_u2
http-request deny if !path_acme
backend be_acme_u1
mode http
server u1 192.168.160.90:80 check
backend be_acme_u2
mode http
server u2 192.168.160.60:80 check
Let’s Encrypt при проверке обращается к http://ubuntu1.kalinamall.ru/.well-known/... или http://ubuntu2... — HAProxy по Host пересылает запрос на нужный внутренний :80, где локальный веб-сервер отдаёт файлы challenge.
Варианты без проброса HTTP на две машины: на каждой Ubuntu DNS-01 (порт 80 на периметре тогда не обязателен для этих сертификатов); либо TLS-ALPN-01 по 443 (потребуется уже другая схема на HAProxy, не этот пример).
После добавления bind :80 допишите в раздел «Порты на фаерволе» выше порт 80 и выполните sudo haproxy -c -f /etc/haproxy/haproxy.cfg.
Лицензия
Конфигурация поставляется как есть, без гарантий. Используйте на свой риск.