Project

General

Profile

Download (11.5 KB) Statistics
| Branch: | Tag: | Revision:
1 c0b6fdde jim-p
<?php
2
/*
3 ce77a9c4 Phil Davis
	easyrule.inc
4 c0b6fdde jim-p
5 998f77a8 jim-p
	Copyright (C) 2009-2010 Jim Pingle (jpingle@gmail.com)
6
	Originally Sponsored By Anathematic @ pfSense Forums
7 c0b6fdde jim-p
	All rights reserved.
8
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11
12
	1. Redistributions of source code must retain the above copyright notice,
13
	this list of conditions and the following disclaimer.
14
15
	2. Redistributions in binary form must reproduce the above copyright
16
	notice, this list of conditions and the following disclaimer in the
17
	documentation and/or other materials provided with the distribution.
18
19
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
	POSSIBILITY OF SUCH DAMAGE.
29
*/
30 7ac5a4cb Scott Ullrich
/*
31 dadad8b3 jim-p
	pfSense_BUILDER_BINARIES:
32 7ac5a4cb Scott Ullrich
	pfSense_MODULE:	filter
33
*/
34 c0b6fdde jim-p
35
$blockaliasname = 'EasyRuleBlockHosts';
36 865ff9b4 jim-p
$protocols_with_ports = array('tcp', 'udp');
37
require_once("functions.inc");
38
require_once("util.inc");
39
require_once("config.inc");
40 4d828a9a Ermal Lu?i
41 c0b6fdde jim-p
function easyrule_find_rule_interface($int) {
42
	global $config;
43
	/* Borrowed from firewall_rules.php */
44 4d828a9a Ermal Lu?i
	$iflist = get_configured_interface_with_descr(false, true);
45 dadad8b3 jim-p
46 1e0b1727 Phil Davis
	if ($config['pptpd']['mode'] == "server") {
47 c0b6fdde jim-p
		$iflist['pptp'] = "PPTP VPN";
48 1e0b1727 Phil Davis
	}
49 dadad8b3 jim-p
50 1e0b1727 Phil Davis
	if ($config['pppoe']['mode'] == "server") {
51 d3d23754 Chris Buechler
		$iflist['pppoe'] = "PPPoE Server";
52 1e0b1727 Phil Davis
	}
53 dadad8b3 jim-p
54 1e0b1727 Phil Davis
	if ($config['l2tp']['mode'] == "server") {
55
		$iflist['l2tp'] = "L2TP VPN";
56
	}
57 4d828a9a Ermal Lu?i
58 c0b6fdde jim-p
	/* add ipsec interfaces */
59 c6dfd289 jim-p
	if (isset($config['ipsec']['enable']) || isset($config['ipsec']['client']['enable'])){
60 c0b6fdde jim-p
		$iflist["enc0"] = "IPSEC";
61
	}
62 dadad8b3 jim-p
63 1e0b1727 Phil Davis
	if (isset($iflist[$int])) {
64 c0b6fdde jim-p
		return $int;
65 1e0b1727 Phil Davis
	}
66 c0b6fdde jim-p
67
	foreach ($iflist as $if => $ifd) {
68 1e0b1727 Phil Davis
		if (strtolower($int) == strtolower($ifd)) {
69 c0b6fdde jim-p
			return $if;
70 1e0b1727 Phil Davis
		}
71 c0b6fdde jim-p
	}
72 dadad8b3 jim-p
73 1e0b1727 Phil Davis
	if (substr($int, 0, 4) == "ovpn") {
74 066afaf1 jim-p
		return "openvpn";
75 1e0b1727 Phil Davis
	}
76 066afaf1 jim-p
77 c0b6fdde jim-p
	return false;
78
}
79
80 4475997e jim-p
function easyrule_block_rule_exists($int = 'wan', $ipproto = "inet") {
81 c0b6fdde jim-p
	global $blockaliasname, $config;
82
	/* No rules, we we know it doesn't exist */
83
	if (!is_array($config['filter']['rule'])) {
84
		return false;
85
	}
86
87
	/* Search through the rules for one referencing our alias */
88 28a581b8 jim-p
	foreach ($config['filter']['rule'] as $rule) {
89 1e0b1727 Phil Davis
		if (!is_array($rule) || !is_array($rule['source'])) {
90 f3704cb2 jim-p
			continue;
91 1e0b1727 Phil Davis
		}
92 4475997e jim-p
		$checkproto = isset($rule['ipprotocol']) ? $rule['ipprotocol'] : "inet";
93 1e0b1727 Phil Davis
		if ($rule['source']['address'] == $blockaliasname . strtoupper($int) && ($rule['interface'] == $int) && ($checkproto == $ipproto)) {
94 c0b6fdde jim-p
			return true;
95 1e0b1727 Phil Davis
		}
96 28a581b8 jim-p
	}
97 c0b6fdde jim-p
	return false;
98
}
99
100 64eda26c jim-p
function easyrule_block_rule_create($int = 'wan', $ipproto = "inet") {
101 c0b6fdde jim-p
	global $blockaliasname, $config;
102
	/* If the alias doesn't exist, exit.
103
	 * Can't create an empty alias, and we don't know a host */
104 1e0b1727 Phil Davis
	if (easyrule_block_alias_getid($int) === false) {
105 c0b6fdde jim-p
		return false;
106 1e0b1727 Phil Davis
	}
107 c0b6fdde jim-p
108
	/* If the rule already exists, no need to do it again */
109 1e0b1727 Phil Davis
	if (easyrule_block_rule_exists($int, $ipproto)) {
110 c0b6fdde jim-p
		return true;
111 1e0b1727 Phil Davis
	}
112 c0b6fdde jim-p
113
	/* No rules, start a new array */
114
	if (!is_array($config['filter']['rule'])) {
115
		$config['filter']['rule'] = array();
116
	}
117
118
	filter_rules_sort();
119
	$a_filter = &$config['filter']['rule'];
120
121
	/* Make up a new rule */
122
	$filterent = array();
123
	$filterent['type'] = 'block';
124 dadad8b3 jim-p
	$filterent['interface'] = $int;
125 64eda26c jim-p
	$filterent['ipprotocol'] = $ipproto;
126 c0b6fdde jim-p
	$filterent['source']['address'] = $blockaliasname . strtoupper($int);
127
	$filterent['destination']['any'] = '';
128 5bd033a0 Renato Botelho
	$filterent['descr'] = gettext("Easy Rule: Blocked from Firewall Log View");
129 ba1d9714 jim-p
	$filterent['created'] = make_config_revision_entry(null, gettext("Easy Rule"));
130 c0b6fdde jim-p
131 a0140246 jim-p
	array_splice($a_filter, 0, 0, array($filterent));
132 c0b6fdde jim-p
133
	return true;
134
}
135
136
function easyrule_block_alias_getid($int = 'wan') {
137
	global $blockaliasname, $config;
138 1e0b1727 Phil Davis
	if (!is_array($config['aliases'])) {
139 c0b6fdde jim-p
		return false;
140 1e0b1727 Phil Davis
	}
141 c0b6fdde jim-p
142
	/* Hunt down an alias with the name we want, return its id */
143 1e0b1727 Phil Davis
	foreach ($config['aliases']['alias'] as $aliasid => $alias) {
144
		if ($alias['name'] == $blockaliasname . strtoupper($int)) {
145 c0b6fdde jim-p
			return $aliasid;
146 1e0b1727 Phil Davis
		}
147
	}
148 c0b6fdde jim-p
149
	return false;
150
}
151
152
function easyrule_block_alias_add($host, $int = 'wan') {
153
	global $blockaliasname, $config;
154
	/* If the host isn't a valid IP address, bail */
155 b4147482 jim-p
	$host = trim($host, "[]");
156 1e0b1727 Phil Davis
	if (!is_ipaddr($host) && !is_subnet($host)) {
157 c0b6fdde jim-p
		return false;
158 1e0b1727 Phil Davis
	}
159 c0b6fdde jim-p
160
	/* If there are no aliases, start an array */
161 1e0b1727 Phil Davis
	if (!is_array($config['aliases']['alias'])) {
162 c0b6fdde jim-p
		$config['aliases']['alias'] = array();
163 1e0b1727 Phil Davis
	}
164 c0b6fdde jim-p
165
	$a_aliases = &$config['aliases']['alias'];
166
167
	/* Try to get the ID if the alias already exists */
168
	$id = easyrule_block_alias_getid($int);
169 1e0b1727 Phil Davis
	if ($id === false) {
170 c0b6fdde jim-p
	  unset($id);
171 1e0b1727 Phil Davis
	}
172 c0b6fdde jim-p
173
	$alias = array();
174
175 0c305760 jim-p
	if (is_subnet($host)) {
176
		list($host, $mask) = explode("/", $host);
177
	} elseif (is_specialnet($host)) {
178
		$mask = 0;
179 b4147482 jim-p
	} elseif (is_ipaddrv6($host)) {
180
		$mask = 128;
181 0c305760 jim-p
	} else {
182
		$mask = 32;
183
	}
184
185 c0b6fdde jim-p
	if (isset($id) && $a_aliases[$id]) {
186
		/* Make sure this IP isn't already in the list. */
187 1e0b1727 Phil Davis
		if (in_array($host.'/'.$mask, explode(" ", $a_aliases[$id]['address']))) {
188 c0b6fdde jim-p
			return true;
189 1e0b1727 Phil Davis
		}
190 c0b6fdde jim-p
		/* Since the alias already exists, just add to it. */
191
		$alias['name']    = $a_aliases[$id]['name'];
192
		$alias['type']    = $a_aliases[$id]['type'];
193
		$alias['descr']   = $a_aliases[$id]['descr'];
194
195 0c305760 jim-p
		$alias['address'] = $a_aliases[$id]['address'] . ' ' . $host . '/' . $mask;
196 5bd033a0 Renato Botelho
		$alias['detail']  = $a_aliases[$id]['detail'] . gettext('Entry added') . ' ' . date('r') . '||';
197 c0b6fdde jim-p
	} else {
198
		/* Create a new alias with all the proper information */
199 1e0b1727 Phil Davis
		$alias['name']    = $blockaliasname . strtoupper($int);
200
		$alias['type']    = 'network';
201 9d3d8d00 Vinicius Coque
		$alias['descr']   = gettext("Hosts blocked from Firewall Log view");
202 c0b6fdde jim-p
203 0c305760 jim-p
		$alias['address'] = $host . '/' . $mask;
204 5bd033a0 Renato Botelho
		$alias['detail']  = gettext('Entry added') . ' ' . date('r') . '||';
205 c0b6fdde jim-p
	}
206
207
	/* Replace the old alias if needed, otherwise tack it on the end */
208 1e0b1727 Phil Davis
	if (isset($id) && $a_aliases[$id]) {
209 c0b6fdde jim-p
		$a_aliases[$id] = $alias;
210 1e0b1727 Phil Davis
	} else {
211 c0b6fdde jim-p
		$a_aliases[] = $alias;
212 1e0b1727 Phil Davis
	}
213 9bb8d542 Ermal Lu?i
214
	// Sort list
215
	$a_aliases = msort($a_aliases, "name");
216 c0b6fdde jim-p
217
	return true;
218
}
219
220 64eda26c jim-p
function easyrule_block_host_add($host, $int = 'wan', $ipproto = "inet") {
221 c0b6fdde jim-p
	global $retval;
222
	/* Bail if the supplied host is not a valid IP address */
223 b4147482 jim-p
	$host = trim($host, "[]");
224 1e0b1727 Phil Davis
	if (!is_ipaddr($host) && !is_subnet($host)) {
225 c0b6fdde jim-p
		return false;
226 1e0b1727 Phil Davis
	}
227 c0b6fdde jim-p
228
	/* Flag whether or not we need to reload the filter */
229
	$dirty = false;
230
231
	/* Attempt to add this host to the alias */
232
	if (easyrule_block_alias_add($host, $int)) {
233
		$dirty = true;
234
	} else {
235
		/* Couldn't add the alias, or adding the host failed. */
236
		return false;
237
	}
238
239
	/* Attempt to add the firewall rule if it doesn't exist.
240
	 * Failing to add the rule isn't necessarily an error, it may
241
	 * have been modified by the user in some way. Adding to the
242
	 * Alias is what's important.
243
	 */
244 64eda26c jim-p
	if (!easyrule_block_rule_exists($int, $ipproto)) {
245
		if (easyrule_block_rule_create($int, $ipproto)) {
246 c0b6fdde jim-p
			$dirty = true;
247
		} else {
248
			return false;
249
		}
250
	}
251
252
	/* If needed, write the config and reload the filter */
253
	if ($dirty) {
254
		write_config();
255
		$retval = filter_configure();
256 865ff9b4 jim-p
		if (!empty($_SERVER['DOCUMENT_ROOT'])) {
257
			header("Location: firewall_aliases.php");
258
			exit;
259
		} else {
260
			return true;
261
		}
262 c0b6fdde jim-p
	} else {
263
		return false;
264
	}
265
}
266
267 bd40781a Seth Mos
function easyrule_pass_rule_add($int, $proto, $srchost, $dsthost, $dstport, $ipproto) {
268 c0b6fdde jim-p
	global $config;
269
270
	/* No rules, start a new array */
271
	if (!is_array($config['filter']['rule'])) {
272
		$config['filter']['rule'] = array();
273
	}
274
275
	filter_rules_sort();
276
	$a_filter = &$config['filter']['rule'];
277
278
	/* Make up a new rule */
279
	$filterent = array();
280
	$filterent['type'] = 'pass';
281
	$filterent['interface'] = $int;
282 bd40781a Seth Mos
	$filterent['ipprotocol'] = $ipproto;
283 5bd033a0 Renato Botelho
	$filterent['descr'] = gettext("Easy Rule: Passed from Firewall Log View");
284 c0b6fdde jim-p
285 1e0b1727 Phil Davis
	if ($proto != "any") {
286 c0b6fdde jim-p
		$filterent['protocol'] = $proto;
287 1e0b1727 Phil Davis
	} else {
288 c0b6fdde jim-p
		unset($filterent['protocol']);
289 1e0b1727 Phil Davis
	}
290 c0b6fdde jim-p
291
	/* Default to only allow echo requests, since that's what most people want and
292
	 *  it should be a safe choice. */
293 1e0b1727 Phil Davis
	if ($proto == "icmp") {
294 c0b6fdde jim-p
		$filterent['icmptype'] = 'echoreq';
295 1e0b1727 Phil Davis
	}
296 c0b6fdde jim-p
297 1e0b1727 Phil Davis
	if ((strtolower($proto) == "icmp6") || (strtolower($proto) == "icmpv6")) {
298 daffbc34 jim-p
		$filterent['protocol'] = "icmp";
299 1e0b1727 Phil Davis
	}
300 daffbc34 jim-p
301 0c305760 jim-p
	if (is_subnet($srchost)) {
302
		list($srchost, $srcmask) = explode("/", $srchost);
303
	} elseif (is_specialnet($srchost)) {
304
		$srcmask = 0;
305 aea83400 Thomas Rieschl
	} elseif (is_ipaddrv6($srchost)) {
306
		$srcmask = 128;
307 0c305760 jim-p
	} else {
308
		$srcmask = 32;
309
	}
310
311
	if (is_subnet($dsthost)) {
312
		list($dsthost, $dstmask) = explode("/", $dsthost);
313
	} elseif (is_specialnet($dsthost)) {
314
		$dstmask = 0;
315 aea83400 Thomas Rieschl
	} elseif (is_ipaddrv6($dsthost)) {
316
		$dstmask = 128;
317 0c305760 jim-p
	} else {
318
		$dstmask = 32;
319
	}
320
321
	pconfig_to_address($filterent['source'], $srchost, $srcmask);
322
	pconfig_to_address($filterent['destination'], $dsthost, $dstmask, '', $dstport, $dstport);
323 c0b6fdde jim-p
324 ba1d9714 jim-p
	$filterent['created'] = make_config_revision_entry(null, gettext("Easy Rule"));
325 c0b6fdde jim-p
	$a_filter[] = $filterent;
326
327 998f77a8 jim-p
	write_config($filterent['descr']);
328 c0b6fdde jim-p
	$retval = filter_configure();
329 865ff9b4 jim-p
	if (!empty($_SERVER['DOCUMENT_ROOT'])) {
330
		header("Location: firewall_rules.php?if={$int}");
331
		exit;
332
	} else {
333
		return true;
334
	}
335
}
336
337 64eda26c jim-p
function easyrule_parse_block($int, $src, $ipproto = "inet") {
338 865ff9b4 jim-p
	if (!empty($src) && !empty($int)) {
339 b4147482 jim-p
		$src = trim($src, "[]");
340 0c305760 jim-p
		if (!is_ipaddr($src) && !is_subnet($src)) {
341 5bd033a0 Renato Botelho
			return gettext("Tried to block invalid IP:") . ' ' . htmlspecialchars($src);
342 865ff9b4 jim-p
		}
343
		$int = easyrule_find_rule_interface($int);
344
		if ($int === false) {
345 5bd033a0 Renato Botelho
			return gettext("Invalid interface for block rule:") . ' ' . htmlspecialchars($int);
346 865ff9b4 jim-p
		}
347 64eda26c jim-p
		if (easyrule_block_host_add($src, $int, $ipproto)) {
348 5bd033a0 Renato Botelho
			return gettext("Host added successfully");
349 865ff9b4 jim-p
		} else {
350 5bd033a0 Renato Botelho
			return gettext("Failed to create block rule, alias, or add host.");
351 865ff9b4 jim-p
		}
352
	} else {
353 5bd033a0 Renato Botelho
		return gettext("Tried to block but had no host IP or interface");
354 865ff9b4 jim-p
	}
355 5bd033a0 Renato Botelho
	return gettext("Unknown block error.");
356 865ff9b4 jim-p
}
357 64eda26c jim-p
function easyrule_parse_pass($int, $proto, $src, $dst, $dstport = 0, $ipproto = "inet") {
358 865ff9b4 jim-p
	/* Check for valid int, srchost, dsthost, dstport, and proto */
359
	global $protocols_with_ports;
360 b4147482 jim-p
	$src = trim($src, "[]");
361
	$dst = trim($dst, "[]");
362 865ff9b4 jim-p
363
	if (!empty($int) && !empty($proto) && !empty($src) && !empty($dst)) {
364
		$int = easyrule_find_rule_interface($int);
365
		if ($int === false) {
366 5bd033a0 Renato Botelho
			return gettext("Invalid interface for pass rule:") . ' ' . htmlspecialchars($int);
367 865ff9b4 jim-p
		}
368
		if (getprotobyname($proto) == -1) {
369 5bd033a0 Renato Botelho
			return gettext("Invalid protocol for pass rule:") . ' ' . htmlspecialchars($proto);
370 865ff9b4 jim-p
		}
371 0c305760 jim-p
		if (!is_ipaddr($src) && !is_subnet($src) && !is_ipaddroralias($src) && !is_specialnet($src)) {
372 5bd033a0 Renato Botelho
			return gettext("Tried to pass invalid source IP:") . ' ' . htmlspecialchars($src);
373 865ff9b4 jim-p
		}
374 0c305760 jim-p
		if (!is_ipaddr($dst) && !is_subnet($dst) && !is_ipaddroralias($dst) && !is_specialnet($dst)) {
375 5bd033a0 Renato Botelho
			return gettext("Tried to pass invalid destination IP:") . ' ' . htmlspecialchars($dst);
376 865ff9b4 jim-p
		}
377
		if (in_array($proto, $protocols_with_ports)) {
378
			if (empty($dstport)) {
379 5bd033a0 Renato Botelho
				return gettext("Missing destination port:") . ' ' . htmlspecialchars($dstport);
380 865ff9b4 jim-p
			}
381 0c305760 jim-p
			if (!is_port($dstport) && ($dstport != "any")) {
382 5bd033a0 Renato Botelho
				return gettext("Tried to pass invalid destination port:") . ' ' . htmlspecialchars($dstport);
383 865ff9b4 jim-p
			}
384
		} else {
385
			$dstport = 0;
386
		}
387
		/* Should have valid input... */
388 bd40781a Seth Mos
		if (easyrule_pass_rule_add($int, $proto, $src, $dst, $dstport, $ipproto)) {
389 5bd033a0 Renato Botelho
			return gettext("Successfully added pass rule!");
390 865ff9b4 jim-p
		} else {
391 5bd033a0 Renato Botelho
			return gettext("Failed to add pass rule.");
392 865ff9b4 jim-p
		}
393
	} else {
394 5bd033a0 Renato Botelho
		return gettext("Missing parameters for pass rule.");
395 865ff9b4 jim-p
	}
396 5bd033a0 Renato Botelho
	return gettext("Unknown pass error.");
397 c0b6fdde jim-p
}
398 9734b054 Scott Ullrich
399 bd40781a Seth Mos
?>