feat(netflow): локальные GeoLite2-базы для стран и ASN потоков
Docker images / prepare-release (push) Successful in 13s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 4m31s
Docker images / updater-image (push) Successful in 48s
Docker images / backend-image (push) Successful in 3m1s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 15s
Docker images / prepare-release (push) Successful in 13s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 4m31s
Docker images / updater-image (push) Successful in 48s
Docker images / backend-image (push) Successful in 3m1s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 15s
Lookup страны/ASN при ingest теперь идёт сначала по локальным mmdb MaxMind GeoLite2 (Country + ASN, зеркало P3TERX, без ключей), с мгновенным синхронным ответом для IPv4/IPv6; RIPEstat остаётся fallback до первой загрузки баз и при промахе. - backend/src/services/traffic-flow-geoip.ts: ридеры maxmind, фасад resolveFlowIp (geoip-first → RIPE-кэш), статус ридеров - geoip-update-collector.ts: conditional GET по ETag, валидация пробоем 8.8.8.8 (US / AS15169), атомарная подмена с .prev-откатом - джоба планировщика geoip_update (по умолчанию раз в 7 дней), настройки geoip_settings + миграция 0004, API /api/geoip (GET/PUT/update), контракты @mmapp/contracts/geoip - engine/analytics/map-hops переведены на resolveFlowIp - секция «GeoIP-базы» в настройках NetFlow, метки джобы на странице сбора данных, тесты test:geoip
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const geoipSettingsDtoSchema = z.object({
|
||||
enabled: z.boolean(),
|
||||
updateIntervalSec: z.number().int().positive(),
|
||||
lastCheckAt: z.string().nullable(),
|
||||
lastSuccessAt: z.string().nullable(),
|
||||
lastError: z.string().nullable(),
|
||||
countryBuildAt: z.string().nullable(),
|
||||
asnBuildAt: z.string().nullable(),
|
||||
updatedAt: z.string(),
|
||||
})
|
||||
|
||||
export const geoipSettingsPatchSchema = z.object({
|
||||
enabled: z.boolean().optional(),
|
||||
updateIntervalSec: z
|
||||
.number()
|
||||
.int()
|
||||
.min(6 * 3600)
|
||||
.max(30 * 86400)
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export const geoipStatusDtoSchema = z.object({
|
||||
ready: z.boolean(),
|
||||
countryLoaded: z.boolean(),
|
||||
asnLoaded: z.boolean(),
|
||||
countryFile: z.string(),
|
||||
asnFile: z.string(),
|
||||
dir: z.string(),
|
||||
running: z.boolean(),
|
||||
settings: geoipSettingsDtoSchema,
|
||||
})
|
||||
|
||||
export const geoipUpdateSnapshotDtoSchema = z.object({
|
||||
v: z.number(),
|
||||
job: z.literal("geoip_update"),
|
||||
sampledAt: z.string(),
|
||||
skipped: z.boolean().optional(),
|
||||
fatalError: z.string().optional(),
|
||||
checked: z.number().int(),
|
||||
downloaded: z.number().int(),
|
||||
skippedUnchanged: z.number().int(),
|
||||
bytes: z.number().int().nonnegative(),
|
||||
errors: z.array(z.string()),
|
||||
})
|
||||
|
||||
export type GeoipSettingsDto = z.infer<typeof geoipSettingsDtoSchema>
|
||||
export type GeoipSettingsPatch = z.infer<typeof geoipSettingsPatchSchema>
|
||||
export type GeoipStatusDto = z.infer<typeof geoipStatusDtoSchema>
|
||||
export type GeoipUpdateSnapshotDto = z.infer<typeof geoipUpdateSnapshotDtoSchema>
|
||||
@@ -6,3 +6,4 @@ export * from "./backups.js"
|
||||
export * from "./wireguard.js"
|
||||
export * from "./users.js"
|
||||
export * from "./traffic-flow.js"
|
||||
export * from "./geoip.js"
|
||||
|
||||
Reference in New Issue
Block a user