diff --git a/server/lib/ip.ts b/server/lib/ip.ts index e8f589424..bb21d28d6 100644 --- a/server/lib/ip.ts +++ b/server/lib/ip.ts @@ -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(); 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 { 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 { diff --git a/server/routers/olm/buildConfiguration.ts b/server/routers/olm/buildConfiguration.ts index 736363a5f..af309f89a 100644 --- a/server/routers/olm/buildConfiguration.ts +++ b/server/routers/olm/buildConfiguration.ts @@ -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(); + 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(); if (!jitMode && relay) { @@ -234,5 +244,8 @@ export async function buildSiteConfigurationForOlmClient( }); } - return { siteConfigurations, haveInferenceResources }; + return { + siteConfigurations, + exitNodeAliases + }; } diff --git a/server/routers/olm/handleOlmRegisterMessage.ts b/server/routers/olm/handleOlmRegisterMessage.ts index 374c37631..95c5e0d47 100644 --- a/server/routers/olm/handleOlmRegisterMessage.ts +++ b/server/routers/olm/handleOlmRegisterMessage.ts @@ -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]