Refactor ip range checks and support ipv6
This commit is contained in:
parent
c8ef1d6ccf
commit
287c2d1bbc
@ -18,6 +18,7 @@
|
|||||||
"dockerode": "^3.3.4",
|
"dockerode": "^3.3.4",
|
||||||
"follow-redirects": "^1.15.2",
|
"follow-redirects": "^1.15.2",
|
||||||
"i18next": "^21.9.2",
|
"i18next": "^21.9.2",
|
||||||
|
"ipaddr.js": "^2.0.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"json-rpc-2.0": "^1.4.1",
|
"json-rpc-2.0": "^1.4.1",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
|
|||||||
@ -25,6 +25,9 @@ dependencies:
|
|||||||
i18next:
|
i18next:
|
||||||
specifier: ^21.9.2
|
specifier: ^21.9.2
|
||||||
version: 21.10.0
|
version: 21.10.0
|
||||||
|
ipaddr.js:
|
||||||
|
specifier: ^2.0.1
|
||||||
|
version: 2.0.1
|
||||||
js-yaml:
|
js-yaml:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
@ -1924,6 +1927,11 @@ packages:
|
|||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/ipaddr.js@2.0.1:
|
||||||
|
resolution: {integrity: sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-arguments@1.1.1:
|
/is-arguments@1.1.1:
|
||||||
resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
|
resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|||||||
@ -2,51 +2,46 @@ import { getClientIp } from "@supercharge/request-ip";
|
|||||||
|
|
||||||
import { getSettings } from "utils/config/config";
|
import { getSettings } from "utils/config/config";
|
||||||
|
|
||||||
function checkIPRange(ip, ipSpace) {
|
const ipaddr = require("ipaddr.js");
|
||||||
// Check if the given IP is in the ipSpace address space using
|
|
||||||
// CIDR notation. If ipSpace is a plain IPv4 we just compare them.
|
function checkSingleIPRange(ip, cidr) {
|
||||||
const ipSpaceParts = ipSpace.split("/");
|
try {
|
||||||
if (ipSpaceParts.length === 1) {
|
const ipAddr = ipaddr.process(ip);
|
||||||
if (ip === ipSpace) {
|
// If the CIDR is not in the format of x.x.x.x/y, we assume it is a single IP
|
||||||
return true;
|
if (!cidr.includes("/")) {
|
||||||
|
const cidrIP = ipaddr.process(cidr);
|
||||||
|
// If both are IPv6, we need to normalize the strings
|
||||||
|
if (ipAddr.kind() === "ipv6" && cidrIP.kind() === "ipv6") {
|
||||||
|
return (ipAddr.toNormalizedString() === cidrIP.toNormalizedString());
|
||||||
|
}
|
||||||
|
return ipAddr.toString() === cidrIP.toString();
|
||||||
}
|
}
|
||||||
} else if (ipSpaceParts.length === 2) {
|
// Otherwise, we assume it is a CIDR range
|
||||||
const ipParts = ip.split(".");
|
const range = ipaddr.parseCIDR(cidr);
|
||||||
const ipNum = parseInt(ipParts[0], 10) * 256 * 256 * 256 + parseInt(ipParts[1], 10) * 256 * 256 + parseInt(ipParts[2], 10) * 256 + parseInt(ipParts[3], 10);
|
return ipAddr.match(range);
|
||||||
const ipSpaceNum = parseInt(ipSpaceParts[0].split(".")[0], 10) * 256 * 256 * 256 + parseInt(ipSpaceParts[0].split(".")[1], 10) * 256 * 256 + parseInt(ipSpaceParts[0].split(".")[2], 10) * 256 + parseInt(ipSpaceParts[0].split(".")[3], 10);
|
} catch (e) {
|
||||||
const mask = 32 - parseInt(ipSpaceParts[1], 10);
|
return false;
|
||||||
// eslint-disable-next-line no-bitwise
|
}
|
||||||
const maskNum = 0xffffffff << mask;
|
}
|
||||||
// eslint-disable-next-line no-bitwise
|
|
||||||
if ((ipNum & maskNum) === (ipSpaceNum & maskNum)) {
|
function checkIPRange(ip, range) {
|
||||||
return true;
|
if (typeof range === "string") {
|
||||||
}
|
return checkSingleIPRange(ip, range);
|
||||||
} else {
|
}
|
||||||
throw new Error(`Invalid ipSpace: ${ipSpace}`);
|
if (Array.isArray(range)) {
|
||||||
|
return range.find((cidr) => checkSingleIPRange(ip, cidr)) !== undefined;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRequestProxied(remoteAddress) {
|
export function isRequestProxied(remoteAddress) {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
// Check if trustedproxies is set
|
// Check if trustedproxies is set
|
||||||
const trustedProxies = settings?.trustedproxies;
|
const trustedProxies = settings?.trustedproxies;
|
||||||
|
|
||||||
// If trustedproxies is set, check if the client IP
|
// If trustedproxies is set, check if the client IP
|
||||||
// is in the trustedproxies address space using CIDR notation.
|
// is in the trustedproxies address space.
|
||||||
if (trustedProxies) {
|
return trustedProxies ? checkIPRange(remoteAddress, trustedProxies) : false;
|
||||||
// Get the connection IP and strip IPv6 from the hybrid IPv4-IPv6 socket
|
|
||||||
const ip = remoteAddress.replace(/^.*:/, '');
|
|
||||||
|
|
||||||
for (let i = 0; i < trustedProxies.length; i += 1) {
|
|
||||||
const proxy = trustedProxies[i].trim();
|
|
||||||
const inRange = checkIPRange(ip, proxy);
|
|
||||||
if (inRange) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRealClientIP(req) {
|
export function getRealClientIP(req) {
|
||||||
@ -63,17 +58,10 @@ export function isInLocalScope(req) {
|
|||||||
const localScope = settings?.localscope;
|
const localScope = settings?.localscope;
|
||||||
|
|
||||||
// If localscope is set, check if the client IP
|
// If localscope is set, check if the client IP
|
||||||
// is in the localscope address space using CIDR notation.
|
// is in the localscope address space.
|
||||||
if (localScope) {
|
if (localScope) {
|
||||||
const ip = getRealClientIP(req);
|
const ip = getRealClientIP(req);
|
||||||
|
return checkIPRange(ip, localScope);
|
||||||
for (let i = 0; i < localScope.length; i += 1) {
|
|
||||||
const localIP = localScope[i].trim();
|
|
||||||
const inRange = checkIPRange(ip, localIP)
|
|
||||||
if (inRange) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user