proxy-addr

Determine the real client IP address behind trusted proxies, with full IPv4, IPv6, and CIDR support.

Library
npm
v2.0.7
141stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity16
Maintenance20
Community72
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture75
Code Quality92
Innovation85
Learning Curve50

proxy-addr is a small, focused Node.js library that answers one question reliably: given a request that may have passed through one or more reverse proxies, what is the actual client IP address? It walks the X-Forwarded-For chain (via the forwarded package) from the socket address outward, stopping at the first address the caller does not trust, so applications never blindly accept a spoofed header value.

Trust is expressed as a function, a single IP/CIDR string, or an array of addresses and pre-defined named ranges (loopback, linklocal, uniquelocal), compiled once into an optimized matcher via proxyaddr.compile(). Because it underpins Express’s req.ip and trust proxy setting, it is one of the most widely depended-on packages in the Node.js HTTP ecosystem, downloaded well over 100 million times a week.

What You Get

  • A single proxyaddr(req, trust) function that returns the closest untrusted client address for a request
  • proxyaddr.all(req, trust) to retrieve the full ordered address chain instead of just the final result
  • proxyaddr.compile(val) to pre-compile a trust specification into a fast, reusable trust function
  • Built-in named trust ranges (loopback, linklocal, uniquelocal) covering common private/reserved address blocks
  • Native support for IPv4, IPv6, IPv4-mapped IPv6 normalization, and CIDR/netmask notation

Common Use Cases

  • Implementing Express’s trust proxy setting and req.ip resolution behind Nginx, HAProxy, or a cloud load balancer
  • Safely resolving client IPs for rate limiting or abuse detection without trusting attacker-supplied X-Forwarded-For headers
  • Geo-IP or analytics pipelines that need the true originating address behind a CDN or reverse-proxy chain
  • Custom HTTP middleware or frameworks that need to whitelist specific internal proxy subnets as trusted hops

Under The Hood

Architecture The module is a single dense file organized around one pipeline: compile() turns a trust specification (string, array, or named range like loopback) into resolved IP/CIDR subnets via parseipNotation(), which compileTrust() then turns into an optimized closure — trustNone, trustSingle, or trustMulti depending on how many subnets were given. alladdrs() retrieves the address chain from forwarded(req) and walks it front-to-back, truncating at the first address the compiled trust function rejects; proxyaddr() simply returns the last surviving entry. The design cleanly separates parsing (turning user input into subnets), compilation (turning subnets into a fast matcher), and evaluation (applying the matcher to a request), so the core abstraction — the trust function — is the only thing a caller depending on custom trust logic needs to reason about.

Tech Stack Pure, dependency-light JavaScript (CommonJS, 'use strict', ES5-style var declarations for broad Node compatibility down to Node 0.10) with exactly two runtime dependencies: forwarded for X-Forwarded-For parsing and ipaddr.js for IP parsing, CIDR matching, and IPv4/IPv6 conversion. No build step is required — the package ships index.js directly. Tests run via Mocha with coverage through nyc, and linting uses ESLint with the standard config.

Code Quality The test suite is extensive relative to the package’s size, covering argument validation, IPv4/IPv6/CIDR/netmask parsing edge cases, pre-defined range expansion, and both function- and array-based trust policies, run with --check-leaks and --bail for strict CI discipline. CI runs the full suite across a wide matrix of Node.js versions from 0.10 through current, plus CodeQL static analysis and an OpenSSF Scorecard workflow — unusually thorough security posture for a package this small. Comments follow a consistent JSDoc-style convention throughout, though there are no TypeScript types shipped natively (DefinitelyTyped covers that separately).

API Design The public surface is deliberately minimal: one primary function plus two small helpers (all, compile), all exported from a single module with no configuration object or class to instantiate. The trust argument’s overloaded string/array/function acceptance covers the common cases (a hardcoded proxy IP, a CIDR range, a fully custom policy) without forcing callers into boilerplate, and pre-compiling a trust function via compile() up front is explicitly documented as the recommended pattern for per-request performance.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search