1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var _ = require("lodash")
|
8 | , inSubnet = require("insubnet")
|
9 | ;
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | var firewall = Firewall.prototype;
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | module.exports = exports = Firewall;
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | function Firewall() {
|
31 | this._rules = [];
|
32 | this._policy = "ACCEPT";
|
33 | return this;
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | firewall.accept = function(address, mask) {
|
46 | return this._rule(address, mask, "ACCEPT");
|
47 | };
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | firewall.reject = function(address, mask) {
|
59 | return this._rule(address, mask, "REJECT");
|
60 | };
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | firewall._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 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | firewall.rules = function() {
|
108 | return this._rules;
|
109 | };
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | firewall.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 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | firewall.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 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 | firewall.reset = function() {
|
190 | this._rules = [];
|
191 | this._policy = "ACCEPT";
|
192 | return this;
|
193 | };
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 | firewall._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 |
|
209 |
|
210 |
|
211 | firewall.allow = Firewall.prototype.accept;
|
212 | firewall.deny = Firewall.prototype.reject;
|
213 | firewall.block = Firewall.prototype.reject;
|