UNPKG

3.55 kBJavaScriptView Raw
1'use strict';
2/**
3 * This plugin whitelists or blacklists source ip addresses
4 */
5
6var debug = require('debug')('plugin:accesscontrol');
7var util = require("util");
8const dns = require('dns');
9
10module.exports.init = function (config /*, logger, stats */) {
11
12 var allow;
13 var deny;
14
15 /**
16 * This method reads allow and/or deby lists from the config.yaml
17 * applies the appropriate rule on the incoming message
18 */
19 function checkAccessControlInfo(sourceIP) {
20 if (config === null) debug('WARNING: insufficient information to run accesscontrol');
21 else if (config.allow === null && config.deny === null) debug('WARNING: insufficient information to run accesscontrol');
22 else if (config.allow !== null) {
23 debug ('allow list: ' + util.inspect(config.allow, 2, true));
24 if (scanIP(config.allow, sourceIP)) {
25 allow = true;
26 }
27 }
28 else if (config.deny !== null) {
29 debug ('deny list: ' + util.inspect(config.deny, 2, true));
30 if (scanIP(config.deny, sourceIP)) {
31 debug ('deny incoming message');
32 deny = true;
33 }
34 }
35 }
36
37 /**
38 * check if the parameter is valid IPv4 address
39 */
40 function checkIsIPV4(entry) {
41 var blocks = entry.split(".");
42 if(blocks.length === 4) {
43 return blocks.every(function(block) {
44 return (block === '*' || (parseInt(block,10) >=0 && parseInt(block,10) <= 255));
45 });
46 }
47 return false;
48 }
49
50 /**
51 * for each list in the allow and deny, make sure they are proper
52 * IPv4 addresses
53 */
54 /* never used
55 function validateIPList(list) {
56 list.forEach(function(entry){
57 if (!checkIsIPV4(entry)) return false;
58 });
59 return true;
60 }
61 */
62
63 function scanIP(list, sourceIP) {
64
65 var sourceOctets = sourceIP.split('.');
66 //no wildcard
67 for (var i=0; i < list.length; i++) {
68 //no wildcard
69 if (list[i].indexOf('*') === -1 && list[i] === sourceIP) {
70 return true;
71 } else if (list[i].indexOf('*') !== -1) { //contains wildcard
72 var listOctets = list[i].split('.');
73 if (octetCompare(listOctets, sourceOctets)) return true;
74 }
75 }
76 //did not match any in the list
77 return false;
78 }
79
80 /**
81 * the allow or deny list contains a wildcard. perform octet level
82 * comparision
83 */
84 function octetCompare (listOctets, sourceOctets) {
85 var compare = false;
86 for (var i=0; i < listOctets.length; i++) {
87 //debug('list ' + listOctets[i] + ' sourceOctets ' + sourceOctets[i]);
88 if (listOctets[i] !== '*' && parseInt(listOctets[i]) === parseInt(sourceOctets[i])) {
89 compare = true;
90 } else if (listOctets[i] !== '*' && parseInt(listOctets[i]) !== parseInt(sourceOctets[i])) {
91 return false;
92 }
93 }
94 return compare;
95 }
96
97 /**
98 * send error message to the user
99 */
100 function sendError(res) {
101 var errorInfo = {
102 "code": "403",
103 "message": "Forbidden"
104 };
105 res.writeHead(403, { 'Content-Type': 'application/json' });
106 res.write(JSON.stringify(errorInfo));
107 res.end();
108 }
109
110 return {
111
112 onrequest: function(req, res, next) {
113 debug('plugin onrequest');
114 var host = req.headers.host;
115 debug ("source ip " + host);
116 var sourceIP = host.split(":");
117
118 if (checkIsIPV4(sourceIP[0])) {
119 checkAccessControlInfo(sourceIP[0]);
120 if (allow === false || deny === true)
121 sendError(res);
122 } else {
123 dns.lookup(sourceIP[0], (err, address, family) => {
124 debug('address: %j family: IPv%s', address, family);
125 if (err) {
126 debug(err);
127 sendError(res);
128 }
129 checkAccessControlInfo(address);
130 if (allow === false || deny === true)
131 sendError(res);
132 });
133 }
134 next();
135 }
136 };
137}
\No newline at end of file