UNPKG

4.35 kBJavaScriptView Raw
1"use strict";
2
3/**
4 * Module dependencies.
5 */
6
7var _ = require("lodash")
8 , inSubnet = require("insubnet")
9 ;
10
11/**
12 * Firewall prototype.
13 */
14
15var firewall = Firewall.prototype;
16
17/**
18 * Expose `Vantage`.
19 */
20
21module.exports = exports = Firewall;
22
23/**
24 * Initialize a new `Firewall` instance.
25 *
26 * @return {Firewall}
27 * @api public
28 */
29
30function Firewall() {
31 this._rules = [];
32 this._policy = "ACCEPT";
33 return this;
34}
35
36/**
37 * Adds an accept rule.
38 *
39 * @param {String} address
40 * @param {Integer} mask
41 * @return {Firewall}
42 * @api public
43 */
44
45firewall.accept = function(address, mask) {
46 return this._rule(address, mask, "ACCEPT");
47};
48
49/**
50 * Adds a reject rule.
51 *
52 * @param {String} address
53 * @param {Integer} mask
54 * @return {Firewall}
55 * @api public
56 */
57
58firewall.reject = function(address, mask) {
59 return this._rule(address, mask, "REJECT");
60};
61
62/**
63 * Adds a rule.
64 *
65 * @param {String} address
66 * @param {Integer} mask
67 * @return {Firewall}
68 * @api private
69 */
70
71firewall._rule = function(address, mask, rule) {
72
73 var parts = String(address).split("/");
74 var subnet = mask || ((parts.length === 2) ? parts[1] : void 0);
75 var ip = (parts.length === 2) ? parts[0] : address;
76
77 subnet = (subnet === undefined) ? 32 : subnet;
78
79 var valid =
80 (!this._isValidIp(ip)) ? "Invalid IP Address passed: " + ip :
81 (isNaN(subnet)) ? "Invalid subnet mask passed: " + subnet :
82 (subnet > 32) ? "Subnet mask cannot be greater than 32: " + subnet :
83 (subnet < 0) ? "Subnet mask cannot be less than 0: " + subnet :
84 true;
85
86 if (valid !== true) {
87 throw new Error(valid);
88 }
89
90 this._rules.push({
91 ip: ip,
92 subnet: parseFloat(subnet),
93 rule: rule
94 });
95
96 return this;
97
98};
99
100/**
101 * Getter for firewall._rules.
102 *
103 * @return {Array}
104 * @api public
105 */
106
107firewall.rules = function() {
108 return this._rules;
109};
110
111/**
112 * Runs address against policy and
113 * rules, returns a bool determining
114 * whether or not the IP is authorized.
115 *
116 * @param {String} ip
117 * @return {Boolean}
118 * @api public
119 */
120
121firewall.valid = function(ip) {
122
123 var valid;
124
125 var toIPv4 = function(addr) {
126 var parts = String(addr).split(":");
127 return parts[parts.length - 1];
128 };
129
130 var addr =
131 (_.isString(ip)) ? ip :
132 (_.isObject(ip) && ip.family === "IPv6") ? toIPv4(ip.address) :
133 (_.isObject(ip)) ? ip.address : void 0;
134
135 if (!this._isValidIp(addr)) {
136 throw Error("Invalid IP Address passed to Firewall.prototype._process: " + addr);
137 }
138
139 var matches = [];
140 for (var i = 0; i < this._rules.length; ++i) {
141 var match = (inSubnet.Auto(addr, this._rules[i].ip, this._rules[i].subnet));
142 if (match) {
143 matches.push(this._rules[i]);
144 }
145 }
146
147 if (matches.length === 0) {
148 valid = (this._policy === "ACCEPT") ? true : false;
149 return valid;
150 }
151
152 var pick = matches[0];
153 valid = (pick.rule === "ACCEPT") ? true : false;
154 return valid;
155};
156
157/**
158 * Setter / Getter for the firewall's policy.
159 *
160 * @param {String} policy
161 * @return {Firewall}
162 * @api public
163 */
164
165firewall.policy = function(policy) {
166
167 if (policy === undefined) { return this._policy; }
168
169 policy = String(policy).toUpperCase();
170 policy = (policy === "ALLOW") ? "ACCEPT" : policy;
171 policy = (policy === "BLOCK") ? "REJECT" : policy;
172 policy = (policy === "DENY") ? "REJECT" : policy;
173
174 if (["ACCEPT", "REJECT"].indexOf(policy) === -1) {
175 throw Error("Invalid firewall policy passed: " + policy);
176 }
177
178 this._policy = policy;
179 return this;
180};
181
182/**
183 * Resets all firewall settings to default.
184 *
185 * @return {Firewall}
186 * @api public
187 */
188
189firewall.reset = function() {
190 this._rules = [];
191 this._policy = "ACCEPT";
192 return this;
193};
194
195/**
196 * Validates IP address.
197 *
198 * @param {String} ip
199 * @return {Boolean}
200 * @api private
201 */
202
203firewall._isValidIp = function(ip) {
204 return ((/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip)));
205};
206
207/**
208 * Failover for forgetful bears.
209 */
210
211firewall.allow = Firewall.prototype.accept;
212firewall.deny = Firewall.prototype.reject;
213firewall.block = Firewall.prototype.reject;