Project

General

Profile

Download (9.63 KB) Statistics
| Branch: | Tag: | Revision:
1 c0b6fdde jim-p
<?php
2
/*
3
	easyrule.inc.php
4
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 c0b6fdde jim-p
	if ($config['pptpd']['mode'] == "server")
47
		$iflist['pptp'] = "PPTP VPN";
48 dadad8b3 jim-p
49 c0b6fdde jim-p
	if ($config['pppoe']['mode'] == "server")
50
		$iflist['pppoe'] = "PPPoE VPN";
51 dadad8b3 jim-p
52 4d828a9a Ermal Lu?i
	if ($config['l2tp']['mode'] == "server")
53
                $iflist['l2tp'] = "L2TP VPN";
54
55 c0b6fdde jim-p
	/* add ipsec interfaces */
56 dadad8b3 jim-p
	if (isset($config['ipsec']['enable']) || isset($config['ipsec']['mobileclients']['enable'])){
57 c0b6fdde jim-p
		$iflist["enc0"] = "IPSEC";
58
	}
59 dadad8b3 jim-p
60 c0b6fdde jim-p
	if (isset($iflist[$int]))
61
		return $int;
62
63
	foreach ($iflist as $if => $ifd) {
64
		if (strtolower($int) == strtolower($ifd))
65
			return $if;
66
	}
67 dadad8b3 jim-p
68 066afaf1 jim-p
	if (substr($int, 0, 4) == "ovpn")
69
		return "openvpn";
70
71 c0b6fdde jim-p
	return false;
