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 function generateAliasConfig(allSiteResources: SiteResource[]): Alias[] {
export function generateAliasConfig(
allSiteResources: SiteResource[],
overrideIp?: string
): Alias[] {
return allSiteResources
.filter(
(sr) =>
@@ -539,7 +542,7 @@ export function generateAliasConfig(allSiteResources: SiteResource[]): Alias[] {
)
.map((sr) => ({
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)
* only need that certificate sent once per sync message.
*/
export function dedupeCertsForTargets(
targetsV2: SubnetProxyTargetV2[]
): { targets: SubnetProxyTargetV2[]; certs: CertRef[] } {
export function dedupeCertsForTargets(targetsV2: SubnetProxyTargetV2[]): {
targets: SubnetProxyTargetV2[];
certs: CertRef[];
} {
const idByContent = new Map<string, string>();
const certs: CertRef[] = [];
@@ -674,7 +678,10 @@ export function dedupeCertsForTargets(
const contentKey = `${target.tlsCert}|${target.tlsKey}`;
let id = idByContent.get(contentKey);
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);
certs.push({ id, cert: target.tlsCert, key: target.tlsKey });
}
@@ -708,7 +715,9 @@ export async function batchFetchCertsForSiteResources(
): Promise<CertByDomain> {
const domains = new Set(
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)
);
@@ -852,7 +861,11 @@ export async function generateSubnetProxyTargetV2(
new Set([siteResource.fullDomain]),
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;
tlsKey = certs[0].keyFile;
} else {
+22 -9
View File
@@ -19,6 +19,7 @@ import logger from "@server/logger";
import { and, eq, inArray } from "drizzle-orm";
import { addPeer, deletePeer } from "../newt/peers";
import config from "@server/lib/config";
import { SiR } from "react-icons/si";
export async function buildSiteConfigurationForOlmClient(
client: Client,
@@ -38,6 +39,8 @@ export async function buildSiteConfigurationForOlmClient(
aliases: Alias[];
}[] = [];
let exitNodeAliases: string[] = [];
// Get all sites data
const sitesData = await db
.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[]>();
let siteResourcesForExitNode = [];
for (const row of allClientSiteResources) {
if (row.siteResource.requiresExitNodeConnection) {
siteResourcesForExitNode.push(row.siteResource);
}
if (!row.siteId) {
// because we are doing a leftJoin above to get the inference resources without a network / sites
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).
const exitNodesById = new Map<number, typeof exitNodes.$inferSelect>();
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
await waitForClientRebuildIdle(olm.clientId);
const { siteConfigurations, haveInferenceResources } =
const { siteConfigurations, exitNodeAliases } =
await buildSiteConfigurationForOlmClient(
client,
publicKey,
@@ -470,6 +470,10 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
jitMode
);
logger.info(
`+++++++++++++++++++++++++++++++ ExitNode Aliases: ${exitNodeAliases}`
);
// Return connect message with all site configurations
return {
message: {
@@ -481,11 +485,9 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
exitNode:
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}`,
relayPort:
config.getRawConfig().gerbil
.clients_start_port,
publicKey: exitNode.publicKey,
serverIP: exitNode.address.split("/")[0],
tunnelIP: client.exitNodeSubnet.split("/")[0]