refactor(gateway): move request client ip resolution to net

This commit is contained in:
Peter Steinberger
2026-03-12 21:41:51 +00:00
parent 904db27019
commit 1d986f1c01
3 changed files with 24 additions and 18 deletions

View File

@@ -16,6 +16,7 @@ import { resolveGatewayCredentialsFromValues } from "./credentials.js";
import { import {
isLocalishHost, isLocalishHost,
isLoopbackAddress, isLoopbackAddress,
resolveRequestClientIp,
isTrustedProxyAddress, isTrustedProxyAddress,
resolveClientIp, resolveClientIp,
} from "./net.js"; } from "./net.js";
@@ -105,23 +106,6 @@ function resolveTailscaleClientIp(req?: IncomingMessage): string | undefined {
}); });
} }
export function resolveRequestClientIp(
req?: IncomingMessage,
trustedProxies?: string[],
allowRealIpFallback = false,
): string | undefined {
if (!req) {
return undefined;
}
return resolveClientIp({
remoteAddr: req.socket?.remoteAddress ?? "",
forwardedFor: headerValue(req.headers?.["x-forwarded-for"]),
realIp: headerValue(req.headers?.["x-real-ip"]),
trustedProxies,
allowRealIpFallback,
});
}
export function isLocalDirectRequest( export function isLocalDirectRequest(
req?: IncomingMessage, req?: IncomingMessage,
trustedProxies?: string[], trustedProxies?: string[],

View File

@@ -1,3 +1,4 @@
import type { IncomingMessage } from "node:http";
import net from "node:net"; import net from "node:net";
import os from "node:os"; import os from "node:os";
import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6 } from "../infra/tailnet.js"; import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6 } from "../infra/tailnet.js";
@@ -184,6 +185,27 @@ export function resolveClientIp(params: {
return undefined; return undefined;
} }
function headerValue(value: string | string[] | undefined): string | undefined {
return Array.isArray(value) ? value[0] : value;
}
export function resolveRequestClientIp(
req?: IncomingMessage,
trustedProxies?: string[],
allowRealIpFallback = false,
): string | undefined {
if (!req) {
return undefined;
}
return resolveClientIp({
remoteAddr: req.socket?.remoteAddress ?? "",
forwardedFor: headerValue(req.headers?.["x-forwarded-for"]),
realIp: headerValue(req.headers?.["x-real-ip"]),
trustedProxies,
allowRealIpFallback,
});
}
export function isLocalGatewayAddress(ip: string | undefined): boolean { export function isLocalGatewayAddress(ip: string | undefined): boolean {
if (isLoopbackAddress(ip)) { if (isLoopbackAddress(ip)) {
return true; return true;

View File

@@ -23,7 +23,6 @@ import {
import { import {
authorizeHttpGatewayConnect, authorizeHttpGatewayConnect,
isLocalDirectRequest, isLocalDirectRequest,
resolveRequestClientIp,
type GatewayAuthResult, type GatewayAuthResult,
type ResolvedGatewayAuth, type ResolvedGatewayAuth,
} from "./auth.js"; } from "./auth.js";
@@ -53,6 +52,7 @@ import {
} from "./hooks.js"; } from "./hooks.js";
import { sendGatewayAuthFailure, setDefaultSecurityHeaders } from "./http-common.js"; import { sendGatewayAuthFailure, setDefaultSecurityHeaders } from "./http-common.js";
import { getBearerToken } from "./http-utils.js"; import { getBearerToken } from "./http-utils.js";
import { resolveRequestClientIp } from "./net.js";
import { handleOpenAiHttpRequest } from "./openai-http.js"; import { handleOpenAiHttpRequest } from "./openai-http.js";
import { handleOpenResponsesHttpRequest } from "./openresponses-http.js"; import { handleOpenResponsesHttpRequest } from "./openresponses-http.js";
import { import {