Skip to content

Instantly share code, notes, and snippets.

@avanavana
Last active January 2, 2021 20:50
Show Gist options
  • Save avanavana/dff3eda31c28111b079f2310ce2c6f66 to your computer and use it in GitHub Desktop.
Save avanavana/dff3eda31c28111b079f2310ce2c6f66 to your computer and use it in GitHub Desktop.
ipUtils – Utilities for working with IP address whitelist/blacklist patterns
/**
* @file Utilities for working with IP address whitelist/blacklist patterns
* @author Avana Vana
* @module ipUtils
* @version 2.0.2
*/
module.exports = {
/*
* Returns an array of IP addresses from a string of space separated IP patterns, expanding any wildcard characters (*)
*
* @deprecated /!\ DO NOT USE /!\ superseded by {@link patternsToRegEx}, which is far more efficient—just a single IP with two wildcards passed to this method creates an array with 65,536 elements...with four wildcards it would be ~4.3 billion elements in length...but just too cool of a one-liner for me to delete
* @method patternsToArray
* @param {string} patterns - List of ip address patterns, space-separated, with optional wildcard parts (*)
* @returns {string[]} Flat array of all combinatorically possible ip addresses using given wildcards
*
* @example <caption>Without wildcards (*)</caption>
* // returns ['67.118.0.1','255.255.1.1'] (2)
* patternsToArray('67.118.0.1 255.255.1.1');
*
* @example <caption>With wildcards (*)</caption>
* // returns ['67.118.0.1','255.255.1.0','255.255.1.1', ... , '255.255.1.254', '255.255.1.255'] (257)
* patternsToArray('67.118.0.1 255.255.1.*');
*/
patternsToArray: (patterns) => patterns
.split(' ')
.map((pattern) => pattern
.split('.')
.map((part) => (part === '*' ? [...Array(256).keys()] : [part])))
.flatMap((ip) => [...ip]
.reduce((a, b) => a
.flatMap((d) => b
.map((e) => [d, e]
.flat()))))
.map((ip) => ip
.join('.')),
/*
* Returns a regular expression from a string of space-separated IP patterns, with wildcard characters (*)
*
* @method patternsToRegEx
* @param {string} patterns - List of ip addresses, space-separated, with optional wildcards (*)
* @returns {RegExp} Regular expression equivalent to IP patterns
*
* @example <caption>Without wildcards (*)</caption>
* // returns true
* let patterns = '67.118.0.1 255.255.1.1';
* patternsToRegEx(patterns).test('67.118.0.1');
*
* @example <caption>With wildcards (*)</caption>
* // returns true
* let patterns = '67.118.0.1 255.255.*.*';
* patternsToRegEx(patterns).test('255.255.0.1');
*/
patternsToRegEx: (patterns) => new RegExp(
`(?:${patterns
.split(' ')
.map((pattern) => pattern
.replace(/\./g, '\\.')
.replace(/\*/g, '\\b(?:1\\d{2}|2[0-4]\\d|[1-9]?\\d|25[0-5])\\b'))
.join('|')})`)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment