From b5a931c96e15d6426834370d753f0d53eded9120 Mon Sep 17 00:00:00 2001 From: Pallavi Kumari Date: Thu, 23 Oct 2025 23:07:26 +0530 Subject: [PATCH 1/5] UI and backend update to add proxy protocol support --- server/db/sqlite/schema/schema.ts | 5 +- server/routers/resource/updateResource.ts | 5 +- .../resources/[niceId]/proxy/page.tsx | 164 +++++++++++++++--- 3 files changed, 147 insertions(+), 27 deletions(-) diff --git a/server/db/sqlite/schema/schema.ts b/server/db/sqlite/schema/schema.ts index 2c19a1c7..415ce80b 100644 --- a/server/db/sqlite/schema/schema.ts +++ b/server/db/sqlite/schema/schema.ts @@ -114,7 +114,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", { diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index a9c3b5de..13c5220d 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -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, { diff --git a/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx index 9588e0c8..5af5b318 100644 --- a/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx @@ -77,7 +77,8 @@ import { MoveRight, ArrowUp, Info, - ArrowDown + ArrowDown, + AlertTriangle } from "lucide-react"; import { ContainersSelector } from "@app/components/ContainersSelector"; import { useTranslations } from "next-intl"; @@ -115,6 +116,7 @@ import { TooltipProvider, TooltipTrigger } from "@app/components/ui/tooltip"; +import { Alert, AlertDescription } from "@app/components/ui/alert"; const addTargetSchema = z .object({ @@ -288,7 +290,9 @@ export default function ReverseProxyTargets(props: { ), headers: z .array(z.object({ name: z.string(), value: z.string() })) - .nullable() + .nullable(), + proxyProtocol: z.boolean().optional(), + proxyProtocolVersion: z.number().int().min(1).max(2).optional() }); const tlsSettingsSchema = z.object({ @@ -325,7 +329,9 @@ export default function ReverseProxyTargets(props: { resolver: zodResolver(proxySettingsSchema), defaultValues: { setHostHeader: resource.setHostHeader || "", - headers: resource.headers + headers: resource.headers, + proxyProtocol: resource.proxyProtocol || false, + proxyProtocolVersion: resource.proxyProtocolVersion || 1 } }); @@ -549,11 +555,11 @@ export default function ReverseProxyTargets(props: { prev.map((t) => t.targetId === target.targetId ? { - ...t, - targetId: response.data.data.targetId, - new: false, - updated: false - } + ...t, + targetId: response.data.data.targetId, + new: false, + updated: false + } : t ) ); @@ -673,11 +679,11 @@ export default function ReverseProxyTargets(props: { targets.map((target) => target.targetId === targetId ? { - ...target, - ...data, - updated: true, - siteType: site ? site.type : target.siteType - } + ...target, + ...data, + updated: true, + siteType: site ? site.type : target.siteType + } : target ) ); @@ -688,10 +694,10 @@ export default function ReverseProxyTargets(props: { targets.map((target) => target.targetId === targetId ? { - ...target, - ...config, - updated: true - } + ...target, + ...config, + updated: true + } : target ) ); @@ -800,6 +806,22 @@ export default function ReverseProxyTargets(props: { setHostHeader: proxyData.setHostHeader || null, headers: proxyData.headers || null }); + } else { + // For TCP/UDP resources, save proxy protocol settings + const proxyData = proxySettingsForm.getValues(); + + const payload = { + proxyProtocol: proxyData.proxyProtocol || false, + proxyProtocolVersion: proxyData.proxyProtocolVersion || 1 + }; + + await api.post(`/resource/${resource.resourceId}`, payload); + + updateResource({ + ...resource, + proxyProtocol: proxyData.proxyProtocol || false, + proxyProtocolVersion: proxyData.proxyProtocolVersion || 1 + }); } toast({ @@ -1064,7 +1086,7 @@ export default function ReverseProxyTargets(props: { className={cn( "w-[180px] justify-between text-sm border-r pr-4 rounded-none h-8 hover:bg-transparent", !row.original.siteId && - "text-muted-foreground" + "text-muted-foreground" )} > @@ -1404,12 +1426,12 @@ export default function ReverseProxyTargets(props: { {header.isPlaceholder ? null : flexRender( - header - .column - .columnDef - .header, - header.getContext() - )} + header + .column + .columnDef + .header, + header.getContext() + )} ) )} @@ -1675,6 +1697,100 @@ export default function ReverseProxyTargets(props: { )} + {!resource.http && resource.protocol && ( + + + + Proxy Protocol Settings + + + Configure Proxy Protocol to preserve client IP addresses for TCP/UDP services. + + + + +
+ + ( + + + { + field.onChange(val); + }} + /> + + + )} + /> + + {proxySettingsForm.watch("proxyProtocol") && ( + <> + ( + + Proxy Protocol Version + + + + + Version 1 is text-based and widely supported. Version 2 is binary and more efficient but less compatible. + + + )} + /> + + + + + Warning: Your backend application must be configured to accept Proxy Protocol connections. + If your backend doesn't support Proxy Protocol, enabling this will break all connections. + Make sure to configure your backend to trust Proxy Protocol headers from Traefik. + + + + )} + + +
+
+
+ )} +