10 KiB
module-03-vm2. Nginx ВМ2 Processing
Статус: целевая спецификация nginx на ВМ2.
Канонический контракт (TLS/ACME, request id, internal 404, logs, reload) —arch-08-nginx.md.
Контур ВМ1 —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 возвращают generic404/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.
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до cutoverdeny all, после cutover только источники ВМ1; - GET webhook
405/404; прочие paths404; - 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и private8443; - 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. - ВМ1:
module-03-nginx-vm1.md. - Указатель:
module-03-nginx.md. - Safety / sync / observability:
module-05-message-safety.md,module-07-bitrix-sync.md,module-09-observability-vm2.md. - Деплой:
module-10-deployment-vm2.md.