Files
han-app/VM2_services/documentation/module-03-nginx-vm2.md
T

146 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# module-03-vm2. Nginx ВМ2 Processing
> Статус: целевая спецификация nginx на ВМ2.
> Канонический контракт (TLS/ACME, request id, internal 404, logs, reload) — [`arch-08-nginx.md`](../../architectory/arch-08-nginx.md).
> Контур ВМ1 — [`module-03-nginx-vm1.md`](../../VM1_app/documentation/module-03-nginx-vm1.md). Guest API, SPA, auth и SMS callback на этой машине не публикуются.
## 1. Назначение и границы
Nginx ВМ2 — самостоятельный ingress Processing:
- public `80/443` на отдельном DNS host: ACME/redirect и два exact CRM webhook;
- private `8443` с сертификатом internal CA: только server-to-server Message Safety и approved ops.
Публичный трафик ВМ2 не проходит через ВМ1. Отказ nginx ВМ1 не прерывает приём CRM webhook. SPA, `/api/`, `/auth/`, WS и Direct SMS callback здесь отсутствуют.
## 2. Routing matrix
### Public `80/443`
| Внешний путь | Upstream | Режим |
|---|---|---|
| exact `/bitrix/sync/webhook/contact` | `bitrix-sync:8080` | public HTTPS Contact event; source IP CIDR/method/body/rate limits, query-token auth в upstream |
| exact `/bitrix/sync/webhook/alert` | `bitrix-sync:8080` | public HTTPS smart-process event; те же ограничения |
До full sync cutover оба exact webhook route закрыты либо возвращают retryable `503`; успешный `2xx ignored` запрещён.
Query не участвует в exact location matching: URL штатного робота `/bitrix/sync/webhook/<type>?token=...&ID=...` попадает в соответствующий exact route.
`/internal/`, `/_internal/`, Redis/OTLP/admin/status/config files на public host → `404`. Fallback на ВМ1 или SPA запрещён. Прочие paths/methods → `404/405`.
### Private `8443`
| Path | Local upstream | Caller |
|---|---|---|
| `/internal/safety/v2/*` | `message-safety-api:8080` | api-backend ВМ1 |
| exact `/internal/safety/status` | `message-safety-api:8080/health/ready` | api-backend ВМ1, ops; capability snapshot, не correctness gate |
| `/internal/sync/v1/*` | `bitrix-sync:8080` | ops/allow-listed service |
Public и private server blocks не имеют общего fallback. Safety status alias доступен только на private listener; public `/health/ready` и `/internal/safety/status` не публикуются.
## 3. Webhook allow-list и preflight
До proxy nginx проверяет непосредственный source IP по version-controlled `BITRIX_WEBHOOK_ALLOWED_CIDRS`; пустой/невалидный список при enabled receiver блокирует deployment. Адрес из недоверенного `X-Forwarded-For` не используется.
`BITRIX_SYNC_ENABLED`, public route, readiness и allow-list согласуются одним
preflight: disabled требует `deny all;`, enabled — reviewed non-empty CIDR и
ready receiver. Обратные комбинации блокируют deployment.
Запрос вне allow-list получает generic `403` без proxy. В безопасном журнале с ограниченным retention сохраняются только timestamp, source IP, route class и outcome; query/body не сохраняются. Telemetry pipeline экспортирует `webhook_rejected_total{receiver,reason="source_ip"}` без IP label. Allow-list не расширяется автоматически: всплеск Contact, восстановленных инкрементальной reconciliation, инициирует проверку rejected-IP журнала, подтверждение принадлежности адреса Битрикс24 и reviewed reload конфигурации.
Bitrix webhook retries имеют отдельный достаточный burst, проходят source IP allow-list и проверяют query receiver token в сервисе.
## 4. Private `8443` fail-closed
До утверждённого Safety cutover active caller allow-list содержит только `deny all;`; после cutover он совпадает с SG/host-firewall источниками ВМ1. Расхождение любого из трёх слоёв (nginx allow-list, SG, host firewall) блокирует rollout.
Private listener доверяет forwarded headers только от allow-listed private caller.
## 5. Listeners и TLS
- `:80` — только ACME challenge и `308 https://$host$request_uri`;
- исключение: `/bitrix/sync/webhook/contact|alert` на HTTP возвращают generic `404/426` **без redirect и отражения query token**;
- `:443` — только ACME-совместимый TLS и exact CRM webhook;
- private `:8443` — internal CA, SAN совпадает с private DNS именем ВМ2;
- public и private сертификаты разные; public key недоступен приложению.
## 6. Timeouts и body limits ВМ2
CRM webhook: connect/send/read `3s / 30s / 60s` (arch-08). Private Safety не короче caller budget. JSON body webhook ограничен; file bytes через этот nginx не идут. Cache на webhook выключен.
## 7. Edge rate limits ВМ2
Отдельные зоны для двух exact webhook (мягкий burst под retries Битрикс24) и `limit_conn`. Зоны guest API/auth/WS/SPA/SMS на ВМ2 не создаются.
Ответ превышения — `429`, `Retry-After`, request id. Generic `403` для wrong source IP — до proxy, не `429`.
## 8. Security headers
Public webhook: не кэшировать, не ослаблять CSP ради SPA (SPA нет). `Server` / `X-Powered-By` скрыты (arch-08). CORS wildcard с credentials запрещён; webhook не требует browser CORS.
## 9. Health и synthetic ВМ2
Внутренний `/nginx-health/live` — arch-08 §8. Synthetic отдельно: HTTP redirect/ACME policy, internal 404 на public host, GET webhook `405/404`, valid отдельный cert, POST webhook allowed/denied source IP без помещения query token в shell history или логи. Private `8443` проверяется с VM1/ops host, не из интернета.
## 10. Layout и Compose ВМ2
Каркас arch-08 §10 плюс:
- отдельный template/server block private `8443`;
- snippet/allow-list `BITRIX_WEBHOOK_ALLOWED_CIDRS`;
- без `websocket.conf` и без `frontend-static`.
Public ports: `${NGINX_HTTP_PORT}:80`, `${NGINX_HTTPS_PORT}:443`. Private `8443` публикуется только в сеть/SG, разрешённую ВМ1 и ops — не как internet listener. Детали портов/SG — arch-03 / arch-06 / [`arch-10-deployment.md`](../../architectory/arch-10-deployment.md).
## 11. Failure behavior ВМ2
Дополнительно к arch-08 §12:
- rollback sync: закрыть public webhook routes либо вернуть retryable `503`; возврат к фиктивному `202 ignored` запрещён;
- ВМ1 при этом не изменяется;
- Safety slow на private `8443`: не маскировать ошибку `2xx`; caller ВМ1 держит poll budget.
## 12. Валидация и тесты ВМ2
Автоматические тесты:
- CRM webhook exact routes принимают query без изменения location matching;
- allowed source IP проксируется, wrong IP получает `403` до upstream;
- HTTP webhook URL с query token не перенаправляется на HTTPS и не отражает query в `Location`/error;
- source-IP rejects попадают в безопасный bounded-retention журнал и low-cardinality telemetry без query/body/IP label;
- disabled/`deny all` и enabled/ready/CIDR preflight: обратные комбинации блокируют deployment;
- public `/internal/safety/*` и `/internal/sync/*``404`;
- private exact `/internal/safety/status` возвращает capability readiness Safety, а соседние неразрешённые health paths → `404`;
- private `8443` до cutover `deny all`, после cutover только источники ВМ1;
- GET webhook `405/404`; прочие paths `404`;
- TLS scan public host и отдельная проверка internal CA на `8443`;
- ACME/redirect rehearsal без остановки приёма (кроме контролируемого окна);
- logs/traces не содержат query token, form body, Authorization.
Acceptance не использует public host ВМ1 и не требует running nginx ВМ1.
## 13. Definition of Done ВМ2
Дополнительно к arch-08 §13:
- независимые public `80/443` и private `8443`;
- routing matrix §2 покрыта;
- CRM webhook достигает ВМ2 напрямую и продолжает приниматься при остановленном nginx ВМ1;
- CRM webhook ограничен version-controlled source IP CIDR allow-list; query token и form body отсутствуют в access/error logs и traces;
- preflight `BITRIX_SYNC_ENABLED` согласован с route/allow-list/readiness;
- private Safety не опубликован на public host.
## 14. TBD ВМ2
- N1: доверенные WAF/LB CIDR перед public host ВМ2, если появятся; до этого allow-list — непосредственный source IP.
- N3: нужен ли публичный health на processing host.
- N6: финальный burst webhook зон.
## 15. Ссылки
- Контракт: [`arch-08-nginx.md`](../../architectory/arch-08-nginx.md).
- ВМ1: [`module-03-nginx-vm1.md`](../../VM1_app/documentation/module-03-nginx-vm1.md).
- Указатель: [`module-03-nginx.md`](module-03-nginx.md).
- Safety / sync / observability: [`module-05-message-safety.md`](module-05-message-safety.md), [`module-07-bitrix-sync.md`](module-07-bitrix-sync.md), [`module-09-observability-vm2.md`](module-09-observability-vm2.md).
- Деплой: [`module-10-deployment-vm2.md`](module-10-deployment-vm2.md).