fix(ipsec): учитывать несколько сессий без ложного офлайн
This commit is contained in:
1 parent
cb6ec09312
commit
60b2e099f0
10 files changed
+272
-24
No files matched your search
@@ -248,17 +248,16 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
const shared = selectSharedIke2Identity(state.identities, ike2PeerNames)
|
||||
const sharedRosId = shared?.[".id"] ? String(shared[".id"]) : undefined
|
||||
|
||||
const activeByRemote = new Map<string, RosIpsecActivePeer>()
|
||||
const ambiguousRemoteIds = new Set<string>()
|
||||
const activeByRemote = new Map<string, RosIpsecActivePeer[]>()
|
||||
for (const a of state.active) {
|
||||
if (a.state !== "established") continue
|
||||
const rid = String(a.id ?? a["remote-id"] ?? "").trim()
|
||||
if (rid) {
|
||||
if (activeByRemote.has(rid)) ambiguousRemoteIds.add(rid)
|
||||
else activeByRemote.set(rid, a)
|
||||
const sessions = activeByRemote.get(rid) ?? []
|
||||
sessions.push(a)
|
||||
activeByRemote.set(rid, sessions)
|
||||
}
|
||||
}
|
||||
for (const rid of ambiguousRemoteIds) activeByRemote.delete(rid)
|
||||
|
||||
const subjectCounts = new Map<string, number>()
|
||||
const cnCounts = new Map<string, number>()
|
||||
@@ -286,8 +285,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
}
|
||||
|
||||
const out: IpsecClientDto[] = []
|
||||
const sessionClaims = new Map<RosIpsecActivePeer, IpsecClientDto[]>()
|
||||
const claimSession = (active: RosIpsecActivePeer | undefined) => {
|
||||
const sessionClaims = new Map<RosIpsecActivePeer[], IpsecClientDto[]>()
|
||||
const claimSession = (active: RosIpsecActivePeer[] | undefined) => {
|
||||
if (!active) return
|
||||
const claims = sessionClaims.get(active) ?? []
|
||||
claims.push(out[out.length - 1]!)
|
||||
@@ -316,6 +315,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
const byCommonName = uniqueCn && !subjectCounts.has(cn) ? activeByRemote.get(cn) : undefined
|
||||
const active = bySubject ?? byCommonName
|
||||
?? (identity?.["remote-id"] ? findActive(String(identity["remote-id"]).trim()) : undefined)
|
||||
// Multiple established sessions confirm presence, but no single lease/uptime.
|
||||
const single = active?.length === 1 ? active[0] : undefined
|
||||
out.push({
|
||||
id: `${server.id}:${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`,
|
||||
rosId: `${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`,
|
||||
@@ -333,8 +334,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
modeConfigName: mcName || undefined,
|
||||
peerName: (identity?.peer ?? "").trim() || undefined,
|
||||
online: Boolean(active),
|
||||
activeAddress: active?.["dynamic-address"] || active?.["remote-address"] || active?.address || undefined,
|
||||
activeSince: active?.uptime || active?.established || undefined,
|
||||
activeAddress: single?.["dynamic-address"] || single?.["remote-address"] || single?.address || undefined,
|
||||
activeSince: single?.uptime || single?.established || undefined,
|
||||
disabled: asBool(identity?.disabled),
|
||||
comment: comment || undefined,
|
||||
managed: isUser || isIpsecManagedComment(comment),
|
||||
@@ -352,6 +353,7 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
const mcName = (i["mode-config"] ?? "").trim()
|
||||
const remoteId = (i["remote-id"] ?? "").trim()
|
||||
const active = remoteId ? findActive(remoteId) : undefined
|
||||
const single = active?.length === 1 ? active[0] : undefined
|
||||
out.push({
|
||||
id: `${server.id}:identity:${rosId}`,
|
||||
rosId: `identity:${rosId}`,
|
||||
@@ -365,8 +367,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
|
||||
modeConfigName: mcName || undefined,
|
||||
peerName: (i.peer ?? "").trim() || undefined,
|
||||
online: Boolean(active),
|
||||
activeAddress: active?.["dynamic-address"] || active?.["remote-address"] || active?.address || undefined,
|
||||
activeSince: active?.uptime || active?.established || undefined,
|
||||
activeAddress: single?.["dynamic-address"] || single?.["remote-address"] || single?.address || undefined,
|
||||
activeSince: single?.uptime || single?.established || undefined,
|
||||
disabled: asBool(i.disabled),
|
||||
comment: i.comment || undefined,
|
||||
managed,
|
||||
|
||||
@@ -122,7 +122,11 @@ state.certs = state.certs.filter(c => c[".id"] !== "*AMBIGUOUS")
|
||||
Object.assign(certificate, { organization: "Example, Ltd", unit: "QA+Operations" })
|
||||
state.active[0]!.id = 'C=US, O=Example, Ltd, OU=QA+Operations, CN=QA, Team+VPN="client"\\Lab'
|
||||
state.active.push({ ...state.active[0]!, ".id": "*DUPSESSION", "dynamic-address": "198.18.79.251" })
|
||||
assert.equal(mapClients(state).find(c => c.certName === "client")?.online, false); checks++
|
||||
const multiCertificate = mapClients(state).find(c => c.certName === "client")!
|
||||
assert.equal(multiCertificate.online, true)
|
||||
assert.equal(multiCertificate.activeAddress, undefined)
|
||||
assert.equal(multiCertificate.activeSince, undefined)
|
||||
assert.equal(multiCertificate.sessionAmbiguous, undefined); checks++
|
||||
state.active.pop()
|
||||
Object.assign(certificate, { state: "New York", locality: "Albany" })
|
||||
state.active[0]!.id = 'C=US, S=New York, L=Albany, O=Example, Ltd, OU=QA+Operations, CN=QA, Team+VPN="client"\\Lab'
|
||||
@@ -169,4 +173,28 @@ const uniqueClients = mapClients(aliasesState)
|
||||
assert.equal(uniqueClients.find(c => c.kind === "cert")?.online, true)
|
||||
assert.equal(uniqueClients.find(c => c.kind === "psk")?.online, false)
|
||||
assert(uniqueClients.every(c => !c.sessionAmbiguous)); checks++
|
||||
// Repeated observed IDs are sessions of one principal, not proof of being offline.
|
||||
aliasesState.active.push({ ...aliasesState.active[0]!, ".id": "*SECOND", "dynamic-address": "198.18.113.251", uptime: "2m" })
|
||||
for (const reverse of [false, true]) {
|
||||
if (reverse) aliasesState.active.reverse()
|
||||
const clients = mapClients(aliasesState)
|
||||
const cert = clients.find(c => c.kind === "cert")!
|
||||
assert.equal(cert.online, true)
|
||||
assert.equal(cert.activeAddress, undefined)
|
||||
assert.equal(cert.activeSince, undefined)
|
||||
assert.equal(mapServerSummary(aliasesState, clients).clientsOnline, 1); checks++
|
||||
}
|
||||
aliasesState.identities[1]!["remote-id"] = "key-id:shared.example"
|
||||
assert(mapClients(aliasesState).every(c => c.sessionAmbiguous && !c.online && !c.activeAddress && !c.activeSince)); checks++
|
||||
aliasesState.certs = []
|
||||
aliasesState.identities = [aliasesState.identities[1]!]
|
||||
const multiplePsk = mapClients(aliasesState)[0]!
|
||||
assert.equal(multiplePsk.online, true)
|
||||
assert.equal(multiplePsk.activeAddress, undefined)
|
||||
assert.equal(multiplePsk.activeSince, undefined)
|
||||
assert.equal(multiplePsk.sessionAmbiguous, undefined); checks++
|
||||
aliasesState.active[1]!.state = "dying"
|
||||
assert.equal(mapClients(aliasesState)[0]?.activeAddress, aliasesState.active[0]!["dynamic-address"]); checks++
|
||||
aliasesState.active[0]!.state = "starting"
|
||||
assert.equal(mapClients(aliasesState)[0]?.online, false); checks++
|
||||
console.log(`ipsec-state: ${checks} checks passed`)
|
||||
Reference in new issue
Block a user