Compare commits

...

2 Commits

Author SHA1 Message Date
Owen c9cc9581b1 Add batch update 2026-06-26 23:24:14 -04:00
Owen eac7c67dcc Send down remote subnets 2026-06-26 18:09:56 -04:00
3 changed files with 66 additions and 6 deletions
@@ -13,13 +13,20 @@
import { NextFunction, Request, Response } from "express";
import { z } from "zod";
import { db, remoteExitNodeResources, remoteExitNodes } from "@server/db";
import {
db,
newts,
remoteExitNodeResources,
remoteExitNodes,
sites
} from "@server/db";
import { eq } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { sendToClientsBatch } from "#private/routers/ws";
const paramsSchema = z.strictObject({
orgId: z.string().min(1),
@@ -113,6 +120,25 @@ export async function setRemoteExitNodeResources(
eq(remoteExitNodeResources.remoteExitNodeId, remoteExitNodeId)
);
// Notify all newts connected to this remote exit node's exit node
if (remoteExitNode.exitNodeId) {
const connectedNewts = await db
.select({ newtId: newts.newtId })
.from(newts)
.innerJoin(sites, eq(newts.siteId, sites.siteId))
.where(eq(sites.exitNodeId, remoteExitNode.exitNodeId));
await sendToClientsBatch(
connectedNewts.map(({ newtId }) => ({
clientId: newtId,
message: {
type: "newt/wg/subnets/update",
data: { subnets: destinations }
}
}))
);
}
return response<SetRemoteExitNodeResourcesResponse>(res, {
data: { resources },
success: true,
+18 -2
View File
@@ -5,6 +5,7 @@ import {
db,
ExitNode,
networks,
remoteExitNodeResources,
resources,
Site,
siteNetworks,
@@ -223,7 +224,8 @@ export async function buildClientConfigurationForNewtClient(
export async function buildTargetConfigurationForNewtClient(
siteId: number,
version?: string | null
version?: string | null,
remoteExitNodeId?: string
) {
// Get all enabled targets with their resource mode information
const allTargets = await db
@@ -379,10 +381,24 @@ export async function buildTargetConfigurationForNewtClient(
};
});
let remoteExitNodeSubnets: string[] = [];
if (remoteExitNodeId) {
const remoteNodeResources = await db
.select()
.from(remoteExitNodeResources)
.where(
eq(remoteExitNodeResources.remoteExitNodeId, remoteExitNodeId)
);
// filter through these and provide the subnets
remoteExitNodeSubnets = remoteNodeResources.map((r) => r.destination);
}
return {
validHealthCheckTargets,
tcpTargets,
udpTargets,
browserGatewayTargets
browserGatewayTargets,
remoteExitNodeSubnets
};
}
@@ -1,4 +1,4 @@
import { db, ExitNode, newts, Transaction } from "@server/db";
import { db, ExitNode, newts, remoteExitNodes, Transaction } from "@server/db";
import { MessageHandler } from "@server/routers/ws";
import { exitNodes, Newt, sites } from "@server/db";
import { eq } from "drizzle-orm";
@@ -196,12 +196,29 @@ export const handleNewtRegisterMessage: MessageHandler = async (context) => {
.where(eq(newts.newtId, newt.newtId));
}
let remoteExitNodeId: string | undefined;
if (exitNode.type == "remoteExitNode") {
// get the remote exit node ID associated with this exit node
const [remoteExitNode] = await db
.select()
.from(remoteExitNodes)
.where(eq(remoteExitNodes.exitNodeId, exitNode.exitNodeId))
.limit(1);
remoteExitNodeId = remoteExitNode?.remoteExitNodeId;
}
const {
tcpTargets,
udpTargets,
validHealthCheckTargets,
browserGatewayTargets
} = await buildTargetConfigurationForNewtClient(siteId, newtVersion);
browserGatewayTargets,
remoteExitNodeSubnets
} = await buildTargetConfigurationForNewtClient(
siteId,
newtVersion,
remoteExitNodeId // this is for the remote node resources
);
logger.debug(
`Sending health check targets to newt ${newt.newtId}: ${JSON.stringify(validHealthCheckTargets)}`
@@ -222,6 +239,7 @@ export const handleNewtRegisterMessage: MessageHandler = async (context) => {
},
healthCheckTargets: validHealthCheckTargets,
browserGatewayTargets: browserGatewayTargets,
remoteExitNodeSubnets: remoteExitNodeSubnets,
chainId: chainId
}
},