- Added support for managing IPsec peers, including editing and deleting functionality. - Introduced a new UI component for displaying peers and their details within the IPsec server grid. - Updated the IPsec user creation form to allow binding identities to specific peers. - Enhanced backend routes and services to handle peer patching and deletion requests. - Improved data structures to accommodate multiple peers and certificates for each server. - Added tests to ensure proper functionality of new peer management features.
7.4 KiB
IKEv2/IPsec VPN: клиенты, IP-адреса и сертификаты — по образцу WireGuard
Архитектура (как у WireGuard)
Роутер — источник истины: live-чтение через существующий REST-клиент (mikrotik.ts), мутации прямыми REST-вызовами, история через config_revisions (новая секция "ipsec"; section — TEXT без CHECK → SQL-миграция не нужна). Новых таблиц нет. Объекты, созданные мастером/при создании клиентов, помечаются managed-комментарием mm-ipsec (по образцу managed-markers).
Модель RouterOS (что создаём/читаем)
Мастер инициализации сервера (per router): CA-сертификат (/certificate add + sign, key-usage=key-cert-sign,crl-sign), серверный сертификат (CN=адрес/домен, SAN, tls-server), /ip/ipsec/peer (passive, exchange-mode=ike2, certificate=серверный cert), /ip/ipsec/profile+proposal (aes-256/sha256/modp2048, pfs), /ip pool + /ip/ipsec/mode-config «VPN» (address-pool, dns), policy-template, и опциональное (default on, чекбокс) managed srcnat masquerade-правило «интернет клиентам».
Клиент = /ip/ipsec/identity: Сертификат (/certificate add CN=<имя> → sign ca= → export-certificate type=pkcs12 → файл .p12 скачивается с роутера → identity match-by=certificate) или PSK (auth-method=pre-shared-key, remote-id+secret). IP: «из пула» (общий mode-config) или статический (персональный mc-<user> mode-config с address=x.x.x.x/32). Онлайн — /ip/ipsec/active-peers.
Клиентские загрузки: .p12 (cert+key+CA, passphrase) + strongSwan .sswan (генерация на бэкенде) + текстовая инструкция. Перекачка .p12 — повторный export с новой passphrase (ключ остаётся на роутере).
Бэкенд
mikrotik.ts:downloadFile(name): Promise<Buffer>— бинарно-безопасный GET/rest/file/<name>(с fallbackflash/<name>, как уuploadTextFile; текущий конвейер парсит JSON как utf8 — нужен Buffer-режим); хелперыsignCertificate(с поллингом готовности, sign небыстрый),exportCertificatePkcs12(name, passphrase).services/ipsec-config.ts(чистые, тестируемые): генератор.sswanи инструкции, поиск свободного IP в пуле, naming-конвенции (ipsec-ca,ipsec-server,mc-<user>,ipsec-user-<name>).services/ipsec-ca.ts:ensureCa/ensureServerCert/issueClientCert/exportClientP12— add → sign (poll) → export → download.services/ipsec-ros.ts: put/patch/delete для/ip/ipsec/{peer,identity,mode-config,profile,proposal,policy},/ip/pool, NAT managed-правило.services/ipsec-live.ts:fetchIpsecState(server)— параллельные GET peer/identity/mode-config/pool/active-peers/certificate (+какие из них наши по маркеру/имени) → DTO;listIpsec()fan-out с failures;countIpsecClients()для сайдбара.entity-snapshots.ts:canonicalIpsecSnapshot/parseIpsecSnapshot/planIpsecRestore(секреты черезisHiddenSecret);CONFIG_SECTIONS+="ipsec"; enum вschema.ts(миграции нет).routes/ipsec.ts:GET /ipsec(+observed revision),POST /ipsec/server/init,DELETE /ipsec/server/:serverId(только managed-объекты),POST /ipsec/users(ответ включает одноразовый p12 base64),PATCH /ipsec/users/:serverId/:rosId(имя/статический IP/psk),DELETE /ipsec/users/...(identity + mc + опционально клиентский cert),POST /ipsec/users/:serverId/:rosId/cert(перекачка p12),GET /ipsec/revisions+POST /ipsec/revisions/:id/restore— всё по образцуroutes/wireguard.ts(captureAndAppendRevision). Регистрация вindex.ts;/api/ipsecв обе группы network-правилpermissions.ts.- Модуль Пользователи:
InterfaceType+="ipsec"(iface-type.ts, schema.ts enum — TEXT, без миграции); каталог интерфейсов дополняется IPsec-клиентами (identity name + CN в peerPublicKey/peerName) — привязка app-пользователя к VPN-клиенту.
Контракт
packages/contracts/src/ipsec.ts (+package.json exports, index.ts): ipsecPeerDto/identityDto/modeConfigDto/poolDto/activePeerDto/certInfoDto/serverSummaryDto, list-response с failures, initRequest (CN/SAN, пул, DNS, NAT-чекбокс), userCreateRequest (имя, auth: certificate|psk, psk?, ip: static|pool, passphrase, daysValid), certDownloadResponse {filename, contentB64, mime}.
Фронт
app/(main)/ipsec/page.tsx — «одно окно» по образцу WG-страницы: ServerRail + KPI (серверы IKEv2 / клиенты / онлайн / CA) + Tabs «Клиенты» (grid: имя, сервер, аутентификация, IP, онлайн, действия — скачать .p12/.sswan, изменить, удалить; Sheet создания клиента), «Сервер» (peer/pool/mode-config/certs + мастер инициализации Stepper + статус NAT-правила), «CLI» (шпаргалка). История/restore — ConfigHistorySheet. Компоненты components/ipsec/* на существующих DataGridShell/form-kit/Sheet; скачивание бинарного p12 — Blob из base64 (по образцу downloadText), .sswan/инструкция — через CodeExportSheet. Сайдбар «IPsec / IKEv2» в «Управление» + бейдж (sidebar-counts.ts + mock в sidebar-badges.ts) + command-palette. Mock-данные в lib/data.ts для демо-режима.
Тесты и проверка
ipsec-config.test.ts(чистые функции: sswan, свободный IP, naming);entity-snapshots.test.ts—planIpsecRestore+opsTouchOnly(["/ip/ipsec", ...]).npm run build -w @mmapp/contracts;tscbackend/root;npm --prefix backend run test:config-sync && test:wireguard+ новые; eslint без новых ошибок.- Демо-режим: визуальная проверка страницы в браузере (как в прошлый раз).
Риски (проверить на живом роутере при внедрении)
- REST-скачивание файла
GET /rest/file/<name>— еслиRouterOS отдаёт только метаданные, fallback: чтениеcontentsмаленьких PEM-файлов или сборка p12 из PEM-частей. - Точные имена полей mode-config (
addressvsaddress-pool) сверить с живым GET и адаптировать. /certificate/sign— поллинг готовности с таймаутом ~30–60 с.
Объём большой; коммит/пуш — по готовности, отдельным feat(ipsec): ….