@sitecmd/network-policy
v1.0.0
Published
Which IP addresses and hostnames are public, for code that fetches a URL someone else chose.
Downloads
220
Readme
@sitecmd/network-policy
Which IP addresses and hostnames are public, for code that fetches a URL someone else chose. SiteCMD Connect uses it to admit sites and alert webhooks, and the hosted scanner uses it to classify every target before it fetches.
The address entry also keys per-address rate limits.
npm install @sitecmd/network-policyThe package ships ES modules with type declarations and has two entries, so code that only classifies addresses never loads the Public Suffix List.
@sitecmd/network-policy/address
isPublicAddress(address) decides whether an IP literal is a public address. It is an allow-list: an address is public only when ipaddr.js names it ordinary unicast, and an IPv6 address must also lie in IANA global unicast (2000::/3). Loopback, private, link-local, carrier-grade NAT, documentation, benchmarking, reserved and multicast ranges are refused, and so are the IPv6 transition forms (IPv4-compatible, 6to4, Teredo, NAT64) rather than decoded to the IPv4 address they carry. IPv4-mapped IPv6 addresses are classified by the IPv4 address inside them. URL hostname brackets and IPv6 zone ids are accepted; shorthand spellings such as 127.1, a single integer, or an octal part are refused rather than guessed at.
import { isPublicAddress } from "@sitecmd/network-policy/address";
isPublicAddress("93.184.215.14"); // true
isPublicAddress("[::ffff:127.0.0.1]"); // false: loopback, mapped into IPv6addressRateLimitKey(address) returns one key per IPv4 address or IPv6 /64. IPv4-mapped IPv6 uses its embedded IPv4 address, so both spellings share the same key while different IPv4 addresses stay separate. Compressed and expanded IPv6 spellings share their prefix's key. An invalid address passes through unchanged.
import { addressRateLimitKey } from "@sitecmd/network-policy/address";
addressRateLimitKey("192.0.2.1"); // "192.0.2.1"
addressRateLimitKey("::ffff:192.0.2.1"); // "192.0.2.1"
addressRateLimitKey("2001:db8:1::2"); // "2001:db8:1::/64"@sitecmd/network-policy/hostname
isPublicHostname(hostname) decides whether a hostname, as URL.hostname gives it, is a public name: it must end in a known ICANN public suffix and have a registrable domain under that suffix, as tldts and its copy of the Public Suffix List read it. That refuses localhost, .local, .internal, .lan, .corp, dotless names and IP literals up front, instead of depending on DNS failing to answer for them. .arpa and .onion are refused as well, because no public site lives there.
import { isPublicHostname } from "@sitecmd/network-policy/hostname";
isPublicHostname(new URL("https://www.example.com/").hostname); // true
isPublicHostname("metadata.google.internal"); // falseA public hostname can still resolve to a private address, so code that connects should check the addresses it resolves with isPublicAddress as well.
License
Apache-2.0. See LICENSE.
