diff --git a/package-lock.json b/package-lock.json index 100cdcd88..cc56b09dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "dotenv": "~16.0.3", "express": "~4.21.0", "express-basic-auth": "~1.2.1", + "express-ipfilter": "^1.3.1", "express-static-gzip": "~2.1.7", "feed": "^4.2.2", "form-data": "~4.0.0", @@ -8605,6 +8606,25 @@ "basic-auth": "^2.0.1" } }, + "node_modules/express-ipfilter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.3.1.tgz", + "integrity": "sha512-9WZC8wGkI6I6ygZNzuZ2MbFJiGoDXs1dM+E8LKtSP13pdgqrnkonWlgvvbxG3YZpa7Haz7Ndum9/J6qkj52OqA==", + "dependencies": { + "ip": "^1.1.8", + "lodash": "^4.17.11", + "proxy-addr": "^2.0.7", + "range_check": "^2.0.4" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/express-ipfilter/node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, "node_modules/express-static-gzip": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.8.tgz", @@ -10196,6 +10216,14 @@ "node": ">= 12" } }, + "node_modules/ip6": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.2.10.tgz", + "integrity": "sha512-1LdpyKjhvepd6EbAU6rW4g14vuYtx5TnJX9TfZZBhsM6DsyPQLNzW12rtbUqXBMwqFrLVV/Gcxv0GNFvJp2cYA==", + "bin": { + "ip6": "ip6-cli.js" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -13609,6 +13637,18 @@ "node": ">=0.8.0" } }, + "node_modules/range_check": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/range_check/-/range_check-2.0.4.tgz", + "integrity": "sha512-aed0ocXXj+SIiNNN9b+mZWA3Ow2GXHtftOGk2xQwshK5GbEZAvUcPWNQBLTx/lPcdFRIUFlFCRtHTQNIFMqynQ==", + "dependencies": { + "ip6": "^0.2.0", + "ipaddr.js": "^1.9.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", diff --git a/package.json b/package.json index 4f8eef138..46e7038df 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "dotenv": "~16.0.3", "express": "~4.21.0", "express-basic-auth": "~1.2.1", + "express-ipfilter": "^1.3.1", "express-static-gzip": "~2.1.7", "feed": "^4.2.2", "form-data": "~4.0.0", diff --git a/server/server.js b/server/server.js index ec5ad49f6..1f8f82232 100644 --- a/server/server.js +++ b/server/server.js @@ -119,6 +119,27 @@ const port = config.port; const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false; const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined; +const ipsToAllow = process.env.UPTIME_KUMA_IPS_TO_ALLOW || args["ips-to-allow"] || undefined; +if (ipsToAllow !== undefined) { + if (typeof ipsToAllow !== "string") { + log.error("server", "IPs to allow must be a string, " + typeof ipsToAllow + " provided"); + process.exit(1); + } + + const splitIps = ipsToAllow.split(","); + const net = require("net"); + for (const ip of splitIps) { + if (net.isIP(ip) === 0) { + log.error("server", "Provided IPs to allow must be valid IP addresses, " + ip + " provided"); + process.exit(1); + } + } + + log.info("server", "IPs to allow: " + splitIps); + const ipfilter = require("express-ipfilter").IpFilter; + app.use(ipfilter(splitIps, { mode: "allow" })); +} + // 2FA / notp verification defaults const twoFAVerifyOptions = { "window": 1,