Merge branch 'feat/add-proxy-protocol-support' into dev

This commit is contained in:
Owen
2025-10-26 18:16:38 -07:00
11 changed files with 218 additions and 40 deletions

View File

@@ -116,7 +116,9 @@ export const resources = pgTable("resources", {
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
onDelete: "cascade"
}),
headers: text("headers") // comma-separated list of headers to add to the request
headers: text("headers"), // comma-separated list of headers to add to the request
proxyProtocol: boolean("proxyProtocol").notNull().default(false),
proxyProtocolVersion: integer("proxyProtocolVersion").default(1)
});
export const targets = pgTable("targets", {

View File

@@ -128,7 +128,10 @@ export const resources = sqliteTable("resources", {
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
onDelete: "cascade"
}),
headers: text("headers") // comma-separated list of headers to add to the request
headers: text("headers"), // comma-separated list of headers to add to the request
proxyProtocol: integer("proxyProtocol", { mode: "boolean" }).notNull().default(false),
proxyProtocolVersion: integer("proxyProtocolVersion").default(1)
});
export const targets = sqliteTable("targets", {

View File

@@ -309,10 +309,7 @@ export class TraefikConfigManager {
this.lastActiveDomains = new Set(domains);
}
if (
process.env.USE_PANGOLIN_DNS === "true" &&
build != "oss"
) {
if (process.env.USE_PANGOLIN_DNS === "true" && build != "oss") {
// Scan current local certificate state
this.lastLocalCertificateState =
await this.scanLocalCertificateState();
@@ -450,7 +447,8 @@ export class TraefikConfigManager {
currentExitNode,
config.getRawConfig().traefik.site_types,
build == "oss", // filter out the namespace domains in open source
build != "oss" // generate the login pages on the cloud and hybrid
build != "oss", // generate the login pages on the cloud and hybrid,
build == "saas" ? false : config.getRawConfig().traefik.allow_raw_resources // dont allow raw resources on saas otherwise use config
);
const domains = new Set<string>();
@@ -502,6 +500,25 @@ export class TraefikConfigManager {
};
}
// tcp:
// serversTransports:
// pp-transport-v1:
// proxyProtocol:
// version: 1
// pp-transport-v2:
// proxyProtocol:
// version: 2
if (build != "saas") {
// add the serversTransports section if not present
if (traefikConfig.tcp && !traefikConfig.tcp.serversTransports) {
traefikConfig.tcp.serversTransports = {
"pp-transport-v1": { proxyProtocol: { version: 1 } },
"pp-transport-v2": { proxyProtocol: { version: 2 } }
};
}
}
return { domains, traefikConfig };
} catch (error) {
// pull data out of the axios error to log

View File

@@ -23,7 +23,8 @@ export async function getTraefikConfig(
exitNodeId: number,
siteTypes: string[],
filterOutNamespaceDomains = false,
generateLoginPageRouters = false
generateLoginPageRouters = false,
allowRawResources = true
): Promise<any> {
// Define extended target type with site information
type TargetWithSite = Target & {
@@ -56,6 +57,8 @@ export async function getTraefikConfig(
setHostHeader: resources.setHostHeader,
enableProxy: resources.enableProxy,
headers: resources.headers,
proxyProtocol: resources.proxyProtocol,
proxyProtocolVersion: resources.proxyProtocolVersion,
// Target fields
targetId: targets.targetId,
targetEnabled: targets.enabled,
@@ -104,7 +107,7 @@ export async function getTraefikConfig(
isNull(targetHealthCheck.hcHealth) // Include targets with no health check record
),
inArray(sites.type, siteTypes),
config.getRawConfig().traefik.allow_raw_resources
allowRawResources
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
: eq(resources.http, true)
)
@@ -167,6 +170,8 @@ export async function getTraefikConfig(
enableProxy: row.enableProxy,
targets: [],
headers: row.headers,
proxyProtocol: row.proxyProtocol,
proxyProtocolVersion: row.proxyProtocolVersion ?? 1,
path: row.path, // the targets will all have the same path
pathMatchType: row.pathMatchType, // the targets will all have the same pathMatchType
rewritePath: row.rewritePath,
@@ -635,6 +640,11 @@ export async function getTraefikConfig(
}
});
})(),
...(resource.proxyProtocol && protocol == "tcp"
? {
serversTransport: `pp-transport-v${resource.proxyProtocolVersion || 1}`
}
: {}),
...(resource.stickySession
? {
sticky: {

View File

@@ -51,7 +51,8 @@ export async function getTraefikConfig(
exitNodeId: number,
siteTypes: string[],
filterOutNamespaceDomains = false,
generateLoginPageRouters = false
generateLoginPageRouters = false,
allowRawResources = true
): Promise<any> {
// Define extended target type with site information
type TargetWithSite = Target & {
@@ -141,7 +142,7 @@ export async function getTraefikConfig(
isNull(targetHealthCheck.hcHealth) // Include targets with no health check record
),
inArray(sites.type, siteTypes),
config.getRawConfig().traefik.allow_raw_resources
allowRawResources
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
: eq(resources.http, true)
)
@@ -709,6 +710,11 @@ export async function getTraefikConfig(
}
});
})(),
...(resource.proxyProtocol && protocol == "tcp" // proxy protocol only works for tcp
? {
serversTransport: `pp-transport-v${resource.proxyProtocolVersion || 1}`
}
: {}),
...(resource.stickySession
? {
sticky: {

View File

@@ -270,7 +270,8 @@ hybridRouter.get(
remoteExitNode.exitNodeId,
["newt", "local", "wireguard"], // Allow them to use all the site types
true, // But don't allow domain namespace resources
false // Dont include login pages
false, // Dont include login pages,
true // allow raw resources
);
return response(res, {

View File

@@ -99,8 +99,9 @@ const updateRawResourceBodySchema = z
name: z.string().min(1).max(255).optional(),
proxyPort: z.number().int().min(1).max(65535).optional(),
stickySession: z.boolean().optional(),
enabled: z.boolean().optional()
// enableProxy: z.boolean().optional() // always true now
enabled: z.boolean().optional(),
proxyProtocol: z.boolean().optional(),
proxyProtocolVersion: z.number().int().min(1).optional()
})
.strict()
.refine((data) => Object.keys(data).length > 0, {

View File

@@ -21,7 +21,8 @@ export async function traefikConfigProvider(
currentExitNodeId,
config.getRawConfig().traefik.site_types,
build == "oss", // filter out the namespace domains in open source
build != "oss" // generate the login pages on the cloud and hybrid
build != "oss", // generate the login pages on the cloud and and enterprise,
config.getRawConfig().traefik.allow_raw_resources
);
if (traefikConfig?.http?.middlewares) {