pax_global_header00006660000000000000000000000064140553027030014511gustar00rootroot0000000000000052 comment=1cdd2f78e0fcc23ceae4723e6b837345c2499772 proxy-addr-2.0.7/000077500000000000000000000000001405530270300136105ustar00rootroot00000000000000proxy-addr-2.0.7/.eslintignore000066400000000000000000000000421405530270300163070ustar00rootroot00000000000000.nyc_output coverage node_modules proxy-addr-2.0.7/.eslintrc.yml000066400000000000000000000002321405530270300162310ustar00rootroot00000000000000root: true extends: - standard - plugin:markdown/recommended plugins: - markdown overrides: - files: '**/*.md' processor: 'markdown/markdown' proxy-addr-2.0.7/.github/000077500000000000000000000000001405530270300151505ustar00rootroot00000000000000proxy-addr-2.0.7/.github/workflows/000077500000000000000000000000001405530270300172055ustar00rootroot00000000000000proxy-addr-2.0.7/.github/workflows/ci.yml000066400000000000000000000120551405530270300203260ustar00rootroot00000000000000name: ci on: - pull_request - push jobs: test: runs-on: ubuntu-latest strategy: matrix: name: - Node.js 0.10 - Node.js 0.12 - io.js 1.x - io.js 2.x - io.js 3.x - Node.js 4.x - Node.js 5.x - Node.js 6.x - Node.js 7.x - Node.js 8.x - Node.js 9.x - Node.js 10.x - Node.js 11.x - Node.js 12.x - Node.js 13.x - Node.js 14.x - Node.js 15.x - Node.js 16.x include: - name: Node.js 0.10 node-version: "0.10" npm-i: mocha@3.5.3 nyc@10.3.2 npm-rm: beautify-benchmark benchmark - name: Node.js 0.12 node-version: "0.12" npm-i: mocha@3.5.3 nyc@10.3.2 npm-rm: beautify-benchmark benchmark - name: io.js 1.x node-version: "1.8" npm-i: mocha@3.5.3 nyc@10.3.2 npm-rm: beautify-benchmark benchmark - name: io.js 2.x node-version: "2.5" npm-i: mocha@3.5.3 nyc@10.3.2 npm-rm: beautify-benchmark benchmark - name: io.js 3.x node-version: "3.3" npm-i: mocha@3.5.3 nyc@10.3.2 npm-rm: beautify-benchmark benchmark - name: Node.js 4.x node-version: "4.9" npm-i: mocha@5.2.0 nyc@11.9.0 npm-rm: beautify-benchmark benchmark - name: Node.js 5.x node-version: "5.12" npm-i: mocha@5.2.0 nyc@11.9.0 npm-rm: beautify-benchmark benchmark - name: Node.js 6.x node-version: "6.17" npm-i: mocha@6.2.2 nyc@14.1.1 npm-rm: beautify-benchmark benchmark - name: Node.js 7.x node-version: "7.10" npm-i: mocha@6.2.2 nyc@14.1.1 npm-rm: beautify-benchmark benchmark - name: Node.js 8.x node-version: "8.17" npm-i: mocha@7.2.0 npm-rm: beautify-benchmark benchmark - name: Node.js 9.x node-version: "9.11" npm-i: mocha@7.2.0 npm-rm: beautify-benchmark benchmark - name: Node.js 10.x node-version: "10.24" npm-rm: beautify-benchmark benchmark - name: Node.js 11.x node-version: "11.15" npm-rm: beautify-benchmark benchmark - name: Node.js 12.x node-version: "12.22" npm-rm: beautify-benchmark benchmark - name: Node.js 13.x node-version: "13.14" npm-rm: beautify-benchmark benchmark - name: Node.js 14.x node-version: "14.17" npm-rm: beautify-benchmark benchmark - name: Node.js 15.x node-version: "15.14" npm-rm: beautify-benchmark benchmark - name: Node.js 16.x node-version: "16.2" npm-rm: beautify-benchmark benchmark steps: - uses: actions/checkout@v2 - name: Install Node.js ${{ matrix.node-version }} shell: bash -eo pipefail -l {0} run: | nvm install --default ${{ matrix.node-version }} if [[ "${{ matrix.node-version }}" == 0.* ]]; then npm config set strict-ssl false fi dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" - name: Configure npm run: npm config set shrinkwrap false - name: Remove npm module(s) ${{ matrix.npm-rm }} run: npm rm --silent --save-dev ${{ matrix.npm-rm }} if: matrix.npm-rm != '' - name: Install npm module(s) ${{ matrix.npm-i }} run: npm install --save-dev ${{ matrix.npm-i }} if: matrix.npm-i != '' - name: Setup Node.js version-specific dependencies shell: bash run: | # eslint for linting # - remove on Node.js < 10 if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ grep -E '^eslint(-|$)' | \ sort -r | \ xargs -n1 npm rm --silent --save-dev fi - name: Install Node.js dependencies run: npm install - name: List environment id: list_env shell: bash run: | echo "node@$(node -v)" echo "npm@$(npm -v)" npm -s ls ||: (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print "::set-output name=" $2 "::" $3 }' - name: Run tests shell: bash run: | if npm -ps ls nyc | grep -q nyc; then npm run test-ci else npm test fi - name: Lint code if: steps.list_env.outputs.eslint != '' run: npm run lint - name: Collect code coverage uses: coverallsapp/github-action@master if: steps.list_env.outputs.nyc != '' with: github-token: ${{ secrets.GITHUB_TOKEN }} flag-name: run-${{ matrix.test_number }} parallel: true coverage: needs: test runs-on: ubuntu-latest steps: - name: Upload code coverage uses: coverallsapp/github-action@master with: github-token: ${{ secrets.github_token }} parallel-finished: true proxy-addr-2.0.7/.gitignore000066400000000000000000000000671405530270300156030ustar00rootroot00000000000000.nyc_output/ coverage/ node_modules/ package-lock.json proxy-addr-2.0.7/HISTORY.md000066400000000000000000000056571405530270300153100ustar00rootroot000000000000002.0.7 / 2021-05-31 ================== * deps: forwarded@0.2.0 - Use `req.socket` over deprecated `req.connection` 2.0.6 / 2020-02-24 ================== * deps: ipaddr.js@1.9.1 2.0.5 / 2019-04-16 ================== * deps: ipaddr.js@1.9.0 2.0.4 / 2018-07-26 ================== * deps: ipaddr.js@1.8.0 2.0.3 / 2018-02-19 ================== * deps: ipaddr.js@1.6.0 2.0.2 / 2017-09-24 ================== * deps: forwarded@~0.1.2 - perf: improve header parsing - perf: reduce overhead when no `X-Forwarded-For` header 2.0.1 / 2017-09-10 ================== * deps: forwarded@~0.1.1 - Fix trimming leading / trailing OWS - perf: hoist regular expression * deps: ipaddr.js@1.5.2 2.0.0 / 2017-08-08 ================== * Drop support for Node.js below 0.10 1.1.5 / 2017-07-25 ================== * Fix array argument being altered * deps: ipaddr.js@1.4.0 1.1.4 / 2017-03-24 ================== * deps: ipaddr.js@1.3.0 1.1.3 / 2017-01-14 ================== * deps: ipaddr.js@1.2.0 1.1.2 / 2016-05-29 ================== * deps: ipaddr.js@1.1.1 - Fix IPv6-mapped IPv4 validation edge cases 1.1.1 / 2016-05-03 ================== * Fix regression matching mixed versions against multiple subnets 1.1.0 / 2016-05-01 ================== * Fix accepting various invalid netmasks - IPv4 netmasks must be contingous - IPv6 addresses cannot be used as a netmask * deps: ipaddr.js@1.1.0 1.0.10 / 2015-12-09 =================== * deps: ipaddr.js@1.0.5 - Fix regression in `isValid` with non-string arguments 1.0.9 / 2015-12-01 ================== * deps: ipaddr.js@1.0.4 - Fix accepting some invalid IPv6 addresses - Reject CIDRs with negative or overlong masks * perf: enable strict mode 1.0.8 / 2015-05-10 ================== * deps: ipaddr.js@1.0.1 1.0.7 / 2015-03-16 ================== * deps: ipaddr.js@0.1.9 - Fix OOM on certain inputs to `isValid` 1.0.6 / 2015-02-01 ================== * deps: ipaddr.js@0.1.8 1.0.5 / 2015-01-08 ================== * deps: ipaddr.js@0.1.6 1.0.4 / 2014-11-23 ================== * deps: ipaddr.js@0.1.5 - Fix edge cases with `isValid` 1.0.3 / 2014-09-21 ================== * Use `forwarded` npm module 1.0.2 / 2014-09-18 ================== * Fix a global leak when multiple subnets are trusted * Support Node.js 0.6 * deps: ipaddr.js@0.1.3 1.0.1 / 2014-06-03 ================== * Fix links in npm package 1.0.0 / 2014-05-08 ================== * Add `trust` argument to determine proxy trust on * Accepts custom function * Accepts IPv4/IPv6 address(es) * Accepts subnets * Accepts pre-defined names * Add optional `trust` argument to `proxyaddr.all` to stop at first untrusted * Add `proxyaddr.compile` to pre-compile `trust` function to make subsequent calls faster 0.0.1 / 2014-05-04 ================== * Fix bad npm publish 0.0.0 / 2014-05-04 ================== * Initial release proxy-addr-2.0.7/LICENSE000066400000000000000000000021061405530270300146140ustar00rootroot00000000000000(The MIT License) Copyright (c) 2014-2016 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. proxy-addr-2.0.7/README.md000066400000000000000000000100431405530270300150650ustar00rootroot00000000000000# proxy-addr [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-url] [![Node.js Version][node-image]][node-url] [![Build Status][ci-image]][ci-url] [![Test Coverage][coveralls-image]][coveralls-url] Determine address of proxied request ## Install This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): ```sh $ npm install proxy-addr ``` ## API ```js var proxyaddr = require('proxy-addr') ``` ### proxyaddr(req, trust) Return the address of the request, using the given `trust` parameter. The `trust` argument is a function that returns `true` if you trust the address, `false` if you don't. The closest untrusted address is returned. ```js proxyaddr(req, function (addr) { return addr === '127.0.0.1' }) proxyaddr(req, function (addr, i) { return i < 1 }) ``` The `trust` arugment may also be a single IP address string or an array of trusted addresses, as plain IP addresses, CIDR-formatted strings, or IP/netmask strings. ```js proxyaddr(req, '127.0.0.1') proxyaddr(req, ['127.0.0.0/8', '10.0.0.0/8']) proxyaddr(req, ['127.0.0.0/255.0.0.0', '192.168.0.0/255.255.0.0']) ``` This module also supports IPv6. Your IPv6 addresses will be normalized automatically (i.e. `fe80::00ed:1` equals `fe80:0:0:0:0:0:ed:1`). ```js proxyaddr(req, '::1') proxyaddr(req, ['::1/128', 'fe80::/10']) ``` This module will automatically work with IPv4-mapped IPv6 addresses as well to support node.js in IPv6-only mode. This means that you do not have to specify both `::ffff:a00:1` and `10.0.0.1`. As a convenience, this module also takes certain pre-defined names in addition to IP addresses, which expand into IP addresses: ```js proxyaddr(req, 'loopback') proxyaddr(req, ['loopback', 'fc00:ac:1ab5:fff::1/64']) ``` * `loopback`: IPv4 and IPv6 loopback addresses (like `::1` and `127.0.0.1`). * `linklocal`: IPv4 and IPv6 link-local addresses (like `fe80::1:1:1:1` and `169.254.0.1`). * `uniquelocal`: IPv4 private addresses and IPv6 unique-local addresses (like `fc00:ac:1ab5:fff::1` and `192.168.0.1`). When `trust` is specified as a function, it will be called for each address to determine if it is a trusted address. The function is given two arguments: `addr` and `i`, where `addr` is a string of the address to check and `i` is a number that represents the distance from the socket address. ### proxyaddr.all(req, [trust]) Return all the addresses of the request, optionally stopping at the first untrusted. This array is ordered from closest to furthest (i.e. `arr[0] === req.connection.remoteAddress`). ```js proxyaddr.all(req) ``` The optional `trust` argument takes the same arguments as `trust` does in `proxyaddr(req, trust)`. ```js proxyaddr.all(req, 'loopback') ``` ### proxyaddr.compile(val) Compiles argument `val` into a `trust` function. This function takes the same arguments as `trust` does in `proxyaddr(req, trust)` and returns a function suitable for `proxyaddr(req, trust)`. ```js var trust = proxyaddr.compile('loopback') var addr = proxyaddr(req, trust) ``` This function is meant to be optimized for use against every request. It is recommend to compile a trust function up-front for the trusted configuration and pass that to `proxyaddr(req, trust)` for each request. ## Testing ```sh $ npm test ``` ## Benchmarks ```sh $ npm run-script bench ``` ## License [MIT](LICENSE) [ci-image]: https://badgen.net/github/checks/jshttp/proxy-addr/master?label=ci [ci-url]: https://github.com/jshttp/proxy-addr/actions?query=workflow%3Aci [coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/proxy-addr/master [coveralls-url]: https://coveralls.io/r/jshttp/proxy-addr?branch=master [node-image]: https://badgen.net/npm/node/proxy-addr [node-url]: https://nodejs.org/en/download [npm-downloads-image]: https://badgen.net/npm/dm/proxy-addr [npm-url]: https://npmjs.org/package/proxy-addr [npm-version-image]: https://badgen.net/npm/v/proxy-addr proxy-addr-2.0.7/benchmark/000077500000000000000000000000001405530270300155425ustar00rootroot00000000000000proxy-addr-2.0.7/benchmark/compiling.js000066400000000000000000000016641405530270300200700ustar00rootroot00000000000000 /** * Globals for benchmark.js */ global.proxyaddr = require('..') global.createReq = createReq /** * Module dependencies. */ var benchmark = require('benchmark') var benchmarks = require('beautify-benchmark') var suite = new benchmark.Suite() suite.add({ name: 're-compiling', minSamples: 100, fn: 'proxyaddr(req, "loopback")', setup: 'req = createReq("127.0.0.1", "10.0.0.1")' }) suite.add({ name: 'pre-compiling', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile("loopback")' }) suite.on('cycle', function onCycle (event) { benchmarks.add(event.target) }) suite.on('complete', function onComplete () { benchmarks.log() }) suite.run({ async: false }) function createReq (socketAddr, forwardedFor) { return { connection: { remoteAddress: socketAddr }, headers: { 'x-forwarded-for': (forwardedFor || '') } } } proxy-addr-2.0.7/benchmark/index.js000066400000000000000000000012161405530270300172070ustar00rootroot00000000000000var fs = require('fs') var path = require('path') var spawn = require('child_process').spawn var exe = process.argv[0] var cwd = process.cwd() runScripts(fs.readdirSync(__dirname)) function runScripts (fileNames) { var fileName = fileNames.shift() if (!fileName) return if (!/\.js$/i.test(fileName)) return runScripts(fileNames) if (fileName.toLowerCase() === 'index.js') return runScripts(fileNames) var fullPath = path.join(__dirname, fileName) console.log('> %s %s', exe, path.relative(cwd, fullPath)) var proc = spawn(exe, [fullPath], { stdio: 'inherit' }) proc.on('exit', function () { runScripts(fileNames) }) } proxy-addr-2.0.7/benchmark/kind.js000066400000000000000000000021641405530270300170300ustar00rootroot00000000000000 /** * Globals for benchmark.js */ global.proxyaddr = require('..') global.createReq = createReq /** * Module dependencies. */ var benchmark = require('benchmark') var benchmarks = require('beautify-benchmark') var suite = new benchmark.Suite() suite.add({ name: 'ipv4', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile("127.0.0.1")' }) suite.add({ name: 'ipv4-mapped', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("::ffff:7f00:1", "10.0.0.1"); trust = proxyaddr.compile("127.0.0.1")' }) suite.add({ name: 'ipv6', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("::1", "10.0.0.1"); trust = proxyaddr.compile("::1")' }) suite.on('cycle', function onCycle (event) { benchmarks.add(event.target) }) suite.on('complete', function onComplete () { benchmarks.log() }) suite.run({ async: false }) function createReq (socketAddr, forwardedFor) { return { connection: { remoteAddress: socketAddr }, headers: { 'x-forwarded-for': (forwardedFor || '') } } } proxy-addr-2.0.7/benchmark/matching.js000066400000000000000000000032511405530270300176730ustar00rootroot00000000000000 /** * Globals for benchmark.js */ global.proxyaddr = require('..') global.createReq = createReq /** * Module dependencies. */ var benchmark = require('benchmark') var benchmarks = require('beautify-benchmark') var suite = new benchmark.Suite() suite.add({ name: 'trust none', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile([])' }) suite.add({ name: 'trust all', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = function() {return true}' }) suite.add({ name: 'trust single', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile("127.0.0.1")' }) suite.add({ name: 'trust first', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = function(a, i) {return i<1}' }) suite.add({ name: 'trust subnet', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile("127.0.0.1/8")' }) suite.add({ name: 'trust multiple', minSamples: 100, fn: 'proxyaddr(req, trust)', setup: 'req = createReq("127.0.0.1", "10.0.0.1"); trust = proxyaddr.compile(["127.0.0.1", "10.0.0.1"])' }) suite.on('cycle', function onCycle (event) { benchmarks.add(event.target) }) suite.on('complete', function onComplete () { benchmarks.log() }) suite.run({ async: false }) function createReq (socketAddr, forwardedFor) { return { connection: { remoteAddress: socketAddr }, headers: { 'x-forwarded-for': (forwardedFor || '') } } } proxy-addr-2.0.7/index.js000066400000000000000000000135601405530270300152620ustar00rootroot00000000000000/*! * proxy-addr * Copyright(c) 2014-2016 Douglas Christopher Wilson * MIT Licensed */ 'use strict' /** * Module exports. * @public */ module.exports = proxyaddr module.exports.all = alladdrs module.exports.compile = compile /** * Module dependencies. * @private */ var forwarded = require('forwarded') var ipaddr = require('ipaddr.js') /** * Variables. * @private */ var DIGIT_REGEXP = /^[0-9]+$/ var isip = ipaddr.isValid var parseip = ipaddr.parse /** * Pre-defined IP ranges. * @private */ var IP_RANGES = { linklocal: ['169.254.0.0/16', 'fe80::/10'], loopback: ['127.0.0.1/8', '::1/128'], uniquelocal: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7'] } /** * Get all addresses in the request, optionally stopping * at the first untrusted. * * @param {Object} request * @param {Function|Array|String} [trust] * @public */ function alladdrs (req, trust) { // get addresses var addrs = forwarded(req) if (!trust) { // Return all addresses return addrs } if (typeof trust !== 'function') { trust = compile(trust) } for (var i = 0; i < addrs.length - 1; i++) { if (trust(addrs[i], i)) continue addrs.length = i + 1 } return addrs } /** * Compile argument into trust function. * * @param {Array|String} val * @private */ function compile (val) { if (!val) { throw new TypeError('argument is required') } var trust if (typeof val === 'string') { trust = [val] } else if (Array.isArray(val)) { trust = val.slice() } else { throw new TypeError('unsupported trust argument') } for (var i = 0; i < trust.length; i++) { val = trust[i] if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) { continue } // Splice in pre-defined range val = IP_RANGES[val] trust.splice.apply(trust, [i, 1].concat(val)) i += val.length - 1 } return compileTrust(compileRangeSubnets(trust)) } /** * Compile `arr` elements into range subnets. * * @param {Array} arr * @private */ function compileRangeSubnets (arr) { var rangeSubnets = new Array(arr.length) for (var i = 0; i < arr.length; i++) { rangeSubnets[i] = parseipNotation(arr[i]) } return rangeSubnets } /** * Compile range subnet array into trust function. * * @param {Array} rangeSubnets * @private */ function compileTrust (rangeSubnets) { // Return optimized function based on length var len = rangeSubnets.length return len === 0 ? trustNone : len === 1 ? trustSingle(rangeSubnets[0]) : trustMulti(rangeSubnets) } /** * Parse IP notation string into range subnet. * * @param {String} note * @private */ function parseipNotation (note) { var pos = note.lastIndexOf('/') var str = pos !== -1 ? note.substring(0, pos) : note if (!isip(str)) { throw new TypeError('invalid IP address: ' + str) } var ip = parseip(str) if (pos === -1 && ip.kind() === 'ipv6' && ip.isIPv4MappedAddress()) { // Store as IPv4 ip = ip.toIPv4Address() } var max = ip.kind() === 'ipv6' ? 128 : 32 var range = pos !== -1 ? note.substring(pos + 1, note.length) : null if (range === null) { range = max } else if (DIGIT_REGEXP.test(range)) { range = parseInt(range, 10) } else if (ip.kind() === 'ipv4' && isip(range)) { range = parseNetmask(range) } else { range = null } if (range <= 0 || range > max) { throw new TypeError('invalid range on address: ' + note) } return [ip, range] } /** * Parse netmask string into CIDR range. * * @param {String} netmask * @private */ function parseNetmask (netmask) { var ip = parseip(netmask) var kind = ip.kind() return kind === 'ipv4' ? ip.prefixLengthFromSubnetMask() : null } /** * Determine address of proxied request. * * @param {Object} request * @param {Function|Array|String} trust * @public */ function proxyaddr (req, trust) { if (!req) { throw new TypeError('req argument is required') } if (!trust) { throw new TypeError('trust argument is required') } var addrs = alladdrs(req, trust) var addr = addrs[addrs.length - 1] return addr } /** * Static trust function to trust nothing. * * @private */ function trustNone () { return false } /** * Compile trust function for multiple subnets. * * @param {Array} subnets * @private */ function trustMulti (subnets) { return function trust (addr) { if (!isip(addr)) return false var ip = parseip(addr) var ipconv var kind = ip.kind() for (var i = 0; i < subnets.length; i++) { var subnet = subnets[i] var subnetip = subnet[0] var subnetkind = subnetip.kind() var subnetrange = subnet[1] var trusted = ip if (kind !== subnetkind) { if (subnetkind === 'ipv4' && !ip.isIPv4MappedAddress()) { // Incompatible IP addresses continue } if (!ipconv) { // Convert IP to match subnet IP kind ipconv = subnetkind === 'ipv4' ? ip.toIPv4Address() : ip.toIPv4MappedAddress() } trusted = ipconv } if (trusted.match(subnetip, subnetrange)) { return true } } return false } } /** * Compile trust function for single subnet. * * @param {Object} subnet * @private */ function trustSingle (subnet) { var subnetip = subnet[0] var subnetkind = subnetip.kind() var subnetisipv4 = subnetkind === 'ipv4' var subnetrange = subnet[1] return function trust (addr) { if (!isip(addr)) return false var ip = parseip(addr) var kind = ip.kind() if (kind !== subnetkind) { if (subnetisipv4 && !ip.isIPv4MappedAddress()) { // Incompatible IP addresses return false } // Convert IP to match subnet IP kind ip = subnetisipv4 ? ip.toIPv4Address() : ip.toIPv4MappedAddress() } return ip.match(subnetip, subnetrange) } } proxy-addr-2.0.7/package.json000066400000000000000000000022371405530270300161020ustar00rootroot00000000000000{ "name": "proxy-addr", "description": "Determine address of proxied request", "version": "2.0.7", "author": "Douglas Christopher Wilson ", "license": "MIT", "keywords": [ "ip", "proxy", "x-forwarded-for" ], "repository": "jshttp/proxy-addr", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" }, "devDependencies": { "benchmark": "2.1.4", "beautify-benchmark": "0.2.4", "deep-equal": "1.0.1", "eslint": "7.26.0", "eslint-config-standard": "14.1.1", "eslint-plugin-import": "2.23.4", "eslint-plugin-markdown": "2.2.0", "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "4.3.1", "eslint-plugin-standard": "4.1.0", "mocha": "8.4.0", "nyc": "15.1.0" }, "files": [ "LICENSE", "HISTORY.md", "README.md", "index.js" ], "engines": { "node": ">= 0.10" }, "scripts": { "bench": "node benchmark/index.js", "lint": "eslint .", "test": "mocha --reporter spec --bail --check-leaks test/", "test-ci": "nyc --reporter=lcov --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } } proxy-addr-2.0.7/test/000077500000000000000000000000001405530270300145675ustar00rootroot00000000000000proxy-addr-2.0.7/test/.eslintrc.yml000066400000000000000000000000231405530270300172060ustar00rootroot00000000000000env: mocha: true proxy-addr-2.0.7/test/test.js000066400000000000000000000432231405530270300161100ustar00rootroot00000000000000 var assert = require('assert') var deepEqual = require('deep-equal') var proxyaddr = require('..') describe('proxyaddr(req, trust)', function () { describe('arguments', function () { describe('req', function () { it('should be required', function () { assert.throws(proxyaddr, /req.*required/) }) }) describe('trust', function () { it('should be required', function () { var req = createReq('127.0.0.1') assert.throws(proxyaddr.bind(null, req), /trust.*required/) }) it('should accept a function', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, all)) }) it('should accept an array', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, [])) }) it('should accept a string', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, '127.0.0.1')) }) it('should reject a number', function () { var req = createReq('127.0.0.1') assert.throws(proxyaddr.bind(null, req, 42), /unsupported trust argument/) }) it('should accept IPv4', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, '127.0.0.1')) }) it('should accept IPv6', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, '::1')) }) it('should accept IPv4-style IPv6', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, '::ffff:127.0.0.1')) }) it('should accept pre-defined names', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, 'loopback')) }) it('should accept pre-defined names in array', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, ['loopback', '10.0.0.1'])) }) it('should not alter input array', function () { var arr = ['loopback', '10.0.0.1'] var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.bind(null, req, arr)) strictDeepEqual(arr, ['loopback', '10.0.0.1']) }) it('should reject non-IP', function () { var req = createReq('127.0.0.1') assert.throws(proxyaddr.bind(null, req, 'blargh'), /invalid IP address/) assert.throws(proxyaddr.bind(null, req, '10.0.300.1'), /invalid IP address/) assert.throws(proxyaddr.bind(null, req, '::ffff:30.168.1.9000'), /invalid IP address/) assert.throws(proxyaddr.bind(null, req, '-1'), /invalid IP address/) }) it('should reject bad CIDR', function () { var req = createReq('127.0.0.1') assert.throws(proxyaddr.bind(null, req, '10.0.0.1/internet'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '10.0.0.1/6000'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '::1/6000'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '::ffff:a00:2/136'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '::ffff:a00:2/-1'), /invalid range on address/) }) it('should reject bad netmask', function () { var req = createReq('127.0.0.1') assert.throws(proxyaddr.bind(null, req, '10.0.0.1/255.0.255.0'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '10.0.0.1/ffc0::'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, 'fe80::/ffc0::'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, 'fe80::/255.255.255.0'), /invalid range on address/) assert.throws(proxyaddr.bind(null, req, '::ffff:a00:2/255.255.255.0'), /invalid range on address/) }) it('should be invoked as trust(addr, i)', function () { var log = [] var req = createReq('127.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.1' }) proxyaddr(req, function (addr, i) { return log.push(Array.prototype.slice.call(arguments)) }) strictDeepEqual(log, [ ['127.0.0.1', 0], ['10.0.0.1', 1] ]) }) }) }) describe('with all trusted', function () { it('should return socket address with no headers', function () { var req = createReq('127.0.0.1') assert.strictEqual(proxyaddr(req, all), '127.0.0.1') }) it('should return header value', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1' }) assert.strictEqual(proxyaddr(req, all), '10.0.0.1') }) it('should return furthest header value', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, all), '10.0.0.1') }) }) describe('with none trusted', function () { it('should return socket address with no headers', function () { var req = createReq('127.0.0.1') assert.strictEqual(proxyaddr(req, none), '127.0.0.1') }) it('should return socket address with headers', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, none), '127.0.0.1') }) }) describe('with some trusted', function () { it('should return socket address with no headers', function () { var req = createReq('127.0.0.1') assert.strictEqual(proxyaddr(req, trust10x), '127.0.0.1') }) it('should return socket address when not trusted', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, trust10x), '127.0.0.1') }) it('should return header when socket trusted', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1' }) assert.strictEqual(proxyaddr(req, trust10x), '192.168.0.1') }) it('should return first untrusted after trusted', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, trust10x), '192.168.0.1') }) it('should not skip untrusted', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '10.0.0.3, 192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, trust10x), '192.168.0.1') }) }) describe('when given array', function () { it('should accept literal IP addresses', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['10.0.0.1', '10.0.0.2']), '192.168.0.1') }) it('should not trust non-IP addresses', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2, localhost' }) assert.strictEqual(proxyaddr(req, ['10.0.0.1', '10.0.0.2']), 'localhost') }) it('should return socket address if none match', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['127.0.0.1', '192.168.0.100']), '10.0.0.1') }) describe('when array empty', function () { it('should return socket address ', function () { var req = createReq('127.0.0.1') assert.strictEqual(proxyaddr(req, []), '127.0.0.1') }) it('should return socket address with headers', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, []), '127.0.0.1') }) }) }) describe('when given IPv4 addresses', function () { it('should accept literal IP addresses', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['10.0.0.1', '10.0.0.2']), '192.168.0.1') }) it('should accept CIDR notation', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.200' }) assert.strictEqual(proxyaddr(req, '10.0.0.2/26'), '10.0.0.200') }) it('should accept netmask notation', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.200' }) assert.strictEqual(proxyaddr(req, '10.0.0.2/255.255.255.192'), '10.0.0.200') }) }) describe('when given IPv6 addresses', function () { it('should accept literal IP addresses', function () { var req = createReq('fe80::1', { 'x-forwarded-for': '2002:c000:203::1, fe80::2' }) assert.strictEqual(proxyaddr(req, ['fe80::1', 'fe80::2']), '2002:c000:203::1') }) it('should accept CIDR notation', function () { var req = createReq('fe80::1', { 'x-forwarded-for': '2002:c000:203::1, fe80::ff00' }) assert.strictEqual(proxyaddr(req, 'fe80::/125'), 'fe80::ff00') }) }) describe('when IP versions mixed', function () { it('should match respective versions', function () { var req = createReq('::1', { 'x-forwarded-for': '2002:c000:203::1' }) assert.strictEqual(proxyaddr(req, ['127.0.0.1', '::1']), '2002:c000:203::1') }) it('should not match IPv4 to IPv6', function () { var req = createReq('::1', { 'x-forwarded-for': '2002:c000:203::1' }) assert.strictEqual(proxyaddr(req, '127.0.0.1'), '::1') }) }) describe('when IPv4-mapped IPv6 addresses', function () { it('should match IPv4 trust to IPv6 request', function () { var req = createReq('::ffff:a00:1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['10.0.0.1', '10.0.0.2']), '192.168.0.1') }) it('should match IPv4 netmask trust to IPv6 request', function () { var req = createReq('::ffff:a00:1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['10.0.0.1/16']), '192.168.0.1') }) it('should match IPv6 trust to IPv4 request', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.2' }) assert.strictEqual(proxyaddr(req, ['::ffff:a00:1', '::ffff:a00:2']), '192.168.0.1') }) it('should match CIDR notation for IPv4-mapped address', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.200' }) assert.strictEqual(proxyaddr(req, '::ffff:a00:2/122'), '10.0.0.200') }) it('should match CIDR notation for IPv4-mapped address mixed with IPv6 CIDR', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.200' }) assert.strictEqual(proxyaddr(req, ['::ffff:a00:2/122', 'fe80::/125']), '10.0.0.200') }) it('should match CIDR notation for IPv4-mapped address mixed with IPv4 addresses', function () { var req = createReq('10.0.0.1', { 'x-forwarded-for': '192.168.0.1, 10.0.0.200' }) assert.strictEqual(proxyaddr(req, ['::ffff:a00:2/122', '127.0.0.1']), '10.0.0.200') }) }) describe('when given pre-defined names', function () { it('should accept single pre-defined name', function () { var req = createReq('fe80::1', { 'x-forwarded-for': '2002:c000:203::1, fe80::2' }) assert.strictEqual(proxyaddr(req, 'linklocal'), '2002:c000:203::1') }) it('should accept multiple pre-defined names', function () { var req = createReq('::1', { 'x-forwarded-for': '2002:c000:203::1, fe80::2' }) assert.strictEqual(proxyaddr(req, ['loopback', 'linklocal']), '2002:c000:203::1') }) }) describe('when header contains non-ip addresses', function () { it('should stop at first non-ip after trusted', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': 'myrouter, 127.0.0.1, proxy' }) assert.strictEqual(proxyaddr(req, '127.0.0.1'), 'proxy') }) it('should stop at first malformed ip after trusted', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': 'myrouter, 127.0.0.1, ::8:8:8:8:8:8:8:8:8' }) assert.strictEqual(proxyaddr(req, '127.0.0.1'), '::8:8:8:8:8:8:8:8:8') }) it('should provide all values to function', function () { var log = [] var req = createReq('127.0.0.1', { 'x-forwarded-for': 'myrouter, 127.0.0.1, proxy' }) proxyaddr(req, function (addr, i) { return log.push(Array.prototype.slice.call(arguments)) }) strictDeepEqual(log, [ ['127.0.0.1', 0], ['proxy', 1], ['127.0.0.1', 2] ]) }) }) describe('when socket address undefined', function () { it('should return undefined as address', function () { var req = createReq(undefined) assert.strictEqual(proxyaddr(req, '127.0.0.1'), undefined) }) it('should return undefined even with trusted headers', function () { var req = createReq(undefined, { 'x-forwarded-for': '127.0.0.1, 10.0.0.1' }) assert.strictEqual(proxyaddr(req, '127.0.0.1'), undefined) }) }) }) describe('proxyaddr.all(req, [trust])', function () { describe('arguments', function () { describe('req', function () { it('should be required', function () { assert.throws(proxyaddr.all, /req.*required/) }) }) describe('trust', function () { it('should be optional', function () { var req = createReq('127.0.0.1') assert.doesNotThrow(proxyaddr.all.bind(null, req)) }) }) }) describe('with no headers', function () { it('should return socket address', function () { var req = createReq('127.0.0.1') strictDeepEqual(proxyaddr.all(req), ['127.0.0.1']) }) }) describe('with x-forwarded-for header', function () { it('should include x-forwarded-for', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1' }) strictDeepEqual(proxyaddr.all(req), ['127.0.0.1', '10.0.0.1']) }) it('should include x-forwarded-for in correct order', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) strictDeepEqual(proxyaddr.all(req), ['127.0.0.1', '10.0.0.2', '10.0.0.1']) }) }) describe('with trust argument', function () { it('should stop at first untrusted', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) strictDeepEqual(proxyaddr.all(req, '127.0.0.1'), ['127.0.0.1', '10.0.0.2']) }) it('should be only socket address for no trust', function () { var req = createReq('127.0.0.1', { 'x-forwarded-for': '10.0.0.1, 10.0.0.2' }) strictDeepEqual(proxyaddr.all(req, []), ['127.0.0.1']) }) }) }) describe('proxyaddr.compile(trust)', function () { describe('arguments', function () { describe('trust', function () { it('should be required', function () { assert.throws(proxyaddr.compile, /argument.*required/) }) it('should accept an array', function () { assert.strictEqual(typeof proxyaddr.compile([]), 'function') }) it('should accept a string', function () { assert.strictEqual(typeof proxyaddr.compile('127.0.0.1'), 'function') }) it('should reject a number', function () { assert.throws(proxyaddr.compile.bind(null, 42), /unsupported trust argument/) }) it('should accept IPv4', function () { assert.strictEqual(typeof proxyaddr.compile('127.0.0.1'), 'function') }) it('should accept IPv6', function () { assert.strictEqual(typeof proxyaddr.compile('::1'), 'function') }) it('should accept IPv4-style IPv6', function () { assert.strictEqual(typeof proxyaddr.compile('::ffff:127.0.0.1'), 'function') }) it('should accept pre-defined names', function () { assert.strictEqual(typeof proxyaddr.compile('loopback'), 'function') }) it('should accept pre-defined names in array', function () { assert.strictEqual(typeof proxyaddr.compile(['loopback', '10.0.0.1']), 'function') }) it('should reject non-IP', function () { assert.throws(proxyaddr.compile.bind(null, 'blargh'), /invalid IP address/) assert.throws(proxyaddr.compile.bind(null, '-1'), /invalid IP address/) }) it('should reject bad CIDR', function () { assert.throws(proxyaddr.compile.bind(null, '10.0.0.1/6000'), /invalid range on address/) assert.throws(proxyaddr.compile.bind(null, '::1/6000'), /invalid range on address/) assert.throws(proxyaddr.compile.bind(null, '::ffff:a00:2/136'), /invalid range on address/) assert.throws(proxyaddr.compile.bind(null, '::ffff:a00:2/-46'), /invalid range on address/) }) it('should not alter input array', function () { var arr = ['loopback', '10.0.0.1'] assert.strictEqual(typeof proxyaddr.compile(arr), 'function') strictDeepEqual(arr, ['loopback', '10.0.0.1']) }) }) }) }) function createReq (socketAddr, headers) { return { connection: { remoteAddress: socketAddr }, headers: headers || {} } } function strictDeepEqual (actual, expected, message) { if (assert.deepStrictEqual) { assert.deepStrictEqual(actual, expected, message) } else { assert.ok(deepEqual(actual, expected, { strict: true })) } } function all () { return true } function none () { return false } function trust10x (addr) { return /^10\./.test(addr) }