Handle aliases when registering

This commit is contained in:
Owen
2026-07-31 16:21:55 -04:00
parent df7bb2fb57
commit a6b97ea130
3 changed files with 50 additions and 22 deletions
+21 -8
View File
@@ -528,7 +528,10 @@ export function generateRemoteSubnets(
export type Alias = { alias: string | null; aliasAddress: string | null }; export type Alias = { alias: string | null; aliasAddress: string | null };
export function generateAliasConfig(allSiteResources: SiteResource[]): Alias[] { export function generateAliasConfig(
allSiteResources: SiteResource[],
overrideIp?: string
): Alias[] {
return allSiteResources return allSiteResources
.filter( .filter(
(sr) => (sr) =>
@@ -539,7 +542,7 @@ export function generateAliasConfig(allSiteResources: SiteResource[]): Alias[] {
) )
.map((sr) => ({ .map((sr) => ({
alias: sr.alias || sr.fullDomain, alias: sr.alias || sr.fullDomain,
aliasAddress: sr.aliasAddress aliasAddress: overrideIp || sr.aliasAddress
})); }));
} }
@@ -660,9 +663,10 @@ export type CertRef = { id: string; cert: string; key: string };
* certificate (e.g. a wildcard cert used by thousands of site resources) * certificate (e.g. a wildcard cert used by thousands of site resources)
* only need that certificate sent once per sync message. * only need that certificate sent once per sync message.
*/ */
export function dedupeCertsForTargets( export function dedupeCertsForTargets(targetsV2: SubnetProxyTargetV2[]): {
targetsV2: SubnetProxyTargetV2[] targets: SubnetProxyTargetV2[];
): { targets: SubnetProxyTargetV2[]; certs: CertRef[] } { certs: CertRef[];
} {
const idByContent = new Map<string, string>(); const idByContent = new Map<string, string>();
const certs: CertRef[] = []; const certs: CertRef[] = [];
@@ -674,7 +678,10 @@ export function dedupeCertsForTargets(
const contentKey = `${target.tlsCert}|${target.tlsKey}`; const contentKey = `${target.tlsCert}|${target.tlsKey}`;
let id = idByContent.get(contentKey); let id = idByContent.get(contentKey);
if (!id) { if (!id) {
id = createHash("sha1").update(contentKey).digest("hex").slice(0, 16); id = createHash("sha1")
.update(contentKey)
.digest("hex")
.slice(0, 16);
idByContent.set(contentKey, id); idByContent.set(contentKey, id);
certs.push({ id, cert: target.tlsCert, key: target.tlsKey }); certs.push({ id, cert: target.tlsCert, key: target.tlsKey });
} }
@@ -708,7 +715,9 @@ export async function batchFetchCertsForSiteResources(
): Promise<CertByDomain> { ): Promise<CertByDomain> {
const domains = new Set( const domains = new Set(
allSiteResources allSiteResources
.filter((r) => r.enabled && r.mode === "http" && r.ssl && r.fullDomain) .filter(
(r) => r.enabled && r.mode === "http" && r.ssl && r.fullDomain
)
.map((r) => r.fullDomain as string) .map((r) => r.fullDomain as string)
); );
@@ -852,7 +861,11 @@ export async function generateSubnetProxyTargetV2(
new Set([siteResource.fullDomain]), new Set([siteResource.fullDomain]),
true true
); );
if (certs.length > 0 && certs[0].certFile && certs[0].keyFile) { if (
certs.length > 0 &&
certs[0].certFile &&
certs[0].keyFile
) {
tlsCert = certs[0].certFile; tlsCert = certs[0].certFile;
tlsKey = certs[0].keyFile; tlsKey = certs[0].keyFile;
} else { } else {
+22 -9
View File
@@ -19,6 +19,7 @@ import logger from "@server/logger";
import { and, eq, inArray } from "drizzle-orm"; import { and, eq, inArray } from "drizzle-orm";
import { addPeer, deletePeer } from "../newt/peers"; import { addPeer, deletePeer } from "../newt/peers";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { SiR } from "react-icons/si";
export async function buildSiteConfigurationForOlmClient( export async function buildSiteConfigurationForOlmClient(
client: Client, client: Client,
@@ -38,6 +39,8 @@ export async function buildSiteConfigurationForOlmClient(
aliases: Alias[]; aliases: Alias[];
}[] = []; }[] = [];
let exitNodeAliases: string[] = [];
// Get all sites data // Get all sites data
const sitesData = await db const sitesData = await db
.select() .select()
@@ -76,16 +79,12 @@ export async function buildSiteConfigurationForOlmClient(
) )
); );
const haveInferenceResources = allClientSiteResources.some(
(row) => row.siteResource.requiresExitNodeConnection === true
);
if (sitesData.length === 0) {
return { siteConfigurations, haveInferenceResources };
}
const siteResourcesBySiteId = new Map<number, SiteResource[]>(); const siteResourcesBySiteId = new Map<number, SiteResource[]>();
let siteResourcesForExitNode = [];
for (const row of allClientSiteResources) { for (const row of allClientSiteResources) {
if (row.siteResource.requiresExitNodeConnection) {
siteResourcesForExitNode.push(row.siteResource);
}
if (!row.siteId) { if (!row.siteId) {
// because we are doing a leftJoin above to get the inference resources without a network / sites // because we are doing a leftJoin above to get the inference resources without a network / sites
continue; continue;
@@ -98,6 +97,17 @@ export async function buildSiteConfigurationForOlmClient(
} }
} }
exitNodeAliases = siteResourcesForExitNode
.map((sr) => sr.alias)
.filter((a) => a != null);
if (sitesData.length == 0) {
return {
siteConfigurations,
exitNodeAliases
};
}
// Batch-fetch exit nodes for all sites in one query (only needed in relay mode). // Batch-fetch exit nodes for all sites in one query (only needed in relay mode).
const exitNodesById = new Map<number, typeof exitNodes.$inferSelect>(); const exitNodesById = new Map<number, typeof exitNodes.$inferSelect>();
if (!jitMode && relay) { if (!jitMode && relay) {
@@ -234,5 +244,8 @@ export async function buildSiteConfigurationForOlmClient(
}); });
} }
return { siteConfigurations, haveInferenceResources }; return {
siteConfigurations,
exitNodeAliases
};
} }
@@ -462,7 +462,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
// NOTE: its important that the client here is the old client and the public key is the new key // NOTE: its important that the client here is the old client and the public key is the new key
await waitForClientRebuildIdle(olm.clientId); await waitForClientRebuildIdle(olm.clientId);
const { siteConfigurations, haveInferenceResources } = const { siteConfigurations, exitNodeAliases } =
await buildSiteConfigurationForOlmClient( await buildSiteConfigurationForOlmClient(
client, client,
publicKey, publicKey,
@@ -470,6 +470,10 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
jitMode jitMode
); );
logger.info(
`+++++++++++++++++++++++++++++++ ExitNode Aliases: ${exitNodeAliases}`
);
// Return connect message with all site configurations // Return connect message with all site configurations
return { return {
message: { message: {
@@ -481,11 +485,9 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
exitNode: exitNode:
exitNode && client.exitNodeSubnet exitNode && client.exitNodeSubnet
? { ? {
connect: haveInferenceResources, // we do not need to connect to the exit node if we do not have inference resources aliases: exitNodeAliases,
connect: exitNodeAliases.length > 0, // we do not need to connect to the exit node if we do not have inference resources and right now all site resources on the exit node have an alias
endpoint: `${exitNode.endpoint}:${exitNode.listenPort}`, endpoint: `${exitNode.endpoint}:${exitNode.listenPort}`,
relayPort:
config.getRawConfig().gerbil
.clients_start_port,
publicKey: exitNode.publicKey, publicKey: exitNode.publicKey,
serverIP: exitNode.address.split("/")[0], serverIP: exitNode.address.split("/")[0],
tunnelIP: client.exitNodeSubnet.split("/")[0] tunnelIP: client.exitNodeSubnet.split("/")[0]