fix(network): исправить keepalive GRE и каталог IPsec
This commit is contained in:
1 parent
3f3f06f147
commit
727e35f985
28 files changed
+1722
-37
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user