1 line
8.4 KiB
Plaintext
1 line
8.4 KiB
Plaintext
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { forwarded } from '@tinyhttp/forwarded'\nimport type { IncomingMessage } from 'node:http'\nimport ipaddr, { IPv6, IPv4 } from 'ipaddr.js'\n\ntype Req = Pick<IncomingMessage, 'headers' | 'socket'>\n\ntype Trust = ((addr: string, i: number) => boolean) | number[] | string[] | string\n\nconst DIGIT_REGEXP = /^[0-9]+$/\nconst isip = ipaddr.isValid\nconst parseip = ipaddr.parse\n/**\n * Pre-defined IP ranges.\n */\nconst IP_RANGES = {\n linklocal: ['169.254.0.0/16', 'fe80::/10'],\n loopback: ['127.0.0.1/8', '::1/128'],\n uniquelocal: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7']\n}\n\n/**\n * Static trust function to trust nothing.\n */\nconst trustNone = () => false\n\n/**\n * Get all addresses in the request, optionally stopping\n * at the first untrusted.\n *\n * @param request\n * @param trust\n */\nfunction alladdrs(req: Req, trust: Trust): string[] {\n // get addresses\n\n const addrs = forwarded(req)\n\n if (!trust) return addrs\n\n if (typeof trust !== 'function') trust = compile(trust)\n\n for (let i = 0; i < addrs.length - 1; i++) {\n if (trust(addrs[i], i)) continue\n addrs.length = i + 1\n }\n return addrs\n}\n/**\n * Compile argument into trust function.\n *\n * @param val\n */\nfunction compile(val: string | string[] | number[]): (addr: string) => boolean {\n let trust: string[]\n if (typeof val === 'string') trust = [val]\n else if (Array.isArray(val)) trust = val.slice() as string[]\n else throw new TypeError('unsupported trust argument')\n\n for (let i = 0; i < trust.length; i++) {\n val = trust[i]\n if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) continue\n\n // Splice in pre-defined range\n val = IP_RANGES[val as string]\n // eslint-disable-next-line prefer-spread\n trust.splice.apply(trust, [i, 1].concat(val as number[]))\n i += val.length - 1\n }\n return compileTrust(compileRangeSubnets(trust))\n}\n/**\n * Compile `arr` elements into range subnets.\n */\nfunction compileRangeSubnets(arr: string[]) {\n const rangeSubnets = new Array(arr.length)\n for (let i = 0; i < arr.length; i++) rangeSubnets[i] = parseIPNotation(arr[i])\n\n return rangeSubnets\n}\n/**\n * Compile range subnet array into trust function.\n *\n * @param rangeSubnets\n */\nfunction compileTrust(rangeSubnets: (IPv4 | IPv6)[]) {\n // Return optimized function based on length\n const len = rangeSubnets.length\n return len === 0 ? trustNone : len === 1 ? trustSingle(rangeSubnets[0]) : trustMulti(rangeSubnets)\n}\n/**\n * Parse IP notation string into range subnet.\n *\n * @param {String} note\n * @private\n */\nexport function parseIPNotation(note: string): [IPv4 | IPv6, string | number] {\n const pos = note.lastIndexOf('/')\n const str = pos !== -1 ? note.substring(0, pos) : note\n\n if (!isip(str)) throw new TypeError('invalid IP address: ' + str)\n\n let ip = parseip(str)\n\n if (pos === -1 && ip.kind() === 'ipv6') {\n ip = ip as IPv6\n\n if (ip.isIPv4MappedAddress()) ip = ip.toIPv4Address()\n }\n\n const max = ip.kind() === 'ipv6' ? 128 : 32\n\n let range: string | number = pos !== -1 ? note.substring(pos + 1, note.length) : null\n\n if (range === null) range = max\n else if (DIGIT_REGEXP.test(range)) range = parseInt(range, 10)\n else if (ip.kind() === 'ipv4' && isip(range)) range = parseNetmask(range)\n else range = null\n\n if (typeof range === 'number' && (range <= 0 || range > max)) throw new TypeError('invalid range on address: ' + note)\n\n return [ip, range]\n}\n/**\n * Parse netmask string into CIDR range.\n *\n * @param netmask\n * @private\n */\nfunction parseNetmask(netmask: string) {\n const ip = parseip(netmask)\n return ip.kind() === 'ipv4' ? ip.prefixLengthFromSubnetMask() : null\n}\n/**\n * Determine address of proxied request.\n *\n * @param request\n * @param trust\n * @public\n */\nexport function proxyaddr(req: Req, trust: Trust): string {\n const addrs = alladdrs(req, trust)\n\n return addrs[addrs.length - 1]\n}\n\n/**\n * Compile trust function for multiple subnets.\n */\nfunction trustMulti(subnets: (IPv4 | IPv6)[]) {\n return function trust(addr: string) {\n if (!isip(addr)) return false\n const ip = parseip(addr)\n let ipconv: IPv4 | IPv6\n const kind = ip.kind()\n for (let i = 0; i < subnets.length; i++) {\n const subnet = subnets[i]\n const subnetip = subnet[0]\n const subnetkind = subnetip.kind()\n const subnetrange = subnet[1]\n let trusted = ip\n if (kind !== subnetkind) {\n if (subnetkind === 'ipv4' && !(ip as IPv6).isIPv4MappedAddress()) continue\n\n if (!ipconv) ipconv = subnetkind === 'ipv4' ? (ip as IPv6).toIPv4Address() : (ip as IPv4).toIPv4MappedAddress()\n\n trusted = ipconv\n }\n if ((trusted as IPv4).match(subnetip, subnetrange)) return true\n }\n return false\n }\n}\n/**\n * Compile trust function for single subnet.\n *\n * @param subnet\n */\nfunction trustSingle(subnet: IPv4 | IPv6) {\n const subnetip = subnet[0]\n const subnetkind = subnetip.kind()\n const subnetisipv4 = subnetkind === 'ipv4'\n const subnetrange = subnet[1]\n return function trust(addr: string) {\n if (!isip(addr)) return false\n let ip = parseip(addr)\n const kind = ip.kind()\n if (kind !== subnetkind) {\n if (subnetisipv4 && !(ip as IPv6).isIPv4MappedAddress()) return false\n\n ip = subnetisipv4 ? (ip as IPv6).toIPv4Address() : (ip as IPv4).toIPv4MappedAddress()\n }\n return (ip as IPv6).match(subnetip, subnetrange)\n }\n}\n\nexport { alladdrs as all }\nexport { compile }\n"],"names":[],"mappings":"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"} |