Skip to content

Commit

Permalink
Use cfwho as extra data source
Browse files Browse the repository at this point in the history
  • Loading branch information
MattIPv4 committed Feb 2, 2021
1 parent 51d53e9 commit cfc71af
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 31 deletions.
6 changes: 6 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
.idea
.DS_Store
test
.editorconfig
.eslintrc.js
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ Perform RDAP/WHOIS lookups over HTTP

---

The package will attempt to use RDAP data primarily, and will return this if it finds results.
Failing that, it will then perform a standard WHOIS lookup and parse limited results from that.
The package will attempt to perform an RDAP lookup of the query, as well as a WHOIS lookup and a
call to the cfwho service for the query. These results are then combined, preferring data from
RDAP, WHOIS and then cfwho.

The second argument of the method can be set to `true` to indicate that the package should perform
both lookups and combine the results, with the RDAP data being preferred.
The second argument of the method can be set to `true` to indicate that the package should return
the first set of results that it finds, without performing any combining.

```javascript
const lookup = require('web-whois');
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "web-whois",
"version": "0.0.1",
"version": "0.0.2",
"description": "Perform RDAP/WHOIS lookups over HTTP",
"main": "src/index.js",
"keywords": [],
Expand Down
29 changes: 29 additions & 0 deletions src/cfwho.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const fetch = require('node-fetch');
const { uniqueCommaSep, consistentResultObj, consistentResult } = require('./util');

const findAbuseEmail = data => {
const abuse = data.contacts && data.contacts.abuse;
if (!abuse || !Array.isArray(abuse)) return;
return uniqueCommaSep(data.contacts.abuse);
};

module.exports = async query => {
const resp = await fetch(`https://cfwho.com/api/v1/${query}`);
const rawData = await resp.json().catch(() => false);
const data = rawData && rawData[query];

// Ensure the data is there
if (!data || !data.success)
return false;

// Find the useful information for us
const result = consistentResultObj({
name: data.netname,
asn: data.asn,
cidr: data.network,
abuse: findAbuseEmail(data),
});

// Done
return consistentResult(result);
};
32 changes: 23 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
const rdapLookup = require('./rdap');
const whoisLookup = require('./whois');
const cfwhoLookup = require('./cfwho');
const { consistentResultObj, consistentResult } = require('./util');

// TODO: Ingest cfwho.com as third source of info
const combineResults = dataArr => {
const result = {};
for (const data of dataArr)
for (const key of data)
if (data[key] && !result[key]) result[key] = data[key];
return consistentResult(consistentResultObj(result));
};

module.exports = async (query, combine = false) => {
module.exports = async (query, first = false) => {
// Do the RDAP lookup
const rdap = await rdapLookup(query);

// If we have RDAP data and don't need to combine, return it
if (rdap && !combine) return rdap;
// If we have RDAP data and want just the first, return it
if (rdap && first) return rdap;

// Doo the WHOIS lokkup
// Do the WHOIS lokkup
const whois = await whoisLookup(query);

// Combine if we can and need to (preferring RDAP)
if (combine && (rdap || whois)) return { ...(whois || {}), ...(rdap || {}) };
// If we have WHOIS data and want just the first, return it
if (whois && first) return whois;

// Do the cfwho lokkup
const cfwho = await cfwhoLookup(query);

// If we have cfwho data and want just the first, return it
if (cfwho && first) return cfwho;

// Return just the WHOIS data
return whois;
// Combine the results (preferring RDAP, WHOIS, then cfwho)
return combineResults([rdap, whois, cfwho]);
};
9 changes: 3 additions & 6 deletions src/rdap.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
const fetch = require('node-fetch');
const { consistentResultObj } = require('./util');

// Unique values in an array, comma-separated
const uniqueCommaSep = arr => [...new Set(arr)].join(', ');
const { uniqueCommaSep, consistentResultObj, consistentResult } = require('./util');

// Find RDAP data entities that match a name
const findEntities = (name, data) => data.entities && data.entities.filter(entity =>
Expand Down Expand Up @@ -83,6 +80,6 @@ module.exports = async query => {
abuse: findAbuseEmail(data.data),
});

// Return false if we found nothing, otherwise return the data
return Object.values(result).every(x => x === undefined) ? false : result;
// Done
return consistentResult(result);
};
25 changes: 17 additions & 8 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
// Unique values in an array, comma-separated
module.exports.uniqueCommaSep = arr => [...new Set(arr)].join(', ');

const trimmed = item => item && `${item}`.trim();

// Consistent keys for the response from the package
module.exports.consistentResultObj = data => ({
name: data.name || undefined,
registrant: data.registrant || undefined,
asn: data.asn || undefined,
registrar: data.registrar || undefined,
registration: data.registration || undefined,
expiration: data.expiration || undefined,
cidr: data.cidr || undefined,
abuse: data.abuse || undefined,
name: trimmed(data.name) || undefined,
registrant: trimmed(data.registrant) || undefined,
asn: trimmed(data.asn) || undefined,
registrar: trimmed(data.registrar) || undefined,
registration: data.registration || undefined,
expiration: data.expiration || undefined,
cidr: trimmed(data.cidr) || undefined,
abuse: trimmed(data.abuse) || undefined,
});

// If we found nothing, the package returns false
module.exports.consistentResult = data => Object.values(data).every(x => x === undefined) ? false : data;
6 changes: 3 additions & 3 deletions src/whois.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const fetch = require('node-fetch');
const { consistentResultObj } = require('./util');
const { consistentResultObj, consistentResult } = require('./util');

const parseWhois = text => {
// RegExp parts
Expand Down Expand Up @@ -83,6 +83,6 @@ module.exports = async query => {
abuse: findAttribute('registrar abuse contact email', data),
});

// Return false if we found nothing, otherwise return the data
return Object.values(result).every(x => x === undefined) ? false : result;
// Done
return consistentResult(result);
};
28 changes: 28 additions & 0 deletions test/src/cfwho.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const assert = require('assert').strict;
const cfwhoLookup = require('../../src/cfwho');

module.exports = async () => {
// cfwho does not support domains
const resultDomain = await cfwhoLookup('digitalocean.com');
assert.equal(resultDomain, false);

// Data here is potentially fragile
const resultIp = await cfwhoLookup('104.16.181.15');
assert.deepEqual(resultIp, {
name: 'CLOUDFLARENET, US',
registrant: undefined,
asn: '13335',
registrar: undefined,
registration: undefined,
expiration: undefined,
cidr: '104.16.176.0/20',
abuse: '[email protected]',
});

// cfwho does not support ASNs
const resultAsn = await cfwhoLookup('13335');
assert.equal(resultAsn, false);

const resultRandom = await cfwhoLookup('this-is-not-a-valid-query');
assert.equal(resultRandom, false);
};
2 changes: 2 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const rdapTest = require('./src/rdap');
const whoisTest = require('./src/whois');
const cfwhoTest = require('./src/cfwho');
const utilTest = require('./src/util');

const main = async () => {
await rdapTest();
await whoisTest();
await cfwhoTest();
utilTest();
};

Expand Down

0 comments on commit cfc71af

Please sign in to comment.