fix(ipsec): обеспечить NAT и изоляцию политик для передачи данных

This commit is contained in:
Denozordec committed 2026-10-09 17:10:33 +07:00
1 parent 43b00e0740
commit 89de7e134b
17 files changed
+571 -25

No files matched your search

+3 -1
View File
@@ -1,6 +1,6 @@
# UX/UI: протокол внешней приёмки 12.5
Статус на2026-10-09: backend ux-ipsec81/frontend ux-ipsec77, backend healthy; основной блок IPsec77 и VXLAN76 приняты в описанных границах. В12.5.67 исправленный Peer .conf принят как клиентский шаблон: API6/6, browser4/4, server endpoint и placeholders; настоящий RSC roundtrip через UI/native/handshake/Ping принят в12.5.68, .conf с явнымName/отказы400/409/сохранение формы приняты в70; поздний native rejection/подтверждённая компенсация/retry приняты в72; изолированный audit INSERT permission denial принят в74; остальные неизвестные исходы/DB faults открыты. Мобильная ширина WireGuard Sheets принята в12.5.64. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. WireGuard handshake/короткий Ping/native API/read-only UI приняты в границах12.5.58; 12.5.59 воспроизвёл оставшиеся peers/IP; 12.5.60 развернул исправление и принял обычное удаление own WG интерфейса с peer/IPv4 адресом на обоих CHR. 12.5.62 принял полный WireGuard UI create/peer/disable/enable/Ping/delete на обоих CHR; устойчивое меню развёрнуто. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). VXLAN75: собственная native пара/Ping/catalog/URL/export приняты, create/delete API отсутствует; selected baseline восстановлен.
Статус на2026-10-09: backend ux-ipsec82c/frontend ux-ipsec77, backend healthy; основной блок IPsec77 и VXLAN76 приняты в описанных границах. В12.5.67 исправленный Peer .conf принят как клиентский шаблон: API6/6, browser4/4, server endpoint и placeholders; настоящий RSC roundtrip через UI/native/handshake/Ping принят в12.5.68, .conf с явнымName/отказы400/409/сохранение формы приняты в70; поздний native rejection/подтверждённая компенсация/retry приняты в72; изолированный audit INSERT permission denial принят в74; остальные неизвестные исходы/DB faults открыты. Мобильная ширина WireGuard Sheets принята в12.5.64. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. WireGuard handshake/короткий Ping/native API/read-only UI приняты в границах12.5.58; 12.5.59 воспроизвёл оставшиеся peers/IP; 12.5.60 развернул исправление и принял обычное удаление own WG интерфейса с peer/IPv4 адресом на обоих CHR. 12.5.62 принял полный WireGuard UI create/peer/disable/enable/Ping/delete на обоих CHR; устойчивое меню развёрнуто. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). VXLAN75: собственная native пара/Ping/catalog/URL/export приняты, create/delete API отсутствует; selected baseline восстановлен.
IPsec78: реальный PSK responder established, mode-config198.18.78.10 и online=true подтверждены API; точные собственные объекты удалены. Сертификатный/DN online, late failure и history restore остаются открытыми. [Отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json), [журнал](ux-ui-progress.md).
@@ -10,6 +10,8 @@ IPsec80: real restore staticIp/disabled, повтор без дубликато
IPsec81: partial/unknown native fault injection, preflight конфликтов, typed Remote ID, удаление старого mode-config и isolated JWT/RBAC приняты. Рабочая авторизация не менялась, физический TCP disconnect не моделировался. [Отчёт](ux-ui/acceptance/ipsec-mutations-2026-10-09.json).
IPsec82: production certificate data plane/NAT Ping3/3, capped UDP3s, history group/egress и API server delete приняты. Baseline14 коллекций×2 восстановлен после route convergence; own/private fixtures удалены. [Отчёт](ux-ui/acceptance/ipsec-network-2026-10-09.json).
## Паспорт стенда
Перед внешним запуском зафиксировать отдельные PostgreSQL и RouterOS тестовые устройства, версии server/client PostgreSQL и RouterOS, HEAD backend/frontend, роли пользователей, число экземпляров backend/планировщика/отправителей и способ их остановки. Для Telegram использовать тестовый чат, для остальных интеграций — тестовые endpoints и учётные записи. Зафиксировать ожидаемые изменения и способ восстановления стенда.
+1 -1
View File
@@ -1,6 +1,6 @@
# План реализации UX/UI по пятичасовым окнам
Актуальное продолжение 2026-10-09: 12.5.81 внедрил исходы partial/unknown/applied, preflight конфликтов и очистку старого mode-config; native/API fault injection и isolated JWT/RBAC приняты. Backend ux-ipsec81 healthy, frontend ux-ipsec77; 7 профильных E2E прошли. Следующий12.5.82 — NAT/связность сертификатного клиента; остальные границы IPsec перечислены ниже. Этап12.5 открыт.
Актуальное продолжение 2026-10-09: 12.5.82 исправил NAT без обязательного WAN, изолировал IPsec policy group и сохранил ограничения NAT/группы в истории. Production API init/client/restore/delete, сертификатный data plane, NAT Ping3/3 и capped bandwidth3s приняты; baseline восстановлен после ожидания динамических маршрутов. Backend ux-ipsec82c healthy, frontend ux-ipsec77. Следующий12.5.83 — BGP/OSPF selected/diagnostic paths: запрет опроса выключенных устройств и достоверность ошибок; затем реальные профильные сценарии маршрутизации. Этап12.5 открыт.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-09. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
+28 -2
View File
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
Актуальное продолжение 2026-10-09: 12.5.81 внедрил исходы partial/unknown/applied, preflight конфликтов и очистку старого mode-config; native/API fault injection и isolated JWT/RBAC приняты. Backend ux-ipsec81 healthy, frontend ux-ipsec77; 7 профильных E2E прошли. Следующий12.5.82 — NAT/связность сертификатного клиента; остальные границы IPsec перечислены ниже. Этап12.5 открыт.
Актуальное продолжение 2026-10-09: 12.5.82 исправил NAT без обязательного WAN, изолировал IPsec policy group и сохранил ограничения NAT/группы в истории. Production API init/client/restore/delete, сертификатный data plane, NAT Ping3/3 и capped bandwidth3s приняты; baseline восстановлен после ожидания динамических маршрутов. Backend ux-ipsec82c healthy, frontend ux-ipsec77. Следующий12.5.83 — BGP/OSPF selected/diagnostic paths: запрет опроса выключенных устройств и достоверность ошибок; затем реальные профильные сценарии маршрутизации. Этап12.5 открыт.
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
@@ -36,7 +36,33 @@
| 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 |
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 |
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–81 и ограничения ниже. Runtime backend ux-ipsec81/frontend ux-ipsec77. |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–82 и ограничения ниже. Runtime backend ux-ipsec82c/frontend ux-ipsec77. |
## 12.5.82 — IPsec: NAT, policy group, реальная передача и полный цикл (2026-10-09)
**Исправления по native доказательствам.** Master NAT ссылался на несуществующий WAN list чистого CHR и получал400 после остальных записей. Теперь до изменений читаются маршруты/interfaces, выбирается единственный egress активных IPv4 defaults main; PPP/direct interface и дубликаты одного egress поддержаны, отсутствие/неоднозначность даёт409 без CA/других записей. Srcnat ограничен VPN-подсетью, конкретным out-interface и ipsec-policy=out,none. Повторный init обновляет одно owned правило; прежнее дополнительное interface-list ограничение не очищается вслепую.
Группа default выбирала несовместимый proposal: phase1 established/lease/online были успешны, data plane Ping0/3 и native log no proposal chosen. Изолированная группа в fixture доказала причину. Master теперь создаёт mmapp-ipsec-vpn, привязывает owned template/listener и новые персональные identities; legacy default/пустая группа owned identities на app peer мигрирует, чужие объекты/default policy сохраняются. Reuse reserved group требует managed template, foreign consumers блокируются до изменений. Delete server удаляет только reserved group со ссылкой managed template и без foreign refs.
**История.** Capture/canonical/body сохраняют policy-template-group и NAT out-interface/out-interface-list/ipsec-policy. Restore проверяет наличие группы и не теряет egress. Старый masquerade snapshot без egress отклоняется409. RouterOS также отклонил пустую out-interface-list как ambiguous: body больше не отправляет пустые ограничения, несовместимое снятие существующего дополнительного фильтра блокируется до записи с инструкцией ручной проверки. PKI/profile/proposal/policy definitions по-прежнему не пересоздаются историей.
| Контроль | Исходная проблема | Подтверждённый результат |
| --- | --- | --- |
| NAT master | WAN отсутствует,400 после partial init | ether1/out,none; repeat init одно правило |
| Data plane | default proposal, Ping0/3 | owned policy group; Ping3/3 в обе стороны |
| Интернет | До группы не проверен | CHR2 assigned198.18.82.250→8.8.8.8 Ping3/3, srcnat=true/seen-reply=true |
| Restore/delete | Пустое interface-list400 | группа/egress/disabled восстановлены; group удалена API, default policy сохранена |
| Cleanup | Преждевременная проверка route IDs | контроль после удаления обоих peer и короткого bounded ожидания: все14 коллекций ×2 совпали |
**Приёмка.** Собственный сертификатный клиент API, PKCS12 import наCHR2; dynamic assigned address применяется RouterOS, отдельный дублирующий IP наCHR2 больше не добавляется. НаCHR1 собственный bridge198.18.82.1/32; отдельные маршруты только между своими IP с pref-src через неизменённые public gateways. Production init/client/GET/restore/DELETE server прошли без ручной модификации группы в финальном сценарии. Capped UDP bandwidth3s,1,000,000bps в каждую сторону: tx-total-average955040/rx970080bps, lost-packets0; encrypted SA byte delta816906. Это smoke передачи, не максимальная пропускная способность/SLA. NAT reply destination194.226.121.150 подтвердил masquerade. [Очищенный отчёт с baseline/recheck](ux-ui/acceptance/ipsec-network-2026-10-09.json).
**Проверки.** test:ipsec: config/80 state checks/history/restore/progress/mutation/NAT/group, entity-snapshots tests, backend TypeScript/ESLint/diff check. Новые HTTP/unit проверки: no-write missing/ambiguous/VRF NAT, shared group inheritance, foreign refs/namespace guard, default group retained, scoped/legacy NAT restore. Исходный unused bool warning сохраняется. Frontend не изменён;7 E2E81 остаются актуальным profile evidence, полная регрессия не повторялась.
**Ошибки тестовой оснастки и очистка.** После ручного proof динамическая policy была ошибочно принята за новый чужой объект; cleanup остановился. Read-only ownership audit подтвердил точные29 собственных ID/атрибутов на двух CHR; они удалены после полного preflight, dynamic policy/assignedIP исчезли с peer, приватные файлы удалены. Receipt теперь пропускает auto policy/address, а статические конфигурации удаляет по точным проверенным ID. Один финальный run имел только transient route mismatch; независимый post-control подтвердил исходные4/5 маршрутов, повторный окончательный run сохранил baseline и recheck: CHR1 initialMatch=false/finalMatch=true, CHR2true/true. Не подменять этот переход утверждением о постоянном изменении ID. Flash/system files,195.195.195.195/32, default routes сохранены; пароли прежние.
**Runtime/происхождение.** Backend mmapp-test/backend:ux-ipsec82c/version1.0.0-test.ipsec82c, image sha256:57fdd7dbbf66091fd0710154ed7c47f284047505977e7b06d0b15bfbfd5fa57d3, healthy; frontend ux-ipsec77. Три builds82/82b/82c по новым подтверждённым отказам: NAT/WAN, proposal group, empty list restore. Финальный context82b +11 backend файлов рабочего состояния, archive d7b0ad10c248ca6c1525266d67b4953f2752f5d046d46b63262e3dc93421e280, label ipsec82c не итоговый Git SHA. Entry/node --check/pg_restore18.6 и compose --wait passed; apt cached. Приватные .env backups, миграций нет. Один локальный коммит без push.
Основной реальный цикл IPsec принят в перечисленных границах. Открыты сложные/экранированные DN, реальные клиентские ОС/IPv6, Portal SSO/browser auth, физические disconnect/durable retry/multi-instance, maximum throughput и полный PKI/policy/profile/proposal restore. Следующий83 — маршрутизация. Референсы интерфейса сохраняются: List9/Sheet8 из общего плана; настройки полей подтверждены [RouterOS IPsec](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec) и [Bandwidth Test](https://help.mikrotik.com/docs/spaces/ROS/pages/7962644/Bandwidth%2BTest).
## 12.5.81 — IPsec: частичные операции, потерянное подтверждение и права (2026-10-09)
+26
View File
@@ -1942,3 +1942,29 @@ flowchart LR
**Очистка и runtime.** До удаления сверены точные ID и ожидаемые имена/comments; свои objects удалены, baseline IDs четырёх коллекций совпали. Один backend build/deploy: mmapp-test/backend:ux-ipsec81/version1.0.0-test.ipsec81, image sha256:2a7d8ab317867f2df4826b7c477659eeba689b7e9d8806676ca030fc4f099abac, healthy; frontend ux-ipsec77. Entry file/node --check/pg_restore18.6 и compose --wait прошли. Runner apt layer #18 CACHED: оптимизация80 подтверждена на изменённом коде/версии. Context ipsec80 + восемь backend-файлов до коммита, archive SHA111eb30a5621eb85e2f7e421a25c22ab70f8073093a83cf0a0f67663163004ec; label ipsec81, не Git SHA. .env backup приватный; миграций нет. Один локальный коммит без push.
Следующий12.5.82: реальная NAT/связность сертификатного клиента. Открыты физические transport disconnect/durable retry, multi-instance, Portal SSO/browser auth, IPv6/клиентские ОС/throughput, сложные DN и полный PKI/policy/profile/proposal restore. Не расширять эти границы по результатам fault injection.
## 12.5.82 — IPsec: NAT, policy group, реальная передача и полный цикл (2026-10-09)
**Исправления по native доказательствам.** Master NAT ссылался на несуществующий WAN list чистого CHR и получал400 после остальных записей. Теперь до изменений читаются маршруты/interfaces, выбирается единственный egress активных IPv4 defaults main; PPP/direct interface и дубликаты одного egress поддержаны, отсутствие/неоднозначность даёт409 без CA/других записей. Srcnat ограничен VPN-подсетью, конкретным out-interface и ipsec-policy=out,none. Повторный init обновляет одно owned правило; прежнее дополнительное interface-list ограничение не очищается вслепую.
Группа default выбирала несовместимый proposal: phase1 established/lease/online были успешны, data plane Ping0/3 и native log no proposal chosen. Изолированная группа в fixture доказала причину. Master теперь создаёт mmapp-ipsec-vpn, привязывает owned template/listener и новые персональные identities; legacy default/пустая группа owned identities на app peer мигрирует, чужие объекты/default policy сохраняются. Reuse reserved group требует managed template, foreign consumers блокируются до изменений. Delete server удаляет только reserved group со ссылкой managed template и без foreign refs.
**История.** Capture/canonical/body сохраняют policy-template-group и NAT out-interface/out-interface-list/ipsec-policy. Restore проверяет наличие группы и не теряет egress. Старый masquerade snapshot без egress отклоняется409. RouterOS также отклонил пустую out-interface-list как ambiguous: body больше не отправляет пустые ограничения, несовместимое снятие существующего дополнительного фильтра блокируется до записи с инструкцией ручной проверки. PKI/profile/proposal/policy definitions по-прежнему не пересоздаются историей.
| Контроль | Исходная проблема | Подтверждённый результат |
| --- | --- | --- |
| NAT master | WAN отсутствует,400 после partial init | ether1/out,none; repeat init одно правило |
| Data plane | default proposal, Ping0/3 | owned policy group; Ping3/3 в обе стороны |
| Интернет | До группы не проверен | CHR2 assigned198.18.82.250→8.8.8.8 Ping3/3, srcnat=true/seen-reply=true |
| Restore/delete | Пустое interface-list400 | группа/egress/disabled восстановлены; group удалена API, default policy сохранена |
| Cleanup | Преждевременная проверка route IDs | контроль после удаления обоих peer и короткого bounded ожидания: все14 коллекций ×2 совпали |
**Приёмка.** Собственный сертификатный клиент API, PKCS12 import наCHR2; dynamic assigned address применяется RouterOS, отдельный дублирующий IP наCHR2 больше не добавляется. НаCHR1 собственный bridge198.18.82.1/32; отдельные маршруты только между своими IP с pref-src через неизменённые public gateways. Production init/client/GET/restore/DELETE server прошли без ручной модификации группы в финальном сценарии. Capped UDP bandwidth3s,1,000,000bps в каждую сторону: tx-total-average955040/rx970080bps, lost-packets0; encrypted SA byte delta816906. Это smoke передачи, не максимальная пропускная способность/SLA. NAT reply destination194.226.121.150 подтвердил masquerade. [Очищенный отчёт с baseline/recheck](ux-ui/acceptance/ipsec-network-2026-10-09.json).
**Проверки.** test:ipsec: config/80 state checks/history/restore/progress/mutation/NAT/group, entity-snapshots tests, backend TypeScript/ESLint/diff check. Новые HTTP/unit проверки: no-write missing/ambiguous/VRF NAT, shared group inheritance, foreign refs/namespace guard, default group retained, scoped/legacy NAT restore. Исходный unused bool warning сохраняется. Frontend не изменён;7 E2E81 остаются актуальным profile evidence, полная регрессия не повторялась.
**Ошибки тестовой оснастки и очистка.** После ручного proof динамическая policy была ошибочно принята за новый чужой объект; cleanup остановился. Read-only ownership audit подтвердил точные29 собственных ID/атрибутов на двух CHR; они удалены после полного preflight, dynamic policy/assignedIP исчезли с peer, приватные файлы удалены. Receipt теперь пропускает auto policy/address, а статические конфигурации удаляет по точным проверенным ID. Один финальный run имел только transient route mismatch; независимый post-control подтвердил исходные4/5 маршрутов, повторный окончательный run сохранил baseline и recheck: CHR1 initialMatch=false/finalMatch=true, CHR2true/true. Не подменять этот переход утверждением о постоянном изменении ID. Flash/system files,195.195.195.195/32, default routes сохранены; пароли прежние.
**Runtime/происхождение.** Backend mmapp-test/backend:ux-ipsec82c/version1.0.0-test.ipsec82c, image sha256:57fdd7dbbf66091fd0710154ed7c47f284047505977e7b06d0b15bfbfd5fa57d3, healthy; frontend ux-ipsec77. Три builds82/82b/82c по новым подтверждённым отказам: NAT/WAN, proposal group, empty list restore. Финальный context82b +11 backend файлов рабочего состояния, archive d7b0ad10c248ca6c1525266d67b4953f2752f5d046d46b63262e3dc93421e280, label ipsec82c не итоговый Git SHA. Entry/node --check/pg_restore18.6 и compose --wait passed; apt cached. Приватные .env backups, миграций нет. Один локальный коммит без push.
Основной реальный цикл IPsec принят в перечисленных границах. Открыты сложные/экранированные DN, реальные клиентские ОС/IPv6, Portal SSO/browser auth, физические disconnect/durable retry/multi-instance, maximum throughput и полный PKI/policy/profile/proposal restore. Следующий83 — маршрутизация. Референсы интерфейса сохраняются: List9/Sheet8 из общего плана; настройки полей подтверждены [RouterOS IPsec](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec) и [Bandwidth Test](https://help.mikrotik.com/docs/spaces/ROS/pages/7962644/Bandwidth%2BTest).
+4 -2
View File
@@ -1,6 +1,6 @@
# Тестовый сервер UX/UI — 2026-10-09
Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-ipsec81/version1.0.0-test.ipsec81, frontend ux-ipsec77/version1.0.0-test.ipsec77; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние.
Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-ipsec82c/version1.0.0-test.ipsec82c, frontend ux-ipsec77/version1.0.0-test.ipsec77; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние.
| Параметр | Проверенное состояние |
| --- | --- |
@@ -14,7 +14,7 @@
| PostgreSQL | postgres:18-alpine,18.6;mmapp-test-postgres healthy;SELECT version() passed |
| Данные | Отдельный Compose project mmapp-test,том mmapp-test_mmapp-pgdata и каталог ./data |
| Доступ | PostgreSQL не публикуется;frontend3000/backend8000 привязаны к127.0.0.1 после запуска |
| Образы приложения | mmapp-test/backend:ux-ipsec81 и mmapp-test/frontend:ux-ipsec77; запущены |
| Образы приложения | mmapp-test/backend:ux-ipsec82c и mmapp-test/frontend:ux-ipsec77; запущены |
Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example).
@@ -26,6 +26,8 @@ IPsec80: real restore staticIp/disabled, повтор без дубликато
IPsec81: partial/unknown native fault injection, preflight конфликтов, typed Remote ID, удаление старого mode-config и isolated JWT/RBAC приняты. Рабочая авторизация не менялась, физический TCP disconnect не моделировался. [Отчёт](ux-ui/acceptance/ipsec-mutations-2026-10-09.json).
IPsec82: production certificate data plane/NAT Ping3/3, capped UDP3s, history group/egress и API server delete приняты. Baseline14 коллекций×2 восстановлен после route convergence; own/private fixtures удалены. [Отчёт](ux-ui/acceptance/ipsec-network-2026-10-09.json).
## Развёртывание приложения
Чистые frontend/backend build contexts подготовлены по .gitea/workflows/docker.yml из закреплённого Git HEAD;образы собраны на сервере без push. Локально docker CLI сейчас отсутствует, на сервере доступен Docker. В корневом .dockerignore исключён backend, поэтому обычный backend build из корня не повторяет CI: использовать отдельный backend context, как main workflow. Не передавать .env.local,backend/.env,ключи и локальные node_modules/.next.
@@ -0,0 +1,336 @@
{
"date": "2026-10-09",
"name": "mm-ipsec82-1791540186150",
"observations": [
{
"serverId": 1,
"active": [
{
".id": "*1",
"id": "CN=mm-ipsec82-1791540186150",
"state": "established",
"dynamic-address": "198.18.82.250",
"remote-address": "104.165.244.7",
"uptime": "0s"
}
],
"catalog": [
{
"name": "mm-ipsec82-1791540186150",
"commonName": "mm-ipsec82-1791540186150",
"staticIp": "198.18.82.250",
"online": true,
"activeAddress": "198.18.82.250",
"activeSince": "0s"
}
]
},
{
"serverId": 2,
"active": [
{
".id": "*1",
"id": "194.226.121.150",
"state": "established",
"remote-address": "194.226.121.150",
"uptime": "0s"
}
],
"catalog": []
}
],
"cleanup": [
{
"serverId": 1,
"/ip/ipsec/identity": true,
"/ip/ipsec/peer": true,
"/ip/ipsec/policy": true,
"/ip/ipsec/policy/group": true,
"/ip/ipsec/mode-config": true,
"/ip/pool": true,
"/ip/ipsec/proposal": true,
"/ip/ipsec/profile": true,
"/certificate": true,
"/file": true,
"/interface/bridge": true,
"/ip/address": true,
"/ip/route": true,
"/ip/firewall/nat": true
},
{
"serverId": 2,
"/ip/ipsec/identity": true,
"/ip/ipsec/peer": true,
"/ip/ipsec/policy": true,
"/ip/ipsec/policy/group": true,
"/ip/ipsec/mode-config": true,
"/ip/pool": true,
"/ip/ipsec/proposal": true,
"/ip/ipsec/profile": true,
"/certificate": true,
"/file": true,
"/interface/bridge": true,
"/ip/address": true,
"/ip/route": true,
"/ip/firewall/nat": true
}
],
"baselineRoutes": [
{
"serverId": 1,
"rows": [
{
".id": "*80000003",
"dst-address": "0.0.0.0/0",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "false"
},
{
".id": "*80000004",
"dst-address": "0.0.0.0/0",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*80000005",
"dst-address": "169.254.169.254/32",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145010",
"dst-address": "194.226.121.0/24",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
}
]
},
{
"serverId": 2,
"rows": [
{
".id": "*80000003",
"dst-address": "0.0.0.0/0",
"gateway": "104.165.244.1",
"routing-table": "main",
"dynamic": "false"
},
{
".id": "*80000005",
"dst-address": "0.0.0.0/0",
"gateway": "104.165.244.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145020",
"dst-address": "104.165.244.0/24",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*80000004",
"dst-address": "169.254.169.254/32",
"gateway": "104.165.244.2",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145010",
"dst-address": "195.195.195.195/32",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
}
]
}
],
"natRule": {
"outInterface": "ether1",
"ipsecPolicy": "out,none",
"noWanListRequired": true,
"repeatInitOneRule": true
},
"expectedAddress": "198.18.82.250",
"staticLeaseCorrect": true,
"catalogCorrect": true,
"pings": [
{
"serverId": 2,
"address": "198.18.82.1",
"source": "198.18.82.250",
"received": 3,
"sent": 3
},
{
"serverId": 1,
"address": "198.18.82.250",
"source": "198.18.82.1",
"received": 3,
"sent": 3
},
{
"serverId": 2,
"address": "8.8.8.8",
"source": "198.18.82.250",
"received": 3,
"sent": 3
}
],
"natEvidence": [
{
"src-address": "198.18.82.250",
"dst-address": "8.8.8.8",
"reply-src-address": "8.8.8.8",
"reply-dst-address": "194.226.121.150",
"srcnat": "true",
"seen-reply": "true"
}
],
"bandwidth": {
"durationSec": 3,
"capBitsPerSecondPerDirection": 1000000,
"protocol": "udp",
"source": "assigned client via own pref-src route",
"rows": [
{
"status": "connecting",
"tx-current": "0",
"rx-current": "0",
"tx-total-average": "0",
"rx-total-average": "0",
"lost-packets": "0"
},
{
"status": "running",
"duration": "0s",
"tx-current": "0",
"rx-current": "0",
"tx-total-average": "0",
"rx-total-average": "0",
"lost-packets": "0"
},
{
"status": "running",
"duration": "1s",
"tx-current": "913680",
"rx-current": "970080",
"tx-total-average": "913680",
"rx-total-average": "970080",
"lost-packets": "0"
},
{
"status": "running",
"duration": "2s",
"tx-current": "981360",
"rx-current": "970080",
"tx-total-average": "947520",
"rx-total-average": "970080",
"lost-packets": "0"
},
{
"status": "done testing",
"duration": "3s",
"tx-current": "970080",
"rx-current": "970080",
"tx-total-average": "955040",
"rx-total-average": "970080",
"lost-packets": "0"
}
]
},
"encryptedByteDelta": 816906,
"historyRestore": {
"groupsPreserved": true,
"natEgressPreserved": true,
"clientEnabled": true
},
"serverDelete": {
"ownedGroupRemoved": true,
"defaultPolicyPreserved": true
},
"routeRecheck": [
{
"serverId": 1,
"initialMatch": false,
"finalMatch": true,
"rows": [
{
".id": "*80000003",
"dst-address": "0.0.0.0/0",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "false"
},
{
".id": "*80000004",
"dst-address": "0.0.0.0/0",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*80000005",
"dst-address": "169.254.169.254/32",
"gateway": "194.226.121.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145010",
"dst-address": "194.226.121.0/24",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
}
]
},
{
"serverId": 2,
"initialMatch": true,
"finalMatch": true,
"rows": [
{
".id": "*80000003",
"dst-address": "0.0.0.0/0",
"gateway": "104.165.244.1",
"routing-table": "main",
"dynamic": "false"
},
{
".id": "*80000005",
"dst-address": "0.0.0.0/0",
"gateway": "104.165.244.1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145020",
"dst-address": "104.165.244.0/24",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*80000004",
"dst-address": "169.254.169.254/32",
"gateway": "104.165.244.2",
"routing-table": "main",
"dynamic": "true"
},
{
".id": "*20145010",
"dst-address": "195.195.195.195/32",
"gateway": "ether1",
"routing-table": "main",
"dynamic": "true"
}
]
}
]
}