Konstantin GARSHENIN
ну так и дай схему настройки на srv1.. почему в ngnix на srv1 не предлагает заменить sni который ожидает srv2. логика клиент - srv1 sni point.simple.com ngnix 443 - замена sni на simple.com и переадресация на srv2
да. вижу не взлетит. sni на рф другой. Предложи еще что-то
🐶 Тогда остаётся **не stream, а reverse proxy на SRV1**.
Схема такая, `клиент → домен на SRV1:443 → nginx терминирует TLS → upstream на SRV2 с его старым SNI`.
Ключевой момент, `stream` SNI не переписывает вообще.
А вот `nginx http/https proxy` умеет к upstream идти со своим `proxy_ssl_name`:
```nginx
location / {
proxy_pass https://SRV2_IP:8443;
proxy_ssl_server_name on;
proxy_ssl_name old.srv2.sni;
proxy_set_header Host old.srv2.sni;
}
```
То есть:
- **SRV2 не трогаем**,
- **новый домен живёт на SRV1**,
- наружу светится только SRV1,
- на SRV2 уходит уже внутренний HTTPS-запрос с нужным старым SNI.
Если хочешь, я сейчас соберу **готовую полную схему для SRV1**, отдельно для **сайта** и отдельно для **точки входа**.
новый домен или поддомен от simple.com который на srv2]
🐶 Лучше **отдельный поддомен** от твоего домена, например `point.simple.com` или `new-entry.simple.com`, и он должен указывать **на SRV1**.
`SRV2` при этом вообще не трогаем, туда SRV1 уже сам проксирует дальше.
То есть логика такая: **DNS → SRV1 → nginx → SRV2**.
Если `simple.com` уже живёт на SRV2, просто заведи **новый поддомен** под входную точку.
давай схему для srv1. и еще вопрос почему ngnix а не haproxy
[tool_call:memory_search]
🐶 Да, тогда **SRV1 = входная точка на HAProxy**, а **SRV2 вообще не трогаем**.
### Схема
`клиент → point.simple.com → SRV1:443 (HAProxy) → SRV2:443 (старый SNI)`
### Почему HAProxy, а не nginx
- `nginx stream` SNI **только читает**, не переписывает.
- `HAProxy` умеет **смотреть SNI на входе** и **идти к backend со своим SNI**.
- То есть SRV2 можно оставить как есть, а новую точку сделать только на SRV1.
### Минимально по SRV1
```haproxy
frontend ft_443
bind :443
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
acl sni_point req.ssl_sni -i point.simple.com
use_backend bk_srv2 if sni_point
backend bk_srv2
mode tcp
server srv2 10.0.0.2:443 ssl verify none sni str(old.srv2.sni)
```
### Итог
- **SRV2 не меняем**
- **новый домен/поддомен смотрит на SRV1**
- **SRV1 гасит SNI и заново ходит на SRV2 с нужным старым SNI**
Если хочешь, следующим сообщением дам **полный готовый конфиг HAProxy + DNS + firewall**.
МОЛОДЕЦ! Давай конфиг
[tool_call:memory_search]
🐶 Да, вот рабочая схема для **SRV1 без правок SRV2**.
Но это уже **TLS terminate на SRV1, потом TLS к SRV2**, иначе SNI не заменить.
```text
DNS: point.simple.com -> SRV1
SRV1: 443 -> HAProxy
SRV2: 443 -> как есть, с его старым SNI
```
### SRV1
```bash
apt update
apt install -y haproxy certbot
certbot certonly --standalone -d point.simple.com
mkdir -p /etc/haproxy/certs
cat /etc/letsencrypt/live/point.simple.com/fullchain.pem \
/etc/letsencrypt/live/point.simple.com/privkey.pem \
> /etc/haproxy/certs/point.simple.com.pem
chmod 600 /etc/haproxy/certs/point.simple.com.pem
```
### `/etc/haproxy/haproxy.cfg`
```haproxy
global
log /dev/log local0
maxconn 4096
defaults
log global
mode tcp
option tcplog
timeout connect 5s
timeout client 60s
timeout server 60s
frontend fe_443
bind :443 ssl crt /etc/haproxy/certs/point.simple.com.pem
mode tcp
default_backend bk_srv2
backend bk_srv2
mode tcp
server srv2 SRV2_IP:443 ssl verify none sni str(old.srv2.sni)
```
### Если на SRV1 ещё нужен сайт
Отдай ему `8443` или другой порт, а `443` оставь HAProxy.
### Почему HAProxy, а не nginx
- `nginx stream` SNI только **читает**, не переписывает.
- `nginx http proxy` удобен только для обычного HTTP.
- `HAProxy` лучше для твоего случая, он умеет **входной TLS принять, а к SRV2 идти уже со своим SNI**.
Если хочешь, следующим сообщением дам ещё **готовый `systemd`-файл и renew-hook для certbot**.
лучше в докер заверни .. env скриптом
чего такой скрипт то кривой. добавь в него env.
🐶 Да, вот уже норм вариант с `.env`, SRV2 не трогаем.
### `.env`
```env
DOMAIN=point.simple.com
EMAIL=admin@simple.com
SRV2_IP=1.2.3.4
SRV2_SNI=old.srv2.sni
```
### `docker-compose.yml`
```yaml
services:
haproxy:
image: haproxy:2.9-alpine
container_name: srv1-haproxy
restart: unless-stopped
ports:
- "443:443"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./certs:/usr/local/etc/haproxy/certs:ro
```
### `haproxy.cfg.tpl`
```haproxy
global
log stdout format raw local0
defaults
log global
mode tcp
option tcplog
timeout connect 5s
timeout client 60s
timeout server 60s
frontend fe_443
bind :443 ssl crt /usr/local/etc/haproxy/certs/${DOMAIN}.pem
mode tcp
acl sni_ok req.ssl_sni -i ${DOMAIN}
use_backend bk_srv2 if sni_ok
tcp-request content reject if !sni_ok
backend bk_srv2
mode tcp
server srv2 ${SRV2_IP}:443 ssl verify none sni str(${SRV2_SNI})
```
### `bootstrap.sh`
```bash
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
set -a
source .env
set +a
apt update
apt install -y docker.io docker-compose-plugin certbot gettext-base
mkdir -p certs letsencrypt
docker run --rm --network host \
-v "$PWD/letsencrypt:/etc/letsencrypt" \
certbot/certbot certonly --standalone \
-d "$DOMAIN" -m "$EMAIL" --agree-tos --non-interactive
cat "letsencrypt/live/$DOMAIN/fullchain.pem" \
"letsencrypt/live/$DOMAIN/privkey.pem" > "certs/$DOMAIN.pem"
envsubst < haproxy.cfg.tpl > haproxy.cfg
docker compose up -d
```
### `renew.sh`
```bash
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
set -a
source .env
set +a
docker run --rm --network host \
-v "$PWD/letsencrypt:/etc/letsencrypt" \
certbot/certbot renew --standalone
cat "letsencrypt/live/$DOMAIN/fullchain.pem" \
"letsencrypt/live/$DOMAIN/privkey.pem" > "certs/$DOMAIN.pem"
docker compose restart haproxy
```
Если хочешь, следующим сообщением дам ещё **cron для автообновления** и **проверку `haproxy -c` перед стартом**.
посмотри и проверь.
#!/usr/bin/env bash
set -euo pipefail
echo "=== SRV1 bootstrap (HAProxy + Let's Encrypt) ==="
# --- Ввод параметров ---
read -rp "Domain (example.com): " DOMAIN
read -rp "Email (for Let's Encrypt): " EMAIL
read -rp "SRV2 IP: " SRV2_IP
read -rp "SRV2 SNI: " SRV2_SNI
# --- Проверка ---
if [[ -z "$DOMAIN" -z "$EMAIL" -z "$SRV2_IP" || -z "$SRV2_SNI" ]]; then
echo "❌ Все поля обязательны"
exit 1
fi
# --- Установка зависимостей ---
echo "=== Installing packages ==="
apt update
apt install -y docker.io docker-compose-plugin certbot gettext-base
systemctl enable docker
systemctl start docker
# --- Создание структуры ---
echo "=== Creating project structure ==="
mkdir -p srv1/{certs,letsencrypt}
cd srv1
# --- .env ---
cat > .env <<EOF
DOMAIN=$DOMAIN
EMAIL=$EMAIL
SRV2_IP=$SRV2_IP
SRV2_SNI=$SRV2_SNI
EOF
# --- docker-compose.yml ---
cat > docker-compose.yml <<'EOF'
services:
haproxy:
image: haproxy:2.9-alpine
container_name: srv1-haproxy
restart: unless-stopped
ports:
- "443:443"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./certs:/usr/local/etc/haproxy/certs:ro
EOF
# --- haproxy.cfg.tpl ---
cat > haproxy.cfg.tpl <<'EOF'
global
log stdout format raw local0
defaults
log global
mode tcp
option tcplog
timeout connect 5s
timeout client 60s
timeout server 60s
frontend fe_443
bind :443 ssl crt /usr/local/etc/haproxy/certs/${DOMAIN}.pem
mode tcp
acl sni_ok req.ssl_sni -i ${DOMAIN}
use_backend bk_srv2 if sni_ok
tcp-request content reject if !sni_ok
backend bk_srv2
mode tcp
server srv2 ${SRV2_IP}:443 ssl verify none sni str(${SRV2_SNI})
EOF
# --- Получение сертификата ---
echo "=== Getting Let's Encrypt certificate ==="
docker run --rm --network host \
-v "$PWD/letsencrypt:/etc/letsencrypt" \
certbot/certbot certonly --standalone \
-d "$DOMAIN" -m "$EMAIL" --agree-tos --non-interactive
# --- Сборка PEM ---
echo "=== Building PEM ==="
cat "letsencrypt/live/$DOMAIN/fullchain.pem" \
"letsencrypt/live/$DOMAIN/privkey.pem" > "certs/$DOMAIN.pem"
# --- Генерация конфига ---
echo "=== Generating HAProxy config ==="
set -a
source .env
set +a
envsubst < haproxy.cfg.tpl > haproxy.cfg
# --- Проверка конфига ---
echo "=== Validating HAProxy config ==="
docker run --rm \
-v "$PWD/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro" \
haproxy:2.9-alpine \
haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg
# --- Запуск ---
echo "=== Starting HAProxy ==="
docker compose up -d
echo "✅ DONE"
echo "Domain: https://$DOMAIN"
🐶 Проверил, есть 4 места, которые надо поправить:
1. `if` сломан, надо `||` между проверками.
2. `docker-compose.yml` сейчас невалидный, отступы нужны.
3. В `haproxy -c` надо примонтировать `certs`, иначе проверка упадёт.
4. Для `bind :443 ssl` лучше `ssl_fc_sni`, а не `req.ssl_sni`.
Вот поправленный вариант:
```bash
#!/usr/bin/env bash
set -euo pipefail
echo "=== SRV1 bootstrap (HAProxy + Let's Encrypt) ==="
read -rp "Domain (example.com): " DOMAIN
read -rp "Email (for Let's Encrypt): " EMAIL
read -rp "SRV2 IP: " SRV2_IP
read -rp "SRV2 SNI: " SRV2_SNI
if [[ -z "$DOMAIN" || -z "$EMAIL" || -z "$SRV2_IP" || -z "$SRV2_SNI" ]]; then
echo "❌ Все поля обязательны"
exit 1
fi
apt update
apt install -y docker.io docker-compose-plugin certbot gettext-base
systemctl enable --now docker
mkdir -p srv1/{certs,letsencrypt}
cd srv1
cat > .env <<EOF
DOMAIN=$DOMAIN
EMAIL=$EMAIL
SRV2_IP=$SRV2_IP
SRV2_SNI=$SRV2_SNI
EOF
cat > docker-compose.yml <<'EOF'
services:
haproxy:
image: haproxy:2.9-alpine
container_name: srv1-haproxy
restart: unless-stopped
ports:
- "443:443"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./certs:/usr/local/etc/haproxy/certs:ro
EOF
cat > haproxy.cfg.tpl <<'EOF'
global
log stdout format raw local0
defaults
log global
mode tcp
option tcplog
timeout connect 5s
timeout client 60s
timeout server 60s
frontend fe_443
bind :443 ssl crt /usr/local/etc/haproxy/certs/${DOMAIN}.pem
mode tcp
acl sni_ok ssl_fc_sni -i ${DOMAIN}
use_backend bk_srv2 if sni_ok
tcp-request content reject if !sni_ok
backend bk_srv2
mode tcp
server srv2 ${SRV2_IP}:443 ssl verify none sni str(${SRV2_SNI})
EOF
docker run --rm --network host \
-v "$PWD/letsencrypt:/etc/letsencrypt" \
certbot/certbot certonly --standalone \
-d "$DOMAIN" -m "$EMAIL" --agree-tos --non-interactive
cat "letsencrypt/live/$DOMAIN/fullchain.pem" \
"letsencrypt/live/$DOMAIN/privkey.pem" > "certs/$DOMAIN.pem"
set -a
source .env
set +a
envsubst < haproxy.cfg.tpl > haproxy.cfg
docker run --rm \
-v "$PWD/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro" \
-v "$PWD/certs:/usr/local/etc/haproxy/certs:ro" \
haproxy:2.9-alpine haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg
docker compose up -d
echo "✅ https://$DOMAIN"
```
Если хочешь, следующим сообщением дам ещё `renew.sh` и `cron` под автообновление сертификата.