mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-07 04:58:44 +02:00
Restrict the ai site resource router to exit node subnet
This commit is contained in:
@@ -4,7 +4,8 @@ import {
|
|||||||
domains,
|
domains,
|
||||||
aiProviders,
|
aiProviders,
|
||||||
resourceAiProviders,
|
resourceAiProviders,
|
||||||
siteResources
|
siteResources,
|
||||||
|
exitNodes
|
||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import {
|
import {
|
||||||
and,
|
and,
|
||||||
@@ -22,6 +23,7 @@ import config from "@server/lib/config";
|
|||||||
import { resources, sites, Target, targets } from "@server/db";
|
import { resources, sites, Target, targets } from "@server/db";
|
||||||
import createPathRewriteMiddleware from "./middleware";
|
import createPathRewriteMiddleware from "./middleware";
|
||||||
import { sanitize, encodePath, validatePathRewriteConfig } from "./utils";
|
import { sanitize, encodePath, validatePathRewriteConfig } from "./utils";
|
||||||
|
import regionalCache from "@server/lib/cache";
|
||||||
|
|
||||||
const redirectHttpsMiddlewareName = "redirect-to-https";
|
const redirectHttpsMiddlewareName = "redirect-to-https";
|
||||||
const badgerMiddlewareName = "badger";
|
const badgerMiddlewareName = "badger";
|
||||||
@@ -55,6 +57,21 @@ export async function getTraefikConfig(
|
|||||||
browserGatewayUiUrl: string | null = null, // UNUSED BUT USED IN PRIVATE
|
browserGatewayUiUrl: string | null = null, // UNUSED BUT USED IN PRIVATE
|
||||||
aiGatewayUrl: string | null = null
|
aiGatewayUrl: string | null = null
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
|
// Get the exit node but cache it for 5 minutes to avoid hitting the DB too often
|
||||||
|
const exitNodeCacheKey = `exitNode:${exitNodeId}`;
|
||||||
|
let exitNode =
|
||||||
|
await regionalCache.get<typeof exitNodes.$inferSelect>(
|
||||||
|
exitNodeCacheKey
|
||||||
|
);
|
||||||
|
if (!exitNode) {
|
||||||
|
[exitNode] = await db
|
||||||
|
.select()
|
||||||
|
.from(exitNodes)
|
||||||
|
.where(eq(exitNodes.exitNodeId, exitNodeId))
|
||||||
|
.limit(1);
|
||||||
|
await regionalCache.set(exitNodeCacheKey, exitNode, 300);
|
||||||
|
}
|
||||||
|
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
const resourcesWithTargetsAndSites = await db
|
const resourcesWithTargetsAndSites = await db
|
||||||
@@ -866,7 +883,7 @@ export async function getTraefikConfig(
|
|||||||
const srKey = `inference-sr${sr.siteResourceId}`;
|
const srKey = `inference-sr${sr.siteResourceId}`;
|
||||||
const routerName = `${srKey}-router`;
|
const routerName = `${srKey}-router`;
|
||||||
const serviceName = `${srKey}-service`;
|
const serviceName = `${srKey}-service`;
|
||||||
const rule = `Host(\`${alias}\`)`;
|
const rule = `Host(\`${alias}\`) && ClientIP(${exitNode.address})`; // restrict to coming from the exit node ip range that the client is connected to
|
||||||
|
|
||||||
const domainParts = alias.split(".");
|
const domainParts = alias.split(".");
|
||||||
const wildCard =
|
const wildCard =
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import {
|
|||||||
getValidCertificatesForDomains
|
getValidCertificatesForDomains
|
||||||
} from "#private/lib/certificates";
|
} from "#private/lib/certificates";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
|
import regionalCache from "#private/lib/cache";
|
||||||
|
|
||||||
const redirectHttpsMiddlewareName = "redirect-to-https";
|
const redirectHttpsMiddlewareName = "redirect-to-https";
|
||||||
const redirectToRootMiddlewareName = "redirect-to-root";
|
const redirectToRootMiddlewareName = "redirect-to-root";
|
||||||
@@ -94,6 +95,21 @@ export async function getTraefikConfig(
|
|||||||
browserGatewayUiUrl: string | null = null,
|
browserGatewayUiUrl: string | null = null,
|
||||||
aiGatewayUrl: string | null = null
|
aiGatewayUrl: string | null = null
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
|
// Get the exit node but cache it for 5 minutes to avoid hitting the DB too often
|
||||||
|
const exitNodeCacheKey = `exitNode:${exitNodeId}`;
|
||||||
|
let exitNode =
|
||||||
|
await regionalCache.get<typeof exitNodes.$inferSelect>(
|
||||||
|
exitNodeCacheKey
|
||||||
|
);
|
||||||
|
if (!exitNode) {
|
||||||
|
[exitNode] = await db
|
||||||
|
.select()
|
||||||
|
.from(exitNodes)
|
||||||
|
.where(eq(exitNodes.exitNodeId, exitNodeId))
|
||||||
|
.limit(1);
|
||||||
|
await regionalCache.set(exitNodeCacheKey, exitNode, 300);
|
||||||
|
}
|
||||||
|
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
const resourcesWithTargetsAndSites = await db
|
const resourcesWithTargetsAndSites = await db
|
||||||
@@ -1546,7 +1562,8 @@ export async function getTraefikConfig(
|
|||||||
// is overridden to a different host than the resource's own. In the
|
// is overridden to a different host than the resource's own. In the
|
||||||
// default case, leave the Host header untouched so it's visible on
|
// default case, leave the Host header untouched so it's visible on
|
||||||
// the other end.
|
// the other end.
|
||||||
const aiGatewayOverride = config.getRawConfig().server.ai_gateway_override;
|
const aiGatewayOverride =
|
||||||
|
config.getRawConfig().server.ai_gateway_override;
|
||||||
|
|
||||||
// Public inference resources: same TLS/cert-resolver handling as
|
// Public inference resources: same TLS/cert-resolver handling as
|
||||||
// plain http-mode resources, but the service points at the AI
|
// plain http-mode resources, but the service points at the AI
|
||||||
@@ -1679,7 +1696,7 @@ export async function getTraefikConfig(
|
|||||||
const srKey = `inference-sr${sr.siteResourceId}`;
|
const srKey = `inference-sr${sr.siteResourceId}`;
|
||||||
const routerName = `${srKey}-router`;
|
const routerName = `${srKey}-router`;
|
||||||
const serviceName = `${srKey}-service`;
|
const serviceName = `${srKey}-service`;
|
||||||
const rule = `Host(\`${alias}\`)`;
|
const rule = `Host(\`${alias}\`) && ClientIP(${exitNode.address})`; // restrict to coming from the exit node ip range that the client is connected to
|
||||||
|
|
||||||
let tls: any = {};
|
let tls: any = {};
|
||||||
if (!privateConfig.getRawPrivateConfig().flags.use_pangolin_dns) {
|
if (!privateConfig.getRawPrivateConfig().flags.use_pangolin_dns) {
|
||||||
|
|||||||
Reference in New Issue
Block a user