Still working on stability

This commit is contained in:
Owen 2025-04-20 14:25:53 -04:00
parent e2efd0e65a
commit f6a19631dc
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
6 changed files with 128 additions and 86 deletions

View file

@ -10,7 +10,8 @@ import {
olms,
clientSites,
exitNodes,
orgs
orgs,
sites
} from "@server/db/schema";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
@ -115,13 +116,28 @@ export async function createClient(
const updatedSubnet = `${subnet}/${org.subnet.split("/")[1]}`; // we want the block size of the whole org
// make sure the subnet is unique
const subnetExists = await db
const subnetExistsClients = await db
.select()
.from(clients)
.where(eq(clients.subnet, updatedSubnet))
.limit(1);
if (subnetExists.length > 0) {
if (subnetExistsClients.length > 0) {
return next(
createHttpError(
HttpCode.CONFLICT,
`Subnet ${subnet} already exists`
)
);
}
const subnetExistsSites = await db
.select()
.from(sites)
.where(eq(sites.address, updatedSubnet))
.limit(1);
if (subnetExistsSites.length > 0) {
return next(
createHttpError(
HttpCode.CONFLICT,

View file

@ -3,18 +3,9 @@ import { MessageHandler } from "../ws";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import db from "@server/db";
import {
clients,
clientSites,
Newt,
Site,
sites,
olms
} from "@server/db/schema";
import { clients, clientSites, Newt, sites } from "@server/db/schema";
import { eq } from "drizzle-orm";
import { getNextAvailableClientSubnet } from "@server/lib/ip";
import config from "@server/lib/config";
import { addPeer } from "../olm/peers";
import { updatePeer } from "../olm/peers";
const inputSchema = z.object({
publicKey: z.string(),
@ -27,7 +18,7 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
const { message, client, sendToClient } = context;
const newt = client as Newt;
logger.debug(JSON.stringify(message.data));
const now = new Date().getTime() / 1000;
logger.debug("Handling Newt get config message!");
@ -63,6 +54,19 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
logger.warn("handleGetConfigMessage: Site not found");
return;
}
// todo check if the public key has changed
// we need to wait for hole punch success
if (!existingSite.endpoint) {
logger.warn(`Site ${existingSite.siteId} has no endpoint, skipping`);
return;
}
if (existingSite.lastHolePunch && now - existingSite.lastHolePunch > 6) {
logger.warn(
`Site ${existingSite.siteId} last hole punch is too old, skipping`
);
return;
}
// update the endpoint and the public key
const [site] = await db
@ -106,29 +110,30 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
return true;
})
.map(async (client) => {
const peerData = {
publicKey: client.clients.pubKey!,
allowedIps: [client.clients.subnet!],
endpoint: client.clientSites.isRelayed
? ""
: client.clients.endpoint! // if its relayed it should be localhost
};
// Add or update this peer on the olm if it is connected
try {
await addPeer(client.clients.clientId, {
...peerData,
siteId: siteId,
serverIP: site.address,
serverPort: site.listenPort
});
if (site.endpoint && site.publicKey) {
await updatePeer(client.clients.clientId, {
siteId: site.siteId,
endpoint: site.endpoint,
publicKey: site.publicKey,
serverIP: site.address,
serverPort: site.listenPort
});
}
} catch (error) {
logger.error(
`Failed to add/update peer ${client.clients.pubKey} to newt ${newt.newtId}: ${error}`
);
}
return peerData;
return {
publicKey: client.clients.pubKey!,
allowedIps: [client.clients.subnet!],
endpoint: client.clientSites.isRelayed
? ""
: client.clients.endpoint! // if its relayed it should be localhost
};
})
);

View file

@ -1,6 +1,6 @@
import db from "@server/db";
import { MessageHandler } from "../ws";
import { clients, clientSites, Olm, olms, sites } from "@server/db/schema";
import { clients, clientSites, Olm } from "@server/db/schema";
import { eq } from "drizzle-orm";
import { updatePeer } from "../newt/peers";
import logger from "@server/logger";
@ -42,6 +42,13 @@ export const handleOlmRelayMessage: MessageHandler = async (context) => {
const { siteId } = message.data;
await db
.update(clientSites)
.set({
isRelayed: true
})
.where(eq(clientSites.clientId, olm.clientId));
// update the peer on the exit node
await updatePeer(siteId, client.pubKey, {
endpoint: "" // this removes the endpoint

View file

@ -7,7 +7,6 @@ import logger from '@server/logger';
export async function addPeer(clientId: number, peer: {
siteId: number,
publicKey: string;
allowedIps: string[];
endpoint: string;
serverIP: string | null;
serverPort: number | null;
@ -20,8 +19,8 @@ export async function addPeer(clientId: number, peer: {
sendToClient(olm.olmId, {
type: 'olm/wg/peer/add',
data: {
siteId: peer.siteId,
publicKey: peer.publicKey,
allowedIps: peer.allowedIps,
endpoint: peer.endpoint,
serverIP: peer.serverIP,
serverPort: peer.serverPort
@ -47,11 +46,12 @@ export async function deletePeer(clientId: number, publicKey: string) {
logger.info(`Deleted peer ${publicKey} from olm ${olm.olmId}`);
}
export async function updatePeer(clientId: number, publicKey: string, peer: {
allowedIps?: string[];
endpoint?: string;
serverIP?: string;
serverPort?: number;
export async function updatePeer(clientId: number, peer: {
siteId: number,
publicKey: string;
endpoint: string;
serverIP: string | null;
serverPort: number | null;
}) {
const [olm] = await db.select().from(olms).where(eq(olms.clientId, clientId)).limit(1);
if (!olm) {
@ -59,12 +59,15 @@ export async function updatePeer(clientId: number, publicKey: string, peer: {
}
sendToClient(olm.olmId, {
type: 'olm/wg/peer/update',
type: 'olm/wg/peer/update',
data: {
publicKey,
...peer
siteId: peer.siteId,
publicKey: peer.publicKey,
endpoint: peer.endpoint,
serverIP: peer.serverIP,
serverPort: peer.serverPort
}
});
logger.info(`Updated peer ${publicKey} on olm ${olm.olmId}`);
logger.info(`Added peer ${peer.publicKey} to olm ${olm.olmId}`);
}

View file

@ -128,14 +128,16 @@ export async function createSite(
);
}
updatedAddress = `${address}/${org.subnet.split("/")[1]}`; // we want the block size of the whole org
// make sure the subnet is unique
const addressExists = await db
const addressExistsSites = await db
.select()
.from(sites)
.where(eq(sites.address, address))
.where(eq(sites.address, updatedAddress))
.limit(1);
if (addressExists.length > 0) {
if (addressExistsSites.length > 0) {
return next(
createHttpError(
HttpCode.CONFLICT,
@ -144,7 +146,19 @@ export async function createSite(
);
}
updatedAddress = `${address}/${org.subnet.split("/")[1]}`; // we want the block size of the whole org
const addressExistsClients = await db
.select()
.from(sites)
.where(eq(sites.subnet, updatedAddress))
.limit(1);
if (addressExistsClients.length > 0) {
return next(
createHttpError(
HttpCode.CONFLICT,
`Subnet ${subnet} already exists`
)
);
}
}
const niceId = await getUniqueSiteName(orgId);

View file

@ -544,6 +544,42 @@ PersistentKeepalive = 5`;
</FormItem>
)}
/>
<FormField
control={form.control}
name="clientAddress"
render={({ field }) => (
<FormItem>
<FormLabel>
Client Address
</FormLabel>
<FormControl>
<Input
autoComplete="off"
value={
clientAddress
}
onChange={(
e
) => {
setClientAddress(
e.target
.value
);
field.onChange(
e.target
.value
);
}}
/>
</FormControl>
<FormMessage />
<FormDescription>
Specify the IP
address of the host.
</FormDescription>
</FormItem>
)}
/>
</form>
</Form>
</SettingsSectionForm>
@ -662,50 +698,11 @@ PersistentKeepalive = 5`;
</FormItem>
)}
/>
<FormField
control={form.control}
name="clientAddress"
render={({ field }) => (
<FormItem>
<FormLabel>
Client Address
</FormLabel>
<FormControl>
<Input
autoComplete="off"
value={
clientAddress
}
onChange={(
e
) => {
setClientAddress(
e
.target
.value
);
field.onChange(
e
.target
.value
);
}}
/>
</FormControl>
<FormMessage />
<FormDescription>
Specify the IP
address of the
host.
</FormDescription>
</FormItem>
)}
/>
</form>
</Form>
</SettingsSectionBody>
</SettingsSection>
<SettingsSection>
<SettingsSection>
<SettingsSectionHeader>
<SettingsSectionTitle>
Install Newt