diff --git a/.codeclimate.yml b/.codeclimate.yml index 0e443ca..424a868 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -8,3 +8,16 @@ engines: ratings: paths: - "**.js" + +checks: + return-statements: + enabled: false + file-lines: + config: + threshold: 400 + method-lines: + config: + threshold: 30 +method-complexity: + config: + threshold: 6 \ No newline at end of file diff --git a/index.js b/index.js index ad7ee42..b8bcbe8 100644 --- a/index.js +++ b/index.js @@ -74,12 +74,53 @@ exports.should_skip = function (connection) { return false; } +exports.eachActiveDnsList = async function (connection, zone, nextOnce) { + const type = this.getListType(zone) + + const ips = await this.lookup(connection.remote.ip, zone) + // console.log(`eachActiveDnsList ip ${connection.remote.ip} zone ${zone} type ${type} ips ${ips}`) + + if (!ips) { + if (type === 'block') connection.results.add(this, { pass: zone }) + return + } + + for (const i of ips) { + if (this.cfg[zone] && this.cfg[zone][i]) { + // console.log(`zone: ${zone} i: ${this.cfg[zone][i]}`) + connection.results.add(this, { msg: this.cfg[zone][i] }) + } + } + + if (type === 'allow') { + connection.notes.dnswl = true + connection.results.add(this, { pass: zone }) + return nextOnce(OK, [zone]) + } + + if (type === 'karma') { + if (ips.includes('127.0.0.1')) { + connection.results.add(this, { pass: zone }) + } + else if (ips.includes('127.0.0.2')) { + connection.results.add(this, { fail: zone }) + if (this.cfg.main.search === 'first') nextOnce(DENY, [zone]) + } + else { + connection.results.add(this, { msg: zone }) + } + return + } + + // type=block + connection.results.add(this, { fail: zone }) + if (this.cfg.main.search === 'first') nextOnce(DENY, [zone]) + return ips +} + exports.onConnect = function (next, connection) { // console.log(`onConnect`) - const remote_ip = connection.remote.ip; - // console.log(`onConnect ${remote_ip}`) - if (this.should_skip(connection)) return next(); let calledNext = false @@ -88,75 +129,25 @@ exports.onConnect = function (next, connection) { if (calledNext) return calledNext = true if (code === undefined || zones === undefined) return next() - next(code, `host [${remote_ip}] is listed on ${zones.join(', ')}`) - } - - const plugin = this - - async function eachActiveDnsList (ip, zone) { - const type = plugin.getListType(zone) - - const ips = await plugin.lookup(ip, zone) - // console.log(`eachActiveDnsList ip ${ip} zone ${zone} type ${type} ips ${ips}`) - - if (!ips) { - if (type === 'block') connection.results.add(plugin, { pass: zone }) - return - } - - for (const i of ips) { - if (plugin.cfg[zone] && plugin.cfg[zone][i]) { - // console.log(`zone: ${zone} i: ${plugin.cfg[zone][i]}`) - connection.results.add(plugin, { msg: plugin.cfg[zone][i] }) - } - } - - switch (type) { - case 'allow': - connection.notes.dnswl = true - connection.results.add(plugin, { pass: zone }) - return nextOnce(OK, [zone]) - case 'karma': - plugin.karmaResults(zone, ips, connection, nextOnce) - /* eslint no-fallthrough: 0 */ - case 'block': - default: - connection.results.add(plugin, { fail: zone }) - if (plugin.cfg.main.search === 'first') nextOnce(DENY, [zone]) - } - return ips + next(code, `host [${connection.remote.ip}] is listed on ${zones.join(', ')}`) } const promises = [] for (const zone of this.zones) { // console.log(`promise zone: ${zone}`) - promises.push(eachActiveDnsList(remote_ip, zone)) + promises.push(this.eachActiveDnsList(connection, zone, nextOnce)) } Promise.all(promises).then(() => { // console.log(`Promise.all`) - if (connection.results.get(plugin).fail?.length) { - nextOnce(DENY, connection.results.get(plugin).fail) + if (connection.results.get(this).fail?.length) { + nextOnce(DENY, connection.results.get(this).fail) return } nextOnce() }) } -exports.karmaResults = function (zone, ips, connection, nextOnce) { - - if (ips.includes('127.0.0.1')) { - connection.results.add(this, { pass: zone }) - } - else if (ips.includes('127.0.0.2')) { - connection.results.add(this, { fail: zone }) - if (this.cfg.main.search === 'first') nextOnce(DENY, [zone]) - } - else { - connection.results.add(this, { msg: zone }) - } -} - exports.check_dnswl = (next, connection) => connection.notes.dnswl ? next(OK) : next() function ipQuery (ip, zone) { @@ -186,26 +177,7 @@ exports.lookup = async function (ip, zone) { this.stats_incr_zone(null, zone, start); // Statistics - // Check for a result outside 127/8 - // This should *never* happen on a proper DNS list - if (a && a.find((rec) => { return rec.split('.')[0] !== '127' })) { - this.disable_zone(zone, a); - return; - } - - if (/spamhaus/.test(zone)) { - // https://www.spamhaus.org/news/article/807/using-our-public-mirrors-check-your-return-codes-now - if (a?.includes('127.255.255.252') || a?.includes('127.255.255.254') || a?.includes('127.255.255.255')) { - this.disable_zone(zone, a); - return; - } - } - - // https://www.dnswl.org/?page_id=15 - if ('list.dnswl.org' === zone && a?.includes('127.0.0.255')) { - this.disable_zone(zone, a); - return; - } + if (this.hasSpecialResults(zone, a)) return return a } @@ -224,6 +196,31 @@ exports.lookup = async function (ip, zone) { } } +exports.hasSpecialResults = function (zone, a) { + // Check for a result outside 127/8 + // This should *never* happen on a proper DNS list + if (a && a.find((rec) => { return rec.split('.')[0] !== '127' })) { + this.disable_zone(zone, a); + return true; + } + + if (/spamhaus/.test(zone)) { + // https://www.spamhaus.org/news/article/807/using-our-public-mirrors-check-your-return-codes-now + if (a?.includes('127.255.255.252') || a?.includes('127.255.255.254') || a?.includes('127.255.255.255')) { + this.disable_zone(zone, a); + return true; + } + } + + // https://www.dnswl.org/?page_id=15 + if ('list.dnswl.org' === zone && a?.includes('127.0.0.255')) { + this.disable_zone(zone, a); + return true; + } + + return false +} + exports.stats_incr_zone = function (err, zone, start) { if (!this.cfg.stats.enable) return; @@ -259,7 +256,7 @@ exports.init_redis = function () { exports.getListType = function (zone) { if (this.cfg[zone] === undefined) return 'block' - return this.cfg[zone]?.type || 'block' // default: block + return this.cfg[zone]?.type || 'block' } exports.getListReject = function (zone) { @@ -276,11 +273,10 @@ exports.checkZonePositive = async function (zone, ip) { try { const a = await dns.resolve4(query, 'A') if (a) { - // console.log(`${query} -> ${a}`) // success // const txt = await dns.resolve4(query, 'TXT') // console.log(`${query} -> ${a}\t${txt}`) for (const e of a) { - if (this.cfg[zone][e]) { + if (this.cfg[zone] && this.cfg[zone][e]) { // console.log(this.cfg[zone][e]); // } }