From e4d8943c59cfceba229e2689d67601127e8ceb1a Mon Sep 17 00:00:00 2001 From: Oliver Welter Date: Sun, 18 Jan 2015 15:03:18 +0100 Subject: [PATCH 1/4] Fix inconsistent handling of seperator in easyrule, should fix #4233 --- etc/inc/easyrule.inc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/etc/inc/easyrule.inc b/etc/inc/easyrule.inc index 25219ce535..978f21e091 100644 --- a/etc/inc/easyrule.inc +++ b/etc/inc/easyrule.inc @@ -167,16 +167,32 @@ function easyrule_block_alias_add($host, $int = 'wan') { } if (isset($id) && $a_aliases[$id]) { - /* Make sure this IP isn't already in the list. */ - if (in_array($host.'/'.$mask, explode(" ", $a_aliases[$id]['address']))) - return true; + + // Catch case when the list is empty + if (empty($a_aliases[$id]['address'])) { + $a_address = array(); + $a_detail = array(); + } else { + $a_address = explode(" ", $a_aliases[$id]['address']); + + /* Make sure this IP isn't already in the list. */ + if (in_array($host.'/'.$mask, $a_address)) { + return true; + } + $a_detail = explode("||", $a_aliases[$id]['detail']); + } + /* Since the alias already exists, just add to it. */ $alias['name'] = $a_aliases[$id]['name']; $alias['type'] = $a_aliases[$id]['type']; $alias['descr'] = $a_aliases[$id]['descr']; - $alias['address'] = $a_aliases[$id]['address'] . ' ' . $host . '/' . $mask; - $alias['detail'] = $a_aliases[$id]['detail'] . gettext('Entry added') . ' ' . date('r') . '||'; + $a_address[] = $host.'/'.$mask; + $a_detail[] = gettext('Entry added') . ' ' . date('r'); + + $alias['address'] = join(" ", $a_address); + $alias['detail'] = join("||", $a_detail); + } else { /* Create a new alias with all the proper information */ $alias['name'] = $blockaliasname . strtoupper($int); From 4dedce6d46c92c4ea3ced36d718461fc5e1f8a2d Mon Sep 17 00:00:00 2001 From: Oliver Welter Date: Sun, 18 Jan 2015 14:05:41 +0100 Subject: [PATCH 2/4] Add showblock and unblock options to easyrule CLI tool Block rules added with easyrule block.... can now be listed and removed using the easyrule tool. This is handy to be used with external IDS like tools, e.g fail2ban. --- etc/inc/easyrule.inc | 81 ++++++++++++++++++++++++++++++++++++++++++ usr/local/bin/easyrule | 14 +++++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/etc/inc/easyrule.inc b/etc/inc/easyrule.inc index 978f21e091..cdd327d6ed 100644 --- a/etc/inc/easyrule.inc +++ b/etc/inc/easyrule.inc @@ -348,6 +348,87 @@ function easyrule_parse_block($int, $src, $ipproto = "inet") { } return gettext("Unknown block error."); } + +function easyrule_parse_unblock($int, $host, $ipproto = "inet") { + global $blockaliasname, $config; + + if (!empty($host) && !empty($int)) { + $host = trim($host, "[]"); + if (!is_ipaddr($host) && !is_subnet($host)) { + return gettext("Tried to unblock invalid IP:") . ' ' . htmlspecialchars($host); + } + $real_int = easyrule_find_rule_interface($int); + if ($real_int === false) { + return gettext("Invalid interface for block rule:") . ' ' . htmlspecialchars($int); + } + + /* Try to get the ID - will fail if there are no rules/alias on this interface */ + $id = easyrule_block_alias_getid($real_int); + if ($id === false || !$config['aliases']['alias'][$id]) { + return gettext("No block rules set on interface:") . ' ' . htmlspecialchars($int); + } + + $alias = &$config['aliases']['alias'][$id]; + + if (is_subnet($host)) { + list($host, $mask) = explode("/", $host); + } elseif (is_specialnet($host)) { + $mask = 0; + } elseif (is_ipaddrv6($host)) { + $mask = 128; + } else { + $mask = 32; + } + + // Create the expected string representation + $unblock = $host.'/'.$mask; + + $a_address = explode(" ", $config['aliases']['alias'][$id]['address']); + $a_detail = explode("||", $config['aliases']['alias'][$id]['detail']); + + if(($key = array_search($unblock, $a_address)) !== false) { + unset($a_address[$key]); + unset($a_detail[$key]); + // Write back the result to the config array + $config['aliases']['alias'][$id]['address'] = join(" ", $a_address); + $config['aliases']['alias'][$id]['detail'] = join("||", $a_detail); + + // Update config + write_config(); + $retval = filter_configure(); + if (!empty($_SERVER['DOCUMENT_ROOT'])) { + header("Location: firewall_aliases.php"); + exit; + } else { + return gettext("Host unblocked successfully"); + } + } else { + return gettext("Host ist not on block list: " . $host); + } + } + + return gettext("Tried to unblock but had no host IP or interface"); + +} + +function easyrule_parse_getblock($int = 'wan', $sep = "\n") { + global $blockaliasname, $config; + + $real_int = easyrule_find_rule_interface($int); + if ($real_int === false) { + return gettext("Invalid interface for block rule:") . ' ' . htmlspecialchars($int); + } + + /* Try to get the ID - will fail if there are no rules/alias on this interface */ + $id = easyrule_block_alias_getid($real_int); + + if ($id === false || !$config['aliases']['alias'][$id] || empty($config['aliases']['alias'][$id]['address'])) { + return gettext("No block rules set on interface:") . ' ' . htmlspecialchars($int); + } + return join($sep, explode(" ", $config['aliases']['alias'][$id]['address'])); + +} + function easyrule_parse_pass($int, $proto, $src, $dst, $dstport = 0, $ipproto = "inet") { /* Check for valid int, srchost, dsthost, dstport, and proto */ global $protocols_with_ports; diff --git a/usr/local/bin/easyrule b/usr/local/bin/easyrule index 9850aee7b9..3179ffa621 100755 --- a/usr/local/bin/easyrule +++ b/usr/local/bin/easyrule @@ -96,6 +96,12 @@ if (($argc > 1) && !empty($argv[1])) { case 'block': $message = easyrule_parse_block($argv[2], $argv[3]); break; + case 'unblock': + $message = easyrule_parse_unblock($argv[2], $argv[3]); + break; + case 'showblock': + $message = easyrule_parse_getblock($argv[2]); + break; case 'pass': $message = easyrule_parse_pass($argv[2], $argv[3], $argv[4], $argv[5], $argv[6]); break; @@ -104,7 +110,7 @@ if (($argc > 1) && !empty($argv[1])) { } else { // Print usage: echo "usage:\n"; - echo " Blocking only requires an IP to block\n"; + echo " Blocking only requires an IP to block, block rules can be shown with showblock and revoked using unblock\n"; echo " " . basename($argv[0]) . " block \n"; echo "\n"; echo " Passing requires more detail, as it must be as specific as possible. The destination port is optional if you're using a protocol without a port (e.g. ICMP, OSPF, etc).\n"; @@ -113,6 +119,12 @@ if (($argc > 1) && !empty($argv[1])) { echo " Block example:\n"; echo " " . basename($argv[0]) . " block wan 1.2.3.4\n"; echo "\n"; + echo " Show active blocks example:\n"; + echo " " . basename($argv[0]) . " showblock wan\n"; + echo "\n"; + echo " Unblock example:\n"; + echo " " . basename($argv[0]) . " unblock wan 1.2.3.4\n"; + echo "\n"; echo " Pass example (protocol with port):\n"; echo " " . basename($argv[0]) . " pass wan tcp 1.2.3.4 192.168.0.4 80\n"; echo "\n"; From 5024242538732f2491ec70d9d2905a2adaeb92be Mon Sep 17 00:00:00 2001 From: Oliver Welter Date: Sun, 18 Jan 2015 14:26:03 +0100 Subject: [PATCH 3/4] Derive name from easyrule block alias from the scripts name Allows to use different block lists by using symlinks to the easyrule CLI script --- usr/local/bin/easyrule | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/usr/local/bin/easyrule b/usr/local/bin/easyrule index 3179ffa621..654a79cfac 100755 --- a/usr/local/bin/easyrule +++ b/usr/local/bin/easyrule @@ -91,6 +91,13 @@ function is_specialnet($net) { if (($argc > 1) && !empty($argv[1])) { + + # Automagically derive an alternate alias name from the scripts name + # This allows for using alternate alias lists with just a symlink + if (($alias = basename($argv[0])) != 'easyrule') { + $blockaliasname = ucfirst($alias).'Rules'; + } + $message = ""; switch ($argv[1]) { case 'block': From a6f973a1a9818ec81ddab7037307403463d9b1cf Mon Sep 17 00:00:00 2001 From: Oliver Welter Date: Wed, 27 May 2015 16:52:13 +0200 Subject: [PATCH 4/4] Fix comment style --- usr/local/bin/easyrule | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/bin/easyrule b/usr/local/bin/easyrule index 654a79cfac..462fffc31c 100755 --- a/usr/local/bin/easyrule +++ b/usr/local/bin/easyrule @@ -92,8 +92,8 @@ function is_specialnet($net) { if (($argc > 1) && !empty($argv[1])) { - # Automagically derive an alternate alias name from the scripts name - # This allows for using alternate alias lists with just a symlink + /* Automagically derive an alternate alias name from the scripts name + * This allows for using alternate alias lists with just a symlink */ if (($alias = basename($argv[0])) != 'easyrule') { $blockaliasname = ucfirst($alias).'Rules'; } @@ -139,4 +139,4 @@ if (($argc > 1) && !empty($argv[1])) { echo " " . basename($argv[0]) . " pass wan icmp 1.2.3.4 192.168.0.4\n"; echo "\n"; } -?> \ No newline at end of file +?>