72
}
73
74
function easyrule_block_rule_exists($int = 'wan') {
75
	global $blockaliasname, $config;
76
	/* No rules, we we know it doesn't exist */
77
	if (!is_array($config['filter']['rule'])) {
78
		return false;
79
	}
80
81
	/* Search through the rules for one referencing our alias */
82
	foreach ($config['filter']['rule'] as $rule)
83 f3704cb2 jim-p
		if (!is_array($rule) || !is_array($rule['source']))
84
			continue;
85 c0b6fdde jim-p
		if ($rule['source']['address'] == $blockaliasname . strtoupper($int) && ($rule['interface'] == $int))
86
			return true;
87
	return false;
88
}
89
90
function easyrule_block_rule_create($int = 'wan') {
91
	global $blockaliasname, $config;
92
	/* If the alias doesn't exist, exit.
93
	 * Can't create an empty alias, and we don't know a host */
94
	if (easyrule_block_alias_getid($int) === false)
95
		return false;
96
97
	/* If the rule already exists, no need to do it again */
98
	if (easyrule_block_rule_exists($int))
99
		return true;
100
101
	/* No rules, start a new array */
102
	if (!is_array($config['filter']['rule'])) {
103
		$config['filter']['rule'] = array();
104
	}
105
106
	filter_rules_sort();
107
	$a_filter = &$config['filter']['rule'];
108
109
	/* Make up a new rule */
110
	$filterent = array();
111
	$filterent['type'] = 'block';
112 dadad8b3 jim-p
	$filterent['interface'] = $int;
113 c0b6fdde jim-p
	$filterent['source']['address'] = $blockaliasname . strtoupper($int);
114
	$filterent['destination']['any'] = '';
115
	$filterent['descr'] = "Easy Rule: Blocked from Firewall Log View";
116
117
	$a_filter[] = $filterent;
118
119
	return true;
120
}
121
122
function easyrule_block_alias_getid($int = 'wan') {
123
	global $blockaliasname, $config;
124
	if (!is_array($config['aliases']))
125
		return false;
126
127
	/* Hunt down an alias with the name we want, return its id */
128
	foreach ($config['aliases']['alias'] as $aliasid => $alias)
129
		if ($alias['name'] == $blockaliasname . strtoupper($int))
130
			return $aliasid;
131
132
	return false;
133
}
134
135
function easyrule_block_alias_add($host, $int = 'wan') {
136
	global $blockaliasname, $config;
137
	/* If the host isn't a valid IP address, bail */
138
	if (!is_ipaddr($host))
139
		return false;
140
141
	/* If there are no aliases, start an array */
142
	if (!is_array($config['aliases']['alias']))
143
		$config['aliases']['alias'] = array();
144
145
	$a_aliases = &$config['aliases']['alias'];
146
147
	/* Try to get the ID if the alias already exists */
148
	$id = easyrule_block_alias_getid($int);
149
	if ($id === false)
150
	  unset($id);
151
152
	$alias = array();
153
154
	if (isset($id) && $a_aliases[$id]) {
155
		/* Make sure this IP isn't already in the list. */
156
		if (in_array($host.'/32', explode(" ", $a_aliases[$id]['address'])))
157
			return true;
158
		/* Since the alias already exists, just add to it. */
159
		$alias['name']    = $a_aliases[$id]['name'];
160
		$alias['type']    = $a_aliases[$id]['type'];
161
		$alias['descr']   = $a_aliases[$id]['descr'];
162
163
		$alias['address'] = $a_aliases[$id]['address'] . ' ' . $host . '/32';
164
	 	$alias['detail']  = $a_aliases[$id]['detail'] . 'Entry added ' . date('r') . '||';
165
	} else {
166
		/* Create a new alias with all the proper information */
167
	 	$alias['name']    = $blockaliasname . strtoupper($int);
168
	 	$alias['type']    = 'network';
169
	 	$alias['descr']   = mb_convert_encoding("Hosts blocked from Firewall Log view","HTML-ENTITIES","auto");
170
171
		$alias['address'] = $host . '/32';
172
	 	$alias['detail']  = 'Entry added ' . date('r') . '||';
173
	}
174
175
	/* Replace the old alias if needed, otherwise tack it on the end */
176
	if (isset($id) && $a_aliases[$id])
177
		$a_aliases[$id] = $alias;
178
	else
179
		$a_aliases[] = $alias;
180 9bb8d542 Ermal Lu?i
181
	// Sort list
182
	$a_aliases = msort($a_aliases, "name");
183 c0b6fdde jim-p
184
	return true;
185
}
186
187
function easyrule_block_host_add($host, $int = 'wan') {
188
	global $retval;
189
	/* Bail if the supplied host is not a valid IP address */
190
	if (!is_ipaddr($host))
191
		return false;
192
193
	/* Flag whether or not we need to reload the filter */
194
	$dirty = false;
195
196
	/* Attempt to add this host to the alias */
197
	if (easyrule_block_alias_add($host, $int)) {
198
		$dirty = true;
199
	} else {
200
		/* Couldn't add the alias, or adding the host failed. */
201
		return false;
202
	}
203
204
	/* Attempt to add the firewall rule if it doesn't exist.
205
	 * Failing to add the rule isn't necessarily an error, it may
206
	 * have been modified by the user in some way. Adding to the
207
	 * Alias is what's important.
208
	 */
209
	if (!easyrule_block_rule_exists($int)) {
210
		if (easyrule_block_rule_create($int)) {
211
			$dirty = true;
212
		} else {
213
			return false;
214
		}
215
	}
216
217
	/* If needed, write the config and reload the filter */
218
	if ($dirty) {
219
		write_config();
220
		$retval = filter_configure();
221 865ff9b4 jim-p
		if (!empty($_SERVER['DOCUMENT_ROOT'])) {
222
			header("Location: firewall_aliases.php");
223
			exit;
224
		} else {
225
			return true;
226
		}
227 c0b6fdde jim-p
	} else {
228
		return false;
229
	}
230
}
231
232
function easyrule_pass_rule_add($int, $proto, $srchost, $dsthost, $dstport) {
233
	global $config;
234
235
	/* No rules, start a new array */
236
	if (!is_array($config['filter']['rule'])) {
237
		$config['filter']['rule'] = array();
238
	}
239
240
	filter_rules_sort();
241
	$a_filter = &$config['filter']['rule'];
242
243
	/* Make up a new rule */
244
	$filterent = array();
245
	$filterent['type'] = 'pass';
246
	$filterent['interface'] = $int;
247
	$filterent['descr'] = "Easy Rule: Passed from Firewall Log View";
248
249
	if ($proto != "any")
250
		$filterent['protocol'] = $proto;
251
	else
252
		unset($filterent['protocol']);
253
254
	/* Default to only allow echo requests, since that's what most people want and
255
	 *  it should be a safe choice. */
256
	if ($proto == "icmp")
257
		$filterent['icmptype'] = 'echoreq';
258
259
	pconfig_to_address($filterent['source'], $srchost, 32);
260
	pconfig_to_address($filterent['destination'], $dsthost, 32, '', $dstport, $dstport);
261
262
	$a_filter[] = $filterent;
263
264 998f77a8 jim-p
	write_config($filterent['descr']);
265 c0b6fdde jim-p
	$retval = filter_configure();
266 865ff9b4 jim-p
	if (!empty($_SERVER['DOCUMENT_ROOT'])) {
267
		header("Location: firewall_rules.php?if={$int}");
268
		exit;
269
	} else {
270
		return true;
271
	}
272
}
273
274
function easyrule_parse_block($int, $src) {
275
	if (!empty($src) && !empty($int)) {
276
		if (!is_ipaddr($src)) {
277
			return "Tried to block invalid IP: " . htmlspecialchars($src);
278
		}
279
		$int = easyrule_find_rule_interface($int);
280
		if ($int === false) {
281
			return "Invalid interface for block rule: " . htmlspecialchars($int);
282
		}
283
		if (easyrule_block_host_add($src, $int)) {
284
			return "Host added successfully";
285
		} else {
286
			return "Failed to create block rule, alias, or add host.";
287
		}
288
	} else {
289
		return "Tried to block but had no host IP or interface";
290
	}
291
	return "Unknown block error.";
292
}
293
function easyrule_parse_pass($int, $proto, $src, $dst, $dstport = 0) {
294
	/* Check for valid int, srchost, dsthost, dstport, and proto */
295
	global $protocols_with_ports;
296
297
	if (!empty($int) && !empty($proto) && !empty($src) && !empty($dst)) {
298
		$int = easyrule_find_rule_interface($int);
299
		if ($int === false) {
300
			return "Invalid interface for pass rule: " . htmlspecialchars($int);
301
		}
302
		if (getprotobyname($proto) == -1) {
303
			return "Invalid protocol for pass rule: " . htmlspecialchars($proto);
304
		}
305
		if (!is_ipaddr($src)) {
306
			return "Tried to pass invalid source IP: " . htmlspecialchars($src);
307
		}
308
		if (!is_ipaddr($dst)) {
309
			return "Tried to pass invalid destination IP: " . htmlspecialchars($dst);
310
		}
311
		if (in_array($proto, $protocols_with_ports)) {
312
			if (empty($dstport)) {
313
				return "Missing destination port: " . htmlspecialchars($dstport);
314
			}
315
			if (!is_port($dstport)) {
316
				return "Tried to pass invalid destination port: " . htmlspecialchars($dstport);
317
			}
318
		} else {
319
			$dstport = 0;
320
		}
321
		/* Should have valid input... */
322
		if (easyrule_pass_rule_add($int, $proto, $src, $dst, $dstport)) {
323
			return "Successfully added pass rule!";
324
		} else {
325
			return "Failed to add pass rule.";
326
		}
327
	} else {
328
		return "Missing parameters for pass rule.";
329
	}
330
	return "Unknown pass error.";
331 c0b6fdde jim-p
}
332 9734b054 Scott Ullrich
333
?>