| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- import fs from "node:fs";
- import https from "node:https";
- import { dirname } from "node:path";
- import { fileURLToPath } from "node:url";
- import errs from "../lib/error.js";
- import utils from "../lib/utils.js";
- import { ipRanges as logger } from "../logger.js";
- import internalNginx from "./nginx.js";
- const __filename = fileURLToPath(import.meta.url);
- const __dirname = dirname(__filename);
- const CLOUDFRONT_URL = "https://ip-ranges.amazonaws.com/ip-ranges.json";
- const CLOUDFARE_V4_URL = "https://www.cloudflare.com/ips-v4";
- const CLOUDFARE_V6_URL = "https://www.cloudflare.com/ips-v6";
- const regIpV4 = /^(\d+\.?){4}\/\d+/;
- const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/;
- const internalIpRanges = {
- interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
- interval: null,
- interval_processing: false,
- iteration_count: 0,
- initTimer: () => {
- logger.info("IP Ranges Renewal Timer initialized");
- internalIpRanges.interval = setInterval(internalIpRanges.fetch, internalIpRanges.interval_timeout);
- },
- fetchUrl: (url) => {
- return new Promise((resolve, reject) => {
- logger.info(`Fetching ${url}`);
- return https
- .get(url, (res) => {
- res.setEncoding("utf8");
- let raw_data = "";
- res.on("data", (chunk) => {
- raw_data += chunk;
- });
- res.on("end", () => {
- resolve(raw_data);
- });
- })
- .on("error", (err) => {
- reject(err);
- });
- });
- },
- /**
- * Triggered at startup and then later by a timer, this will fetch the ip ranges from services and apply them to nginx.
- */
- fetch: () => {
- if (!internalIpRanges.interval_processing) {
- internalIpRanges.interval_processing = true;
- logger.info("Fetching IP Ranges from online services...");
- let ip_ranges = [];
- return internalIpRanges
- .fetchUrl(CLOUDFRONT_URL)
- .then((cloudfront_data) => {
- const data = JSON.parse(cloudfront_data);
- if (data && typeof data.prefixes !== "undefined") {
- data.prefixes.map((item) => {
- if (item.service === "CLOUDFRONT") {
- ip_ranges.push(item.ip_prefix);
- }
- return true;
- });
- }
- if (data && typeof data.ipv6_prefixes !== "undefined") {
- data.ipv6_prefixes.map((item) => {
- if (item.service === "CLOUDFRONT") {
- ip_ranges.push(item.ipv6_prefix);
- }
- return true;
- });
- }
- })
- .then(() => {
- return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL);
- })
- .then((cloudfare_data) => {
- const items = cloudfare_data.split("\n").filter((line) => regIpV4.test(line));
- ip_ranges = [...ip_ranges, ...items];
- })
- .then(() => {
- return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL);
- })
- .then((cloudfare_data) => {
- const items = cloudfare_data.split("\n").filter((line) => regIpV6.test(line));
- ip_ranges = [...ip_ranges, ...items];
- })
- .then(() => {
- const clean_ip_ranges = [];
- ip_ranges.map((range) => {
- if (range) {
- clean_ip_ranges.push(range);
- }
- return true;
- });
- return internalIpRanges.generateConfig(clean_ip_ranges).then(() => {
- if (internalIpRanges.iteration_count) {
- // Reload nginx
- return internalNginx.reload();
- }
- });
- })
- .then(() => {
- internalIpRanges.interval_processing = false;
- internalIpRanges.iteration_count++;
- })
- .catch((err) => {
- logger.fatal(err.message);
- internalIpRanges.interval_processing = false;
- });
- }
- },
- /**
- * @param {Array} ip_ranges
- * @returns {Promise}
- */
- generateConfig: (ip_ranges) => {
- const renderEngine = utils.getRenderEngine();
- return new Promise((resolve, reject) => {
- let template = null;
- const filename = "/etc/nginx/conf.d/include/ip_ranges.conf";
- try {
- template = fs.readFileSync(`${__dirname}/../templates/ip_ranges.conf`, { encoding: "utf8" });
- } catch (err) {
- reject(new errs.ConfigurationError(err.message));
- return;
- }
- renderEngine
- .parseAndRender(template, { ip_ranges: ip_ranges })
- .then((config_text) => {
- fs.writeFileSync(filename, config_text, { encoding: "utf8" });
- resolve(true);
- })
- .catch((err) => {
- logger.warn(`Could not write ${filename}: ${err.message}`);
- reject(new errs.ConfigurationError(err.message));
- });
- });
- },
- };
- export default internalIpRanges;
|