mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
Fix build
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!");
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user