Fix build

This commit is contained in:
Owen
2026-01-14 17:54:34 -08:00
parent eb0cdda0f9
commit d52bd65d21
7 changed files with 69 additions and 151 deletions

View File

@@ -1,3 +1,10 @@
import { clients, clientSiteResourcesAssociationsCache, clientSitesAssociationsCache, db, ExitNode, resources, Site, siteResources, targetHealthCheck, targets } from "@server/db";
import logger from "@server/logger";
import { initPeerAddHandshake, updatePeer } from "../olm/peers";
import { eq, and } from "drizzle-orm";
import config from "@server/lib/config";
import { generateSubnetProxyTargets, SubnetProxyTarget } from "@server/lib/ip";
export async function buildClientConfigurationForNewtClient( export async function buildClientConfigurationForNewtClient(
site: Site, site: Site,
exitNode?: ExitNode exitNode?: ExitNode

View File

@@ -2,20 +2,10 @@ import { z } from "zod";
import { MessageHandler } from "@server/routers/ws"; import { MessageHandler } from "@server/routers/ws";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { import { db, ExitNode, exitNodes, Newt, sites } from "@server/db";
db,
ExitNode,
exitNodes,
siteResources,
clientSiteResourcesAssociationsCache,
Site
} from "@server/db";
import { clients, clientSitesAssociationsCache, Newt, sites } from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { initPeerAddHandshake, updatePeer } from "../olm/peers";
import { sendToExitNode } from "#dynamic/lib/exitNodes"; import { sendToExitNode } from "#dynamic/lib/exitNodes";
import { generateSubnetProxyTargets, SubnetProxyTarget } from "@server/lib/ip"; import { buildClientConfigurationForNewtClient } from "./buildConfiguration";
import config from "@server/lib/config";
const inputSchema = z.object({ const inputSchema = z.object({
publicKey: z.string(), publicKey: z.string(),
@@ -136,20 +126,13 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
exitNode exitNode
); );
// Build the configuration response
const configResponse = {
ipAddress: site.address,
peers,
targets
};
logger.debug("Sending config: ", configResponse);
return { return {
message: { message: {
type: "newt/wg/receive-config", type: "newt/wg/receive-config",
data: { data: {
...configResponse ipAddress: site.address,
peers,
targets
} }
}, },
broadcast: false, broadcast: false,

View File

@@ -1,4 +1,4 @@
import { db } from "@server/db"; import { db, sites } from "@server/db";
import { disconnectClient } from "#dynamic/routers/ws"; import { disconnectClient } from "#dynamic/routers/ws";
import { getClientConfigVersion, MessageHandler } from "@server/routers/ws"; import { getClientConfigVersion, MessageHandler } from "@server/routers/ws";
import { clients, Newt } from "@server/db"; import { clients, Newt } from "@server/db";
@@ -9,6 +9,7 @@ import { checkOrgAccessPolicy } from "#dynamic/lib/checkOrgAccessPolicy";
import { sendTerminateClient } from "../client/terminate"; import { sendTerminateClient } from "../client/terminate";
import { encodeHexLowerCase } from "@oslojs/encoding"; import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2"; import { sha256 } from "@oslojs/crypto/sha2";
import { sendNewtSyncMessage } from "./sync";
// Track if the offline checker interval is running // Track if the offline checker interval is running
// let offlineCheckerInterval: NodeJS.Timeout | null = null; // let offlineCheckerInterval: NodeJS.Timeout | null = null;
@@ -102,7 +103,26 @@ export const handleNewtPingMessage: MessageHandler = async (context) => {
const newt = c as Newt; const newt = c as Newt;
if (!newt) { if (!newt) {
logger.warn("Newt not found"); logger.warn("Newt ping message: Newt not found");
return;
}
if (!newt.siteId) {
logger.warn("Newt ping message: has no site ID");
return;
}
// get the site
const [site] = await db
.select()
.from(sites)
.where(eq(sites.siteId, newt.siteId))
.limit(1);
if (!site) {
logger.warn(
`Newt ping message: site with ID ${newt.siteId} not found`
);
return; return;
} }
@@ -114,7 +134,7 @@ export const handleNewtPingMessage: MessageHandler = async (context) => {
`Newt ping with outdated config version: ${message.configVersion} (current: ${configVersion})` `Newt ping with outdated config version: ${message.configVersion} (current: ${configVersion})`
); );
// TODO: sync the client await sendNewtSyncMessage(newt, site);
} }
// try { // try {

View File

@@ -18,6 +18,7 @@ import {
} from "#dynamic/lib/exitNodes"; } from "#dynamic/lib/exitNodes";
import { fetchContainers } from "./dockerSocket"; import { fetchContainers } from "./dockerSocket";
import { lockManager } from "#dynamic/lib/lock"; import { lockManager } from "#dynamic/lib/lock";
import { buildTargetConfigurationForNewtClient } from "./buildConfiguration";
export type ExitNodePingResult = { export type ExitNodePingResult = {
exitNodeId: number; exitNodeId: number;
@@ -261,118 +262,6 @@ export const handleNewtRegisterMessage: MessageHandler = async (context) => {
}; };
}; };
export async function buildTargetConfigurationForNewtClient(siteId: number) {
// Get all enabled targets with their resource protocol information
const allTargets = await db
.select({
resourceId: targets.resourceId,
targetId: targets.targetId,
ip: targets.ip,
method: targets.method,
port: targets.port,
internalPort: targets.internalPort,
enabled: targets.enabled,
protocol: resources.protocol,
hcEnabled: targetHealthCheck.hcEnabled,
hcPath: targetHealthCheck.hcPath,
hcScheme: targetHealthCheck.hcScheme,
hcMode: targetHealthCheck.hcMode,
hcHostname: targetHealthCheck.hcHostname,
hcPort: targetHealthCheck.hcPort,
hcInterval: targetHealthCheck.hcInterval,
hcUnhealthyInterval: targetHealthCheck.hcUnhealthyInterval,
hcTimeout: targetHealthCheck.hcTimeout,
hcHeaders: targetHealthCheck.hcHeaders,
hcMethod: targetHealthCheck.hcMethod,
hcTlsServerName: targetHealthCheck.hcTlsServerName
})
.from(targets)
.innerJoin(resources, eq(targets.resourceId, resources.resourceId))
.leftJoin(
targetHealthCheck,
eq(targets.targetId, targetHealthCheck.targetId)
)
.where(and(eq(targets.siteId, siteId), eq(targets.enabled, true)));
const { tcpTargets, udpTargets } = allTargets.reduce(
(acc, target) => {
// Filter out invalid targets
if (!target.internalPort || !target.ip || !target.port) {
return acc;
}
// Format target into string
const formattedTarget = `${target.internalPort}:${target.ip}:${target.port}`;
// Add to the appropriate protocol array
if (target.protocol === "tcp") {
acc.tcpTargets.push(formattedTarget);
} else {
acc.udpTargets.push(formattedTarget);
}
return acc;
},
{ tcpTargets: [] as string[], udpTargets: [] as string[] }
);
const healthCheckTargets = allTargets.map((target) => {
// make sure the stuff is defined
if (
!target.hcPath ||
!target.hcHostname ||
!target.hcPort ||
!target.hcInterval ||
!target.hcMethod
) {
logger.debug(
`Skipping target ${target.targetId} due to missing health check fields`
);
return null; // Skip targets with missing health check fields
}
// parse headers
const hcHeadersParse = target.hcHeaders
? JSON.parse(target.hcHeaders)
: null;
const hcHeadersSend: { [key: string]: string } = {};
if (hcHeadersParse) {
hcHeadersParse.forEach(
(header: { name: string; value: string }) => {
hcHeadersSend[header.name] = header.value;
}
);
}
return {
id: target.targetId,
hcEnabled: target.hcEnabled,
hcPath: target.hcPath,
hcScheme: target.hcScheme,
hcMode: target.hcMode,
hcHostname: target.hcHostname,
hcPort: target.hcPort,
hcInterval: target.hcInterval, // in seconds
hcUnhealthyInterval: target.hcUnhealthyInterval, // in seconds
hcTimeout: target.hcTimeout, // in seconds
hcHeaders: hcHeadersSend,
hcMethod: target.hcMethod,
hcTlsServerName: target.hcTlsServerName
};
});
// Filter out any null values from health check targets
const validHealthCheckTargets = healthCheckTargets.filter(
(target) => target !== null
);
return {
validHealthCheckTargets,
tcpTargets,
udpTargets
};
}
async function getUniqueSubnetForSite( async function getUniqueSubnetForSite(
exitNode: ExitNode, exitNode: ExitNode,
trx: Transaction | typeof db = db trx: Transaction | typeof db = db

View File

@@ -1,22 +1,41 @@
import { Client, Olm } from "@server/db"; import { ExitNode, exitNodes, Newt, Site, db } from "@server/db";
import { buildSiteConfigurationForOlmClient } from "./buildSiteConfigurationForOlmClient"; import { eq } from "drizzle-orm";
import { sendToClient } from "#dynamic/routers/ws"; import { sendToClient } from "#dynamic/routers/ws";
import logger from "@server/logger"; import logger from "@server/logger";
import {
buildClientConfigurationForNewtClient,
buildTargetConfigurationForNewtClient
} from "./buildConfiguration";
export async function sendOlmSyncMessage(olm: Olm, client: Client) { export async function sendNewtSyncMessage(newt: Newt, site: Site) {
// NOTE: WE ARE HARDCODING THE RELAY PARAMETER TO FALSE HERE BUT IN THE REGISTER MESSAGE ITS DEFINED BY THE CLIENT const { tcpTargets, udpTargets, validHealthCheckTargets } =
const siteConfigurations = await buildSiteConfigurationForOlmClient( await buildTargetConfigurationForNewtClient(site.siteId);
client,
client.pubKey, let exitNode: ExitNode | undefined;
false if (site.exitNodeId) {
[exitNode] = await db
.select()
.from(exitNodes)
.where(eq(exitNodes.exitNodeId, site.exitNodeId))
.limit(1);
}
const { peers, targets } = await buildClientConfigurationForNewtClient(
site,
exitNode
); );
await sendToClient(olm.olmId, { await sendToClient(newt.newtId, {
type: "olm/sync", type: "newt/sync",
data: { data: {
sites: siteConfigurations proxyTargets: {
udp: udpTargets,
tcp: tcpTargets
},
healthCheckTargets: validHealthCheckTargets,
peers: peers,
clientTargets: targets
} }
}).catch((error) => { }).catch((error) => {
logger.warn(`Error sending olm sync message:`, error); logger.warn(`Error sending newt sync message:`, error);
}); });
} }

View File

@@ -24,7 +24,7 @@ import { validateSessionToken } from "@server/auth/sessions/app";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { encodeHexLowerCase } from "@oslojs/encoding"; import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2"; import { sha256 } from "@oslojs/crypto/sha2";
import { buildSiteConfigurationForOlmClient } from "./buildSiteConfigurationForOlmClient"; import { buildSiteConfigurationForOlmClient } from "./buildConfiguration";
export const handleOlmRegisterMessage: MessageHandler = async (context) => { export const handleOlmRegisterMessage: MessageHandler = async (context) => {
logger.info("Handling register olm message!"); logger.info("Handling register olm message!");

View File

@@ -1,5 +1,5 @@
import { Client, Olm } from "@server/db"; import { Client, Olm } from "@server/db";
import { buildSiteConfigurationForOlmClient } from "./buildSiteConfigurationForOlmClient"; import { buildSiteConfigurationForOlmClient } from "./buildConfiguration";
import { sendToClient } from "#dynamic/routers/ws"; import { sendToClient } from "#dynamic/routers/ws";
import logger from "@server/logger"; import logger from "@server/logger";