Merge branch 'private-http' of https://github.com/fosrl/pangolin into private-http

This commit is contained in:
miloschwartz
2026-04-12 12:17:57 -07:00
8 changed files with 38 additions and 27 deletions

View File

@@ -2437,6 +2437,7 @@
"validPassword": "Valid Password",
"validEmail": "Valid email",
"validSSO": "Valid SSO",
"connectedClient": "Connected Client",
"resourceBlocked": "Resource Blocked",
"droppedByRule": "Dropped by Rule",
"noSessions": "No Sessions",

View File

@@ -662,10 +662,10 @@ export async function generateSubnetProxyTargetV2(
}
if (
!siteResource.alias ||
!siteResource.aliasAddress ||
!siteResource.destinationPort ||
!siteResource.scheme
!siteResource.scheme ||
!siteResource.fullDomain
) {
logger.debug(
`Site resource ${siteResource.siteResourceId} is in HTTP mode but is missing alias or alias address or destinationPort or scheme, skipping alias target generation.`
@@ -676,10 +676,10 @@ export async function generateSubnetProxyTargetV2(
let tlsCert: string | undefined;
let tlsKey: string | undefined;
if (siteResource.ssl && siteResource.alias) {
if (siteResource.ssl && siteResource.fullDomain) {
try {
const certs = await getValidCertificatesForDomains(
new Set([siteResource.alias]),
new Set([siteResource.fullDomain]),
true
);
if (certs.length > 0 && certs[0].certFile && certs[0].keyFile) {
@@ -687,12 +687,12 @@ export async function generateSubnetProxyTargetV2(
tlsKey = certs[0].keyFile;
} else {
logger.warn(
`No valid certificate found for SSL site resource ${siteResource.siteResourceId} with domain ${siteResource.alias}`
`No valid certificate found for SSL site resource ${siteResource.siteResourceId} with domain ${siteResource.fullDomain}`
);
}
} catch (err) {
logger.error(
`Failed to retrieve certificate for site resource ${siteResource.siteResourceId} domain ${siteResource.alias}: ${err}`
`Failed to retrieve certificate for site resource ${siteResource.siteResourceId} domain ${siteResource.fullDomain}: ${err}`
);
}
}

View File

@@ -144,7 +144,7 @@ export const handleRequestLogMessage: MessageHandler = async (context) => {
await logRequestAudit(
{
action: true,
reason: 100,
reason: 108,
resourceId: entry.resourceId,
orgId
},
@@ -163,4 +163,4 @@ export const handleRequestLogMessage: MessageHandler = async (context) => {
logger.debug(
`Buffered ${entries.length} request log entry/entries from newt ${newt.newtId} (site ${newt.siteId})`
);
};
};

View File

@@ -18,6 +18,7 @@ Reasons:
105 - Valid Password
106 - Valid email
107 - Valid SSO
108 - Connected Client
201 - Resource Not Found
202 - Resource Blocked

View File

@@ -56,7 +56,7 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
if (existingSite.lastHolePunch && now - existingSite.lastHolePunch > 5) {
logger.warn(
`Site last hole punch is too old; skipping this register. The site is failing to hole punch and identify its network address with the server. Can the client reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`
`Site last hole punch is too old; skipping this register. The site is failing to hole punch and identify its network address with the server. Can the site reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`
);
return;
}

View File

@@ -262,7 +262,7 @@ export async function createSiteResource(
let fullDomain: string | null = null;
let finalSubdomain: string | null = null;
if (domainId && subdomain) {
if (domainId) {
// Validate domain and construct full domain
const domainResult = await validateAndConstructDomain(
domainId,

View File

@@ -80,18 +80,15 @@ const updateSiteResourceSchema = z
.strict()
.refine(
(data) => {
if (
data.mode === "host" &&
data.destination
) {
const isValidIP = z
// .union([z.ipv4(), z.ipv6()])
.union([z.ipv4()]) // for now lets just do ipv4 until we verify ipv6 works everywhere
.safeParse(data.destination).success;
if (data.mode === "host" && data.destination) {
const isValidIP = z
// .union([z.ipv4(), z.ipv6()])
.union([z.ipv4()]) // for now lets just do ipv4 until we verify ipv6 works everywhere
.safeParse(data.destination).success;
if (isValidIP) {
return true;
}
if (isValidIP) {
return true;
}
// Check if it's a valid domain (hostname pattern, TLD not required)
const domainRegex =
@@ -306,7 +303,7 @@ export async function updateSiteResource(
let fullDomain: string | null = null;
let finalSubdomain: string | null = null;
if (domainId && subdomain) {
if (domainId) {
// Validate domain and construct full domain
const domainResult = await validateAndConstructDomain(
domainId,
@@ -324,12 +321,16 @@ export async function updateSiteResource(
finalSubdomain = domainResult.subdomain;
// make sure the full domain is unique
const existingResource = await db
const [existingDomain] = await db
.select()
.from(siteResources)
.where(eq(siteResources.fullDomain, fullDomain));
if (existingResource.length > 0) {
if (
existingDomain &&
existingDomain.siteResourceId !==
existingSiteResource.siteResourceId
) {
return next(
createHttpError(
HttpCode.CONFLICT,
@@ -666,9 +667,14 @@ export async function handleMessagingForUpdatedSiteResource(
const destinationChanged =
existingSiteResource &&
existingSiteResource.destination !== updatedSiteResource.destination;
const destinationPortChanged =
existingSiteResource &&
existingSiteResource.destinationPort !==
updatedSiteResource.destinationPort;
const aliasChanged =
existingSiteResource &&
existingSiteResource.alias !== updatedSiteResource.alias;
(existingSiteResource.alias !== updatedSiteResource.alias ||
existingSiteResource.fullDomain !== updatedSiteResource.fullDomain); // because the full domain gets sent down to the stuff as an alias
const portRangesChanged =
existingSiteResource &&
(existingSiteResource.tcpPortRangeString !==
@@ -680,7 +686,7 @@ export async function handleMessagingForUpdatedSiteResource(
// if the existingSiteResource is undefined (new resource) we don't need to do anything here, the rebuild above handled it all
if (destinationChanged || aliasChanged || portRangesChanged) {
if (destinationChanged || aliasChanged || portRangesChanged || destinationPortChanged) {
const [newt] = await trx
.select()
.from(newts)
@@ -694,7 +700,7 @@ export async function handleMessagingForUpdatedSiteResource(
}
// Only update targets on newt if destination changed
if (destinationChanged || portRangesChanged) {
if (destinationChanged || portRangesChanged || destinationPortChanged) {
const oldTarget = await generateSubnetProxyTargetV2(
existingSiteResource,
mergedAllClients

View File

@@ -360,6 +360,7 @@ export default function GeneralPage() {
// 105 - Valid Password
// 106 - Valid email
// 107 - Valid SSO
// 108 - Connected Client
// 201 - Resource Not Found
// 202 - Resource Blocked
@@ -377,6 +378,7 @@ export default function GeneralPage() {
105: t("validPassword"),
106: t("validEmail"),
107: t("validSSO"),
108: t("connectedClient"),
201: t("resourceNotFound"),
202: t("resourceBlocked"),
203: t("droppedByRule"),
@@ -630,6 +632,7 @@ export default function GeneralPage() {
{ value: "105", label: t("validPassword") },
{ value: "106", label: t("validEmail") },
{ value: "107", label: t("validSSO") },
{ value: "108", label: t("connectedClient") },
{ value: "201", label: t("resourceNotFound") },
{ value: "202", label: t("resourceBlocked") },
{ value: "203", label: t("droppedByRule") },