From d7fa562d91ae480dc8f3896b8358990bf54d08a2 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 7 Oct 2020 17:02:08 +0200 Subject: [PATCH] feat: is multiaddr private and loopback (#10) --- README.md | 54 ++++++++++++++++++++++++++++ package.json | 10 +++--- src/array-equals.js | 1 + src/multiaddr/is-loopback.js | 17 +++++++++ src/multiaddr/is-private.js | 17 +++++++++ test/multiaddr/is-loopback.spec.js | 57 +++++++++++++++++++++++++++++ test/multiaddr/is-private.spec.js | 58 ++++++++++++++++++++++++++++++ 7 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 src/multiaddr/is-loopback.js create mode 100644 src/multiaddr/is-private.js create mode 100644 test/multiaddr/is-loopback.spec.js create mode 100644 test/multiaddr/is-private.spec.js diff --git a/README.md b/README.md index 5553afd..471eaea 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,60 @@ const ipAndPortToMultiaddr = require('libp2p-utils/src/ip-port-to-multiaddr') const ma = ipAndPortToMultiaddr('127.0.0.1', 9000) ``` +## API + +### multiaddr `.isLoopback(ma)` + +Check if a given multiaddr is a loopback address. + +#### Parameters + +| Name | Type | Description | +|------|------|-------------| +| ma | `Multiaddr` | multiaddr to verify | + +#### Returns + +| Type | Description | +|------|-------------| +| `boolean` | returns true if multiaddr is a loopback address, false otherwise | + +#### Example + +```js +const multiaddr = require('multiaddr') +const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback') + +const ma = multiaddr('/ip4/127.0.0.1/tcp/1000') +isMultiaddrLoopbackAddrs = isLoopback(ma) +``` + +### multiaddr `.isPrivate(ma)` + +Check if a given multiaddr has a private address. + +#### Parameters + +| Name | Type | Description | +|------|------|-------------| +| ma | `Multiaddr` | multiaddr to verify | + +#### Returns + +| Type | Description | +|------|-------------| +| `boolean` | returns true if multiaddr is a private address, false otherwise | + +#### Example + +```js +const multiaddr = require('multiaddr') +const isPrivate = require('libp2p-utils/src/multiaddr/is-private') + +const ma = multiaddr('/ip4/10.0.0.1/tcp/1000') +isMultiaddrPrivateAddrs = isPrivate(ma) +``` + ## Contribute Contributions welcome. Please check out [the issues](https://github.com/libp2p/js-libp2p-utils/issues). diff --git a/package.json b/package.json index d571b20..15ad818 100644 --- a/package.json +++ b/package.json @@ -29,17 +29,19 @@ }, "homepage": "https://github.com/libp2p/js-libp2p-utils#readme", "devDependencies": { - "aegir": "^25.0.0", + "aegir": "^27.0.0", "it-pair": "^1.0.0", "it-pipe": "^1.1.0", - "streaming-iterables": "^5.0.2" + "streaming-iterables": "^5.0.3" }, "dependencies": { "abortable-iterator": "^3.0.0", - "debug": "^4.1.1", + "debug": "^4.2.0", "err-code": "^2.0.3", "ip-address": "^6.1.0", - "multiaddr": "^8.0.0" + "is-loopback-addr": "^1.0.0", + "multiaddr": "^8.0.0", + "private-ip": "^1.0.5" }, "contributors": [ "Vasco Santos ", diff --git a/src/array-equals.js b/src/array-equals.js index e293167..4679e27 100644 --- a/src/array-equals.js +++ b/src/array-equals.js @@ -3,6 +3,7 @@ /** * Verify if two arrays of non primitive types with the "equals" function are equal. * Compatible with multiaddr, peer-id and Buffer. + * * @param {Array<*>} a * @param {Array<*>} b * @returns {boolean} diff --git a/src/multiaddr/is-loopback.js b/src/multiaddr/is-loopback.js new file mode 100644 index 0000000..1c11c1c --- /dev/null +++ b/src/multiaddr/is-loopback.js @@ -0,0 +1,17 @@ +'use strict' + +const isLoopbackAddr = require('is-loopback-addr') + +/** + * Check if a given multiaddr is a loopback address. + * + * @param {Multiaddr} ma + * @returns {boolean} + */ +function isLoopback (ma) { + const { address } = ma.nodeAddress() + + return isLoopbackAddr(address) +} + +module.exports = isLoopback diff --git a/src/multiaddr/is-private.js b/src/multiaddr/is-private.js new file mode 100644 index 0000000..69192b7 --- /dev/null +++ b/src/multiaddr/is-private.js @@ -0,0 +1,17 @@ +'use strict' + +const isIpPrivate = require('private-ip') + +/** + * Check if a given multiaddr has a private address. + * + * @param {Multiaddr} ma + * @returns {boolean} + */ +function isPrivate (ma) { + const { address } = ma.nodeAddress() + + return isIpPrivate(address) +} + +module.exports = isPrivate diff --git a/test/multiaddr/is-loopback.spec.js b/test/multiaddr/is-loopback.spec.js new file mode 100644 index 0000000..2880973 --- /dev/null +++ b/test/multiaddr/is-loopback.spec.js @@ -0,0 +1,57 @@ +/* eslint-env mocha */ +'use strict' + +const { expect } = require('aegir/utils/chai') +const multiaddr = require('multiaddr') + +const isLoopback = require('../../src/multiaddr/is-loopback') + +describe('multiaddr isLoopback', () => { + it('identifies loopback ip4 multiaddrs', () => { + [ + multiaddr('/ip4/127.0.0.1/tcp/1000'), + multiaddr('/ip4/127.0.1.1/tcp/1000'), + multiaddr('/ip4/127.1.1.1/tcp/1000'), + multiaddr('/ip4/127.255.255.255/tcp/1000') + ].forEach(ma => { + expect(isLoopback(ma)).to.eql(true) + }) + }) + + it('identifies non loopback ip4 multiaddrs', () => { + [ + multiaddr('/ip4/101.0.26.90/tcp/1000'), + multiaddr('/ip4/10.0.0.1/tcp/1000'), + multiaddr('/ip4/192.168.0.1/tcp/1000'), + multiaddr('/ip4/172.16.0.1/tcp/1000') + ].forEach(ma => { + expect(isLoopback(ma)).to.eql(false) + }) + }) + + it('identifies loopback ip6 multiaddrs', () => { + [ + multiaddr('/ip6/::1/tcp/1000') + ].forEach(ma => { + expect(isLoopback(ma)).to.eql(true) + }) + }) + + it('identifies non loopback ip6 multiaddrs', () => { + [ + multiaddr('/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/1000'), + multiaddr('/ip6/::/tcp/1000') + ].forEach(ma => { + expect(isLoopback(ma)).to.eql(false) + }) + }) + + it('identifies other multiaddrs as not loopback addresses', () => { + [ + multiaddr('/dns4/wss0.bootstrap.libp2p.io/tcp/443'), + multiaddr('/dns6/wss0.bootstrap.libp2p.io/tcp/443') + ].forEach(ma => { + expect(isLoopback(ma)).to.eql(false) + }) + }) +}) diff --git a/test/multiaddr/is-private.spec.js b/test/multiaddr/is-private.spec.js new file mode 100644 index 0000000..aef5503 --- /dev/null +++ b/test/multiaddr/is-private.spec.js @@ -0,0 +1,58 @@ +/* eslint-env mocha */ +'use strict' + +const { expect } = require('aegir/utils/chai') +const multiaddr = require('multiaddr') + +const isPrivate = require('../../src/multiaddr/is-private') + +describe('multiaddr isPrivate', () => { + it('identifies private ip4 multiaddrs', () => { + [ + multiaddr('/ip4/127.0.0.1/tcp/1000'), + multiaddr('/ip4/10.0.0.1/tcp/1000'), + multiaddr('/ip4/192.168.0.1/tcp/1000'), + multiaddr('/ip4/172.16.0.1/tcp/1000') + ].forEach(ma => { + expect(isPrivate(ma)).to.eql(true) + }) + }) + + it('identifies public ip4 multiaddrs', () => { + [ + multiaddr('/ip4/101.0.26.90/tcp/1000'), + multiaddr('/ip4/40.1.20.9/tcp/1000'), + multiaddr('/ip4/92.168.0.1/tcp/1000'), + multiaddr('/ip4/2.16.0.1/tcp/1000') + ].forEach(ma => { + expect(isPrivate(ma)).to.eql(false) + }) + }) + + it('identifies private ip6 multiaddrs', () => { + [ + multiaddr('/ip6/fd52:8342:fc46:6c91:3ac9:86ff:fe31:7095/tcp/1000'), + multiaddr('/ip6/fd52:8342:fc46:6c91:3ac9:86ff:fe31:1/tcp/1000') + ].forEach(ma => { + expect(isPrivate(ma)).to.eql(true) + }) + }) + + it('identifies public ip6 multiaddrs', () => { + [ + multiaddr('/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/1000'), + multiaddr('/ip6/2000:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/1000') + ].forEach(ma => { + expect(isPrivate(ma)).to.eql(false) + }) + }) + + it('identifies other multiaddrs as not private addresses', () => { + [ + multiaddr('/dns4/wss0.bootstrap.libp2p.io/tcp/443'), + multiaddr('/dns6/wss0.bootstrap.libp2p.io/tcp/443') + ].forEach(ma => { + expect(isPrivate(ma)).to.eql(false) + }) + }) +})