Working on handlers
This commit is contained in:
parent
e112fcba29
commit
b9de0f8e38
5 changed files with 62 additions and 171 deletions
|
@ -16,7 +16,7 @@ export const handleNewtRegisterMessage: MessageHandler = async (context) => {
|
||||||
|
|
||||||
const newt = client;
|
const newt = client;
|
||||||
|
|
||||||
logger.info("Handling register message!");
|
logger.info("Handling register newt message!");
|
||||||
|
|
||||||
if (!newt) {
|
if (!newt) {
|
||||||
logger.warn("Newt not found");
|
logger.warn("Newt not found");
|
||||||
|
|
46
server/routers/newt/peers.ts
Normal file
46
server/routers/newt/peers.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import db from '@server/db';
|
||||||
|
import { newts, sites } from '@server/db/schema';
|
||||||
|
import { eq } from 'drizzle-orm';
|
||||||
|
import { sendToClient } from '../ws';
|
||||||
|
|
||||||
|
export async function addPeer(siteId: number, peer: {
|
||||||
|
publicKey: string;
|
||||||
|
allowedIps: string[];
|
||||||
|
}) {
|
||||||
|
|
||||||
|
const [site] = await db.select().from(sites).where(eq(sites.siteId, siteId)).limit(1);
|
||||||
|
if (!site) {
|
||||||
|
throw new Error(`Exit node with ID ${siteId} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the newt on the site
|
||||||
|
const [newt] = await db.select().from(newts).where(eq(newts.siteId, siteId)).limit(1);
|
||||||
|
if (!newt) {
|
||||||
|
throw new Error(`Newt not found for site ${siteId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendToClient(newt.newtId, {
|
||||||
|
type: 'add_peer',
|
||||||
|
data: peer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deletePeer(siteId: number, publicKey: string) {
|
||||||
|
const [site] = await db.select().from(sites).where(eq(sites.siteId, siteId)).limit(1);
|
||||||
|
if (!site) {
|
||||||
|
throw new Error(`Exit node with ID ${siteId} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the newt on the site
|
||||||
|
const [newt] = await db.select().from(newts).where(eq(newts.siteId, siteId)).limit(1);
|
||||||
|
if (!newt) {
|
||||||
|
throw new Error(`Newt not found for site ${siteId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendToClient(newt.newtId, {
|
||||||
|
type: 'delete_peer',
|
||||||
|
data: {
|
||||||
|
publicKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,147 +0,0 @@
|
||||||
import { z } from "zod";
|
|
||||||
import { MessageHandler } from "../ws";
|
|
||||||
import logger from "@server/logger";
|
|
||||||
import { fromError } from "zod-validation-error";
|
|
||||||
import db from "@server/db";
|
|
||||||
import { olms, Site, sites } from "@server/db/schema";
|
|
||||||
import { eq, isNotNull } from "drizzle-orm";
|
|
||||||
import { findNextAvailableCidr } from "@server/lib/ip";
|
|
||||||
import config from "@server/lib/config";
|
|
||||||
|
|
||||||
const inputSchema = z.object({
|
|
||||||
publicKey: z.string(),
|
|
||||||
endpoint: z.string(),
|
|
||||||
listenPort: z.number()
|
|
||||||
});
|
|
||||||
|
|
||||||
type Input = z.infer<typeof inputSchema>;
|
|
||||||
|
|
||||||
export const handleGetConfigMessage: MessageHandler = async (context) => {
|
|
||||||
const { message, newt, sendToClient } = context;
|
|
||||||
|
|
||||||
logger.debug("Handling Newt get config message!");
|
|
||||||
|
|
||||||
if (!newt) {
|
|
||||||
logger.warn("Newt not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newt.siteId) {
|
|
||||||
logger.warn("Newt has no site!"); // TODO: Maybe we create the site here?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsed = inputSchema.safeParse(message.data);
|
|
||||||
if (!parsed.success) {
|
|
||||||
logger.error(
|
|
||||||
"handleGetConfigMessage: Invalid input: " +
|
|
||||||
fromError(parsed.error).toString()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { publicKey, endpoint, listenPort } = message.data as Input;
|
|
||||||
|
|
||||||
const siteId = newt.siteId;
|
|
||||||
|
|
||||||
const [siteRes] = await db
|
|
||||||
.select()
|
|
||||||
.from(sites)
|
|
||||||
.where(eq(sites.siteId, siteId));
|
|
||||||
|
|
||||||
if (!siteRes) {
|
|
||||||
logger.warn("handleGetConfigMessage: Site not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let site: Site | undefined;
|
|
||||||
if (!site) {
|
|
||||||
const address = await getNextAvailableSubnet();
|
|
||||||
|
|
||||||
// create a new exit node
|
|
||||||
const [updateRes] = await db
|
|
||||||
.update(sites)
|
|
||||||
.set({
|
|
||||||
publicKey,
|
|
||||||
endpoint,
|
|
||||||
address,
|
|
||||||
listenPort
|
|
||||||
})
|
|
||||||
.where(eq(sites.siteId, siteId))
|
|
||||||
.returning();
|
|
||||||
|
|
||||||
site = updateRes;
|
|
||||||
|
|
||||||
logger.info(`Updated site ${siteId} with new WG Newt info`);
|
|
||||||
} else {
|
|
||||||
site = siteRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!site) {
|
|
||||||
logger.error("handleGetConfigMessage: Failed to update site");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientsRes = await db
|
|
||||||
.select()
|
|
||||||
.from(olms)
|
|
||||||
.where(eq(olms.siteId, siteId));
|
|
||||||
|
|
||||||
const peers = await Promise.all(
|
|
||||||
clientsRes.map(async (client) => {
|
|
||||||
return {
|
|
||||||
publicKey: client.pubKey,
|
|
||||||
allowedIps: "0.0.0.0/0"
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const configResponse = {
|
|
||||||
listenPort: site.listenPort, // ?????
|
|
||||||
// ipAddress: exitNode[0].address,
|
|
||||||
peers
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.debug("Sending config: ", configResponse);
|
|
||||||
|
|
||||||
return {
|
|
||||||
message: {
|
|
||||||
type: "olm/wg/connect", // what to make the response type?
|
|
||||||
data: {
|
|
||||||
config: configResponse
|
|
||||||
}
|
|
||||||
},
|
|
||||||
broadcast: false, // Send to all clients
|
|
||||||
excludeSender: false // Include sender in broadcast
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getNextAvailableSubnet(): Promise<string> {
|
|
||||||
const existingAddresses = await db
|
|
||||||
.select({
|
|
||||||
address: sites.address
|
|
||||||
})
|
|
||||||
.from(sites)
|
|
||||||
.where(isNotNull(sites.address));
|
|
||||||
|
|
||||||
const addresses = existingAddresses
|
|
||||||
.map((a) => a.address)
|
|
||||||
.filter((a) => a) as string[];
|
|
||||||
|
|
||||||
let subnet = findNextAvailableCidr(
|
|
||||||
addresses,
|
|
||||||
config.getRawConfig().wg_site.block_size,
|
|
||||||
config.getRawConfig().wg_site.subnet_group
|
|
||||||
);
|
|
||||||
if (!subnet) {
|
|
||||||
throw new Error("No available subnets remaining in space");
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace the last octet with 1
|
|
||||||
subnet =
|
|
||||||
subnet.split(".").slice(0, 3).join(".") +
|
|
||||||
".1" +
|
|
||||||
"/" +
|
|
||||||
subnet.split("/")[1];
|
|
||||||
return subnet;
|
|
||||||
}
|
|
|
@ -1,14 +1,11 @@
|
||||||
import db from "@server/db";
|
import db from "@server/db";
|
||||||
import { MessageHandler } from "../ws";
|
import { MessageHandler } from "../ws";
|
||||||
import {
|
import {
|
||||||
exitNodes,
|
olms,
|
||||||
resources,
|
|
||||||
sites,
|
sites,
|
||||||
Target,
|
|
||||||
targets
|
|
||||||
} from "@server/db/schema";
|
} from "@server/db/schema";
|
||||||
import { eq, and, sql } from "drizzle-orm";
|
import { eq, } from "drizzle-orm";
|
||||||
import { addPeer, deletePeer } from "../gerbil/peers";
|
import { addPeer, deletePeer } from "../newt/peers";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
|
|
||||||
export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
||||||
|
@ -16,7 +13,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
||||||
|
|
||||||
const olm = client;
|
const olm = client;
|
||||||
|
|
||||||
logger.info("Handling register message!");
|
logger.info("Handling register olm message!");
|
||||||
|
|
||||||
if (!olm) {
|
if (!olm) {
|
||||||
logger.warn("Olm not found");
|
logger.warn("Olm not found");
|
||||||
|
@ -42,28 +39,22 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
||||||
.where(eq(sites.siteId, siteId))
|
.where(eq(sites.siteId, siteId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if (!site || !site.exitNodeId) {
|
if (!site) {
|
||||||
logger.warn("Site not found or does not have exit node");
|
logger.warn("Site not found or does not have exit node");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.update(sites)
|
.update(olms)
|
||||||
.set({
|
.set({
|
||||||
pubKey: publicKey
|
pubKey: publicKey
|
||||||
})
|
})
|
||||||
.where(eq(sites.siteId, siteId))
|
.where(eq(olms.olmId, olm.olmId))
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
const [exitNode] = await db
|
if (olm.pubKey && olm.pubKey !== publicKey) {
|
||||||
.select()
|
|
||||||
.from(exitNodes)
|
|
||||||
.where(eq(exitNodes.exitNodeId, site.exitNodeId))
|
|
||||||
.limit(1);
|
|
||||||
|
|
||||||
if (site.pubKey && site.pubKey !== publicKey) {
|
|
||||||
logger.info("Public key mismatch. Deleting old peer...");
|
logger.info("Public key mismatch. Deleting old peer...");
|
||||||
await deletePeer(site.exitNodeId, site.pubKey);
|
await deletePeer(site.siteId, site.pubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!site.subnet) {
|
if (!site.subnet) {
|
||||||
|
@ -72,7 +63,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the peer to the exit node
|
// add the peer to the exit node
|
||||||
await addPeer(site.exitNodeId, {
|
await addPeer(site.siteId, {
|
||||||
publicKey: publicKey,
|
publicKey: publicKey,
|
||||||
allowedIps: [site.subnet]
|
allowedIps: [site.subnet]
|
||||||
});
|
});
|
||||||
|
@ -81,9 +72,9 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
||||||
message: {
|
message: {
|
||||||
type: "olm/wg/connect",
|
type: "olm/wg/connect",
|
||||||
data: {
|
data: {
|
||||||
endpoint: `${exitNode.endpoint}:${exitNode.listenPort}`,
|
endpoint: `${site.endpoint}:${site.listenPort}`,
|
||||||
publicKey: exitNode.publicKey,
|
publicKey: site.publicKey,
|
||||||
serverIP: exitNode.address.split("/")[0],
|
serverIP: site.address!.split("/")[0],
|
||||||
tunnelIP: site.subnet.split("/")[0]
|
tunnelIP: site.subnet.split("/")[0]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export * from "./pickOlmDefaults";
|
export * from "./pickOlmDefaults";
|
||||||
|
export * from "./handleOlmRegisterMessage";
|
Loading…
Add table
Reference in a new issue