Able to connect multi site on olm - POC 1

This commit is contained in:
Owen 2025-04-01 12:49:02 -04:00
parent 96d6ad8142
commit 5ff4215bde
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
5 changed files with 39 additions and 30 deletions

View file

@ -218,6 +218,11 @@ export function isIpInCidr(ip: string, cidr: string): boolean {
} }
export async function getNextAvailableClientSubnet(orgId: string): Promise<string> { export async function getNextAvailableClientSubnet(orgId: string): Promise<string> {
const [org] = await db
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
const existingAddressesSites = await db const existingAddressesSites = await db
.select({ .select({
address: sites.address address: sites.address
@ -233,14 +238,14 @@ export async function getNextAvailableClientSubnet(orgId: string): Promise<strin
.where(and(isNotNull(clients.subnet), eq(clients.orgId, orgId))); .where(and(isNotNull(clients.subnet), eq(clients.orgId, orgId)));
const addresses = [ const addresses = [
...existingAddressesSites.map((site) => site.address), ...existingAddressesSites.map((site) => `${site.address?.split("/")[0]}/32`), // we are overriding the 32 so that we pick individual addresses in the subnet of the org for the site and the client even though they are stored with the /block_size of the org
...existingAddressesClients.map((client) => client.address) ...existingAddressesClients.map((client) => `${client.address.split("/")}/32`)
].filter((address) => address !== null) as string[]; ].filter((address) => address !== null) as string[];
let subnet = findNextAvailableCidr( let subnet = findNextAvailableCidr(
addresses, addresses,
32, 32,
config.getRawConfig().orgs.subnet_group org.subnet
); // pick the sites address in the org ); // pick the sites address in the org
if (!subnet) { if (!subnet) {
throw new Error("No available subnets remaining in space"); throw new Error("No available subnets remaining in space");

View file

@ -51,32 +51,32 @@ export async function getAllRelays(
} }
} }
// get the clients on each site and map them to the site // // get the clients on each site and map them to the site
const sitesAndClients = await Promise.all(sitesRes.map(async (site) => { // const sitesAndClients = await Promise.all(sitesRes.map(async (site) => {
const clientsRes = await db.select().from(clients).where(eq(clients.siteId, site.siteId)); // const clientsRes = await db.select().from(clients).where(eq(clients.siteId, site.siteId));
return { // return {
site, // site,
clients: clientsRes // clients: clientsRes
}; // };
})); // }));
let mappings: { [key: string]: { let mappings: { [key: string]: {
destinationIp: string; destinationIp: string;
destinationPort: number; destinationPort: number;
} } = {}; } } = {};
for (const siteAndClients of sitesAndClients) { // for (const siteAndClients of sitesAndClients) {
const { site, clients } = siteAndClients; // const { site, clients } = siteAndClients;
for (const client of clients) { // for (const client of clients) {
if (!client.endpoint || !site.endpoint || !site.subnet) { // if (!client.endpoint || !site.endpoint || !site.subnet) {
continue; // continue;
} // }
mappings[client.endpoint] = { // mappings[client.endpoint] = {
destinationIp: site.subnet.split("/")[0], // destinationIp: site.subnet.split("/")[0],
destinationPort: parseInt(site.endpoint.split(":")[1]) // destinationPort: parseInt(site.endpoint.split(":")[1])
}; // };
} // }
} // }
return res.status(HttpCode.OK).send({ mappings }); return res.status(HttpCode.OK).send({ mappings });
} catch (error) { } catch (error) {

View file

@ -80,10 +80,10 @@ export async function updateHolePunch(
.where(eq(clients.clientId, olm.clientId)) .where(eq(clients.clientId, olm.clientId))
.returning(); .returning();
[site] = await db // [site] = await db
.select() // .select()
.from(sites) // .from(sites)
.where(eq(sites.siteId, client.siteId)); // .where(eq(sites.siteId, client.siteId));
} else if (newtId) { } else if (newtId) {
const { session, newt: newtSession } = const { session, newt: newtSession } =

View file

@ -6,6 +6,7 @@ import db from "@server/db";
import { clients, clientSites, Newt, Site, sites } from "@server/db/schema"; import { clients, clientSites, Newt, Site, sites } from "@server/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { getNextAvailableClientSubnet } from "@server/lib/ip"; import { getNextAvailableClientSubnet } from "@server/lib/ip";
import config from "@server/lib/config";
const inputSchema = z.object({ const inputSchema = z.object({
publicKey: z.string(), publicKey: z.string(),
@ -58,7 +59,12 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
let site: Site | undefined; let site: Site | undefined;
if (!siteRes.address) { if (!siteRes.address) {
let address = await getNextAvailableClientSubnet(siteRes.orgId); let address = await getNextAvailableClientSubnet(siteRes.orgId);
address = address.split("/")[0]; // get the first part of the CIDR if (!address) {
logger.error("handleGetConfigMessage: No available address");
return;
}
address = `${address.split("/")[0]}/${config.getRawConfig().orgs.block_size}` // we want the block size of the whole org
// create a new exit node // create a new exit node
const [updateRes] = await db const [updateRes] = await db

View file

@ -36,8 +36,6 @@ export default async function ClientsPage(props: ClientsPageProps) {
const clientRows: ClientRow[] = clients.map((client) => { const clientRows: ClientRow[] = clients.map((client) => {
return { return {
name: client.name, name: client.name,
siteName: client.siteName,
siteId: client.siteNiceId,
id: client.clientId, id: client.clientId,
mbIn: formatSize(client.megabytesIn || 0), mbIn: formatSize(client.megabytesIn || 0),
mbOut: formatSize(client.megabytesOut || 0), mbOut: formatSize(client.megabytesOut || 0),