fix(network): исправить keepalive GRE и каталог IPsec

This commit is contained in:
Denozordec committed 2026-10-13 21:15:49 +07:00
1 parent 3f3f06f147
commit 727e35f985
28 files changed
+1722 -37

No files matched your search

+1 -11
View File
@@ -5,6 +5,7 @@ import { db } from "../db/index.js"
import { filterRules, recursiveRoutes, servers } from "../db/schema.js"
import { MikrotikClient } from "../services/mikrotik.js"
import { pollGreCatalog } from "../services/gre-catalog-poll.js"
import { parseKeepalive } from "../services/gre-live.js"
import { parseDbServerId } from "../utils/server-id.js"
import { appendEvent } from "../modules/events/service/events-service.js"
import { managedComment } from "../managed-markers.js"
@@ -74,17 +75,6 @@ interface ApiFilterRule {
description: string
}
function parseKeepalive(value: string | undefined): { interval: number; retries: number } {
if (!value || value.toLowerCase() === "none") return { interval: 0, retries: 0 }
const [intervalRaw, retriesRaw] = value.split(",")
const interval = Number.parseInt((intervalRaw ?? "").trim(), 10)
const retries = Number.parseInt((retriesRaw ?? "").trim(), 10)
return {
interval: Number.isFinite(interval) ? interval : 0,
retries: Number.isFinite(retries) ? retries : 0,
}
}
function parseDscp(value: string | undefined): "inherit" | number {
if (!value || value === "inherit") return "inherit"
const n = Number.parseInt(value, 10)
+8 -6
View File
@@ -43,8 +43,8 @@ const TunnelWriteSchema = z.object({
comment: z.string().optional(),
enabled: z.boolean().optional(),
mtu: z.number().optional(),
keepaliveInterval: z.number().optional(),
keepaliveRetries: z.number().optional(),
keepaliveInterval: z.number().int().min(1).max(4294967295).optional(),
keepaliveRetries: z.number().int().min(1).max(4294967295).optional(),
dscp: z.union([z.literal("inherit"), z.number(), z.string()]).optional(),
clampTcpMss: z.boolean().optional(),
allowFastPath: z.boolean().optional(),
@@ -84,9 +84,7 @@ function tunnelFromBody(body: z.infer<typeof TunnelWriteSchema> & { keepaliveInt
: typeof body.dscp === "number"
? String(body.dscp)
: body.dscp
const keepalive = body.keepaliveInterval === undefined && body.keepaliveRetries === undefined
? undefined
: formatKeepalive(body.keepaliveInterval ?? 0, body.keepaliveRetries ?? 10)
const keepalive = formatKeepalive(body.keepaliveInterval ?? 10, body.keepaliveRetries ?? 10)
return canonicalGreSnapshot({
tunnels: [{
name: body.name,
@@ -97,7 +95,7 @@ function tunnelFromBody(body: z.infer<typeof TunnelWriteSchema> & { keepaliveInt
comment: body.remoteInnerIp === undefined ? body.comment ?? "" : writeGreComment(body.comment ?? "", body.remoteInnerIp),
disabled: body.enabled === false,
mtu: body.mtu ?? 1476,
keepalive: keepalive ?? "0",
keepalive,
dscp,
clampTcpMss: body.clampTcpMss,
allowFastPath: body.allowFastPath,
@@ -173,6 +171,10 @@ const greRoutes: FastifyPluginAsyncZod = async (app) => {
allowFastPath: body.allowFastPath ?? live.allowFastPath,
ipsecSecret: body.ipsecSecret ?? live.ipsecSecret,
})
// A patch to another field must not reformat an observed native timer.
if (body.keepaliveInterval === undefined && body.keepaliveRetries === undefined) {
merged.keepalive = original.keepalive
}
merged.innerAddresses = original.innerAddresses?.map(a => ({ ...a }))
if (body.localInnerIp !== undefined && body.localInnerIp !== original.localInnerIp) {
merged.innerAddresses = (merged.innerAddresses ?? []).filter(a => a.address !== original.localInnerIp)
@@ -0,0 +1,9 @@
import assert from "node:assert/strict"
import { parseKeepalive } from "./gre-live.js"
for (const [native, seconds] of [["1m,3", 60], ["1m30s,3", 90], ["00:01:00,3", 60], ["1h2m3s,3", 3723], ["10s,3", 10], ["10,3", 10]] as const) {
assert.deepEqual(parseKeepalive(native), { interval: seconds, retries: 3 })
}
assert.deepEqual(parseKeepalive("invalid,3"), { interval: 0, retries: 3 })
assert.deepEqual(parseKeepalive("10s,3garbage"), { interval: 10, retries: 0 })
console.log("GRE keepalive: native units and clock parsed without prefix truncation")
+8 -4
View File
@@ -3,6 +3,7 @@ import { db } from "../db/index.js"
import { servers } from "../db/schema.js"
import { MikrotikClient } from "./mikrotik.js"
import { readGreComment } from "./gre-comment.js"
import { observedDurationMs, observedInteger } from "./ospf-observed-values.js"
import {
canonicalGreSnapshot,
greAddressPath,
@@ -69,11 +70,14 @@ export interface LiveGreTunnel {
export function parseKeepalive(value: string | undefined): { interval: number; retries: number } {
if (!value || value.toLowerCase() === "none") return { interval: 0, retries: 0 }
const [intervalRaw, retriesRaw] = value.split(",")
const interval = Number.parseInt((intervalRaw ?? "").trim(), 10)
const retries = Number.parseInt((retriesRaw ?? "").trim(), 10)
const intervalText = intervalRaw?.trim()
const interval = intervalText && /^\d+$/.test(intervalText)
? observedInteger(intervalText)
: (observedDurationMs(intervalText) ?? 0) / 1000
const retries = observedInteger(retriesRaw)
return {
interval: Number.isFinite(interval) ? interval : 0,
retries: Number.isFinite(retries) ? retries : 0,
interval: interval ?? 0,
retries: retries ?? 0,
}
}