UNPKG

is-private-host

Version:

Check if a hostname or URL resolves to a private IP address

1 lines 7.58 kB
{"version":3,"file":"index.cjs","sources":["../src/privateRanges.ts","../src/isPrivateIP.ts","../src/isPrivateHost.ts","../src/isPrivateUrl.ts"],"sourcesContent":["/**\n * @internal\n */\nconst PRIVATE_IPV4_RANGES = [\n // Unspecified\n '0.0.0.0/8',\n // Private Class A\n '10.0.0.0/8',\n // CGNAT (Optional)\n '100.64.0.0/10',\n // Loopback\n '127.0.0.0/8',\n // Link-local\n '169.254.0.0/16',\n // Private Class B\n '172.16.0.0/12',\n // Private Class C\n '192.168.0.0/16',\n]\n\n/**\n * @internal\n */\nconst PRIVATE_IPV6_RANGES = [\n // Unspecified\n '::/128',\n // Loopback\n '::1/128',\n // IPv4-Mapped IPv6\n '::ffff:0:0/96',\n // NAT64\n '64:ff9b::/96',\n // Unique Local Addresses (ULA)\n 'fc00::/7',\n // Link-local\n 'fe80::/10',\n]\n\n/**\n * @internal\n */\nexport const privateRanges = {\n ipv4: PRIVATE_IPV4_RANGES,\n ipv6: PRIVATE_IPV6_RANGES,\n}\n","import {parse as parseIP, parseCIDR} from 'ipaddr.js'\n\nimport {privateRanges} from './privateRanges.js'\n\n/**\n * Checks if an IP address falls within a private/reserved range.\n *\n * @param ipAddress - The IP address to check. Can be either IPv4 or IPv6.\n * @returns True if the IP address is private/reserved, false otherwise.\n * @public\n */\nexport function isPrivateIP(ipAddress: string): boolean {\n try {\n const parsedIP = parseIP(ipAddress)\n\n // Check if the IP is within any of the defined private ranges\n const ranges = parsedIP.kind() === 'ipv4' ? privateRanges.ipv4 : privateRanges.ipv6\n return ranges.some((range) => {\n const subnet = parseCIDR(range)\n return parsedIP.match(subnet)\n })\n } catch (error) {\n throw new Error(`Invalid IP address \"${ipAddress}\"`)\n }\n}\n","import type {LookupAddress} from 'node:dns'\nimport {lookup} from 'node:dns/promises'\n\nimport {isPrivateIP} from './isPrivateIP.js'\n\n/**\n * Resolve result for a given hostname\n *\n * @public\n */\nexport interface HostResolveInfo {\n isPrivate: boolean\n addresses: LookupAddress[]\n}\n\n/**\n * Determines if a the given hostname resolves to a \"private\" IP address\n *\n * @param hostname - Hostname to check\n * @returns Promise resolving to true if the hostname resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateHost(hostname: string): Promise<boolean>\n\n/**\n * Determines if a the given hostname resolves to a \"private\" IP address\n *\n * @param hostname - Hostname to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to true if the hostname resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateHost(\n hostname: string,\n options: Record<string, never>,\n): Promise<boolean>\n\n/**\n * Determines if a the given hostname resolves to a \"private\" IP address\n *\n * @param hostname - Hostname to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to true if the hostname resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateHost(\n hostname: string,\n options: {withResolveInfo: false},\n): Promise<boolean>\n\n/**\n * Determines if a the given hostname resolves to a \"private\" IP address\n *\n * @param hostname - Hostname to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to an object containing the resolve information\n * @public\n */\nexport async function isPrivateHost(\n hostname: string,\n options: {withResolveInfo: true},\n): Promise<HostResolveInfo>\n\nexport async function isPrivateHost(\n hostname: string,\n options?: {withResolveInfo?: boolean},\n): Promise<boolean | HostResolveInfo> {\n try {\n const addresses = await lookup(hostname, {\n // Check both IPv4 and IPv6 records since we don't know which one will be used in the end\n all: true,\n })\n\n const isPrivate = addresses.some(({address}) => isPrivateIP(address))\n return options && options.withResolveInfo ? {isPrivate, addresses} : isPrivate\n } catch (error: unknown) {\n throw new Error(\n `Error resolving hostname \"${hostname}\": ${error instanceof Error ? error.message : error}`,\n {cause: error},\n )\n }\n}\n","import type {LookupAddress} from 'node:dns'\n\nimport {type HostResolveInfo, isPrivateHost} from './isPrivateHost.js'\n\n/**\n * Resolve result for a given URL\n *\n * @public\n */\nexport interface UrlResolveInfo {\n isPrivate: boolean\n parsedUrl: URL\n addresses: LookupAddress[]\n}\n\n/**\n * Determines if a the given URL resolves to a \"private\" IP address\n *\n * @param url - URL to check\n * @returns Promise resolving to true if the URL resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateUrl(url: string): Promise<boolean>\n\n/**\n * Determines if a the given URL resolves to a \"private\" IP address\n *\n * @param url - URL to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to true if the URL resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateUrl(url: string, options: Record<string, never>): Promise<boolean>\n\n/**\n * Determines if a the given URL resolves to a \"private\" IP address\n *\n * @param url - URL to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to true if the URL resolves to a private IP address, false otherwise\n * @public\n */\nexport async function isPrivateUrl(url: string, options: {withResolveInfo: false}): Promise<boolean>\n\n/**\n * Determines if a the given URL resolves to a \"private\" IP address\n *\n * @param url - URL to check\n * @param options - Options for the resolve operation\n * @returns Promise resolving to an object containing the resolve information\n * @public\n */\nexport async function isPrivateUrl(\n url: string,\n options: {withResolveInfo: true},\n): Promise<UrlResolveInfo>\n\nexport async function isPrivateUrl(\n url: string,\n options?: {withResolveInfo?: boolean},\n): Promise<boolean | HostResolveInfo> {\n const parsedUrl = new URL(url)\n const {isPrivate, addresses} = await isPrivateHost(parsedUrl.hostname, {withResolveInfo: true})\n const resolveInfo: UrlResolveInfo = {isPrivate, parsedUrl, addresses}\n return options && options.withResolveInfo ? resolveInfo : isPrivate\n}\n"],"names":["parseIP","parseCIDR","lookup"],"mappings":";;;AAGA,MAAM,sBAAsB;AAAA;AAAA,EAE1B;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF,GAKM,sBAAsB;AAAA;AAAA,EAE1B;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF,GAKa,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,MAAM;AACR;ACjCO,SAAS,YAAY,WAA4B;AAClD,MAAA;AACI,UAAA,WAAWA,gBAAQ,SAAS;AAGnB,YAAA,SAAS,KAAK,MAAM,SAAS,cAAc,OAAO,cAAc,MACjE,KAAK,CAAC,UAAU;AACtB,YAAA,SAASC,oBAAU,KAAK;AACvB,aAAA,SAAS,MAAM,MAAM;AAAA,IAAA,CAC7B;AAAA,EAAA,QACa;AACd,UAAM,IAAI,MAAM,uBAAuB,SAAS,GAAG;AAAA,EAAA;AAEvD;ACuCsB,eAAA,cACpB,UACA,SACoC;AAChC,MAAA;AACI,UAAA,YAAY,MAAMC,SAAA,OAAO,UAAU;AAAA;AAAA,MAEvC,KAAK;AAAA,IAAA,CACN,GAEK,YAAY,UAAU,KAAK,CAAC,EAAC,QAAO,MAAM,YAAY,OAAO,CAAC;AACpE,WAAO,WAAW,QAAQ,kBAAkB,EAAC,WAAW,cAAa;AAAA,WAC9D,OAAgB;AACvB,UAAM,IAAI;AAAA,MACR,6BAA6B,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,MACzF,EAAC,OAAO,MAAK;AAAA,IACf;AAAA,EAAA;AAEJ;ACxBsB,eAAA,aACpB,KACA,SACoC;AAC9B,QAAA,YAAY,IAAI,IAAI,GAAG,GACvB,EAAC,WAAW,UAAS,IAAI,MAAM,cAAc,UAAU,UAAU,EAAC,iBAAiB,GAAK,CAAA,GACxF,cAA8B,EAAC,WAAW,WAAW,UAAS;AAC7D,SAAA,WAAW,QAAQ,kBAAkB,cAAc;AAC5D;;;;"}