Contador de Regras para Pfsense (Hit Count)
-
Bom dia senhores,
Em uma das minhas consultorias, enquanto explicava sobre sentido das regras, firewall stateful, etc, senti a necessidade de um contador na parte grafica para mostrar ao sysadmin o volume de acesso a cada uma das regras.
Essa feature existe em quase todos os firewalls comerciais então, porque não ter no pfSense? 8)O procedimento de instalação é quase todo via interface web. Não criei um instalador automático por envolver patches em arquivos importantes do pfSense.
FIQUE ATENTO PARA A VERSÃO DO PFSENSE
-
conteúdo dos patches para pfSense 2.1.5
Passo 1:
Instalar os pacotes filer e System PatchesPasso 2:
Criar no pacote filer, o arquivo /etc/inc/rule_count.inc com permissão 0644 com o seguinte conteúdofunction bd_nice_number($n) { // first strip any formatting; $n = (0+str_replace(",","",$n)); // is this a number? if(!is_numeric($n)) return false; // now filter it; if($n>1000000000000) return round(($n/1000000000000),1).'t'; else if($n>1000000000) return round(($n/1000000000),1).'g'; else if($n>1000000) return round(($n/1000000),1).'m'; else if($n>1000) return round(($n/1000),1).'k'; return number_format($n); } $rules_count_array=array(); exec("/sbin/pfctl -vvsr | /usr/bin/grep -A1 USER_RULE:",$cnt_pfctl); if (!empty($cnt_pfctl)) { foreach($cnt_pfctl as $line) { if (preg_match("/USER_RULE:\s+(\w+)/",$line,$m1)){ $cr=$m1[1]; continue; } if (preg_match("/Evaluations:\s+(\d+)\s+Packets:\s+(\d+)\s+Bytes:\s+(\d+)\s+States:\s+(\d+)\s+/",$line,$m2)){ if ($cr != "" && !isset($rules_count_array[$cr][Packets])){ $rules_count_array[$cr]=array('Evaluations'=>$m2[1],'Packets'=>bd_nice_number($m2[2]),'Bytes'=>bd_nice_number($m2[3]),'States'=>$m2[4]); } } } } ?>
Criar no pacote filer, o arquivo /root/create_rule_hashes.php com permissão 0644 com o seguinte conteúdo
require_once("/etc/inc/util.inc"); require_once("/etc/inc/functions.inc"); require_once("/etc/inc/pkg-utils.inc"); require_once("/etc/inc/globals.inc"); global $config; //var_dump($config['filter']['rule'][0]); //var_dump($config['filter']); $new_rules=array(); $count=0; foreach($config['filter']['rule'] as $fr){ if ( !array_key_exists ( 'hash' , $fr )) { $fr['hash']= md5(rand(10000000,99999999)); $count++; } $new_rules[]=$fr; } if ($count > 0) { print "{$count} new hashes created.\n Please reload your rules.\n"; $config['filter']['rule']=$new_rules; write_config(); } ?>
Passo 3:
executar o arquivo criado /root/create_rule_hashes.php via consolecp /conf/config.xml /root/config.bkp.xml && php /root/create_rule_hashes.php
Passo 4:
Criar, salvar, testar e aplicar os seguintes patches em system->patchesDescription: filter_inc_patch
Patch Contents:--- filter.orig.inc 2015-08-11 16:40:29.000000000 +0000 +++ filter.inc 2015-08-11 16:40:33.000000000 +0000 @@ -1947,10 +1947,13 @@ $line = filter_generate_user_rule($rule); $ret['rule'] = $line; $ret['interface'] = $rule['interface']; - if($rule['descr'] != "" and $line != "") + if ($rule['hash'] != "" and $line != "") { + $ret['descr'] = "label \"" . fix_rule_label("USER_RULE: {$rule['hash']}") . "\""; + } elseif ($rule['descr'] != "" and $line != "") { $ret['descr'] = "label \"" . fix_rule_label("USER_RULE: {$rule['descr']}") . "\""; - else + } else { $ret['descr'] = "label \"USER_RULE\""; + } return $ret; }
Base Directory:/etc/inc/ <–-Não esquecer deste campo!!!
Description:firewall_rules_patch
Patch Contents:--- firewall_rules.orig.php 2015-08-11 16:41:35.000000000 +0000 +++ firewall_rules.php 2015-08-11 16:47:46.000000000 +0000 @@ -45,6 +45,7 @@ require_once("functions.inc"); require_once("filter.inc"); require_once("shaper.inc"); +require_once("rule_count.inc"); $pgtitle = array(gettext("Firewall"),gettext("Rules")); $shortcut_section = "firewall"; @@ -352,7 +353,7 @@ - + "> pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_id_tablehead"); ?> @@ -744,9 +745,18 @@ $printicon = true; } } + if (isset($filterent['hash']) && is_array($rules_count_array) && array_key_exists($filterent['hash'],$rules_count_array)) { + $rules_count=$rules_count_array[$filterent['hash']]['Packets']."/".$rules_count_array[$filterent['hash']]['States']; + $rules_title=""; + foreach ($rules_count_array[$filterent['hash']] as $rck => $rcv) { + $rules_title.= "$rck: $rcv\n"; + } + } else { + $rules_count="0/0"; + } ?> - - + + pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_id_tr");
Base Directory:/usr/local/www/
Description:firewall_rules_edit_patch
Patch Contents:--- firewall_rules_edit.orig.php 2015-08-11 16:41:38.000000000 +0000 +++ firewall_rules_edit.php 2015-08-11 16:44:02.000000000 +0000 @@ -108,6 +108,10 @@ if ( isset($a_filter[$id]['updated']) && is_array($a_filter[$id]['updated']) ) $pconfig['updated'] = $a_filter[$id]['updated']; + if (isset($a_filter[$id]['hash']) && is_array($a_filter[$id]['hash'])) { + $pconfig['hash'] = $a_filter[$id]['hash']; + } + if (!isset($a_filter[$id]['type'])) $pconfig['type'] = "pass"; else @@ -730,6 +734,12 @@ if ( isset($a_filter[$id]['created']) && is_array($a_filter[$id]['created']) ) $filterent['created'] = $a_filter[$id]['created']; + if (isset($a_filter[$id]['hash']) && is_array($a_filter[$id]['hash'])) { + $filterent['hash'] = $a_filter[$id]['hash']; + } else { + $filterent['hash'] = md5(rand(10000000,99999999)); + } + $filterent['updated'] = make_config_revision_entry(); // Allow extending of the firewall edit page and include custom input validation @@ -1683,6 +1693,13 @@ + + + + + + +
Base Directory:/usr/local/www/
Depois de criar e salvar cada um dos patches, clique em test e se o resultado do teste for ok, clique em apply
Passo 5:
Edite e salve qualquer regra para atualizar o pfctrl e começar a ver o hit count na interface web. -
Passo a passo para pfSense 2.2.4 (atualizado 24/11/2015) v0.4.1
Passo 1:
Instale os pacotes filer e System PatchesPasso 2:
Crie no pacote filer, o arquivo /etc/inc/rule_count.inc com permissão 0644 e o seguinte conteúdo:$rules_count_array=array(); exec("/sbin/pfctl -vvsr | /usr/bin/grep -A1 ' label '",$cnt_pfctl); if (!empty($cnt_pfctl)) { foreach($cnt_pfctl as $line) { if (preg_match('/@(\d+)\W\d+.*label "(USER_RULE: |)(.*)"/',$line,$m1)){ $cr=$m1[3]; $rl=$m1[2].$m1[3]; $rid=$m1[1]; continue; } if ($cr != "" && preg_match("/Evaluations:\s+(\d+)\s+Packets:\s+(\d+)\s+Bytes:\s+(\d+)\s+States:\s+(\d+)\s+/",$line,$m2)){ if (isset($rules_count_array[$cr][Packets])){ $rules_count_array[$cr]['Packets'] += $m2[2]; $rules_count_array[$cr]['Evaluations'] += $m2[1]; $rules_count_array[$cr]['Bytes'] += $m2[3]; $rules_count_array[$cr]['States'] += $m2[4]; $rules_count_array[$cr]['RuleId'] .= "|$rid"; }else { $rules_count_array[$cr]=array('Evaluations'=>$m2[1],'Packets'=>$m2[2],'Bytes'=>$m2[3],'States'=>$m2[4],'Label'=>$rl,'RuleId'=>$rid); } } } } ?>
Passo 3:
Crie, salve, teste e aplique os seguintes patches em system->patches.Description: filter_inc_patch
Patch Contents:--- filter.orig.inc 2015-08-11 13:17:11.000000000 +0000 +++ filter.inc 2015-08-17 15:05:54.000000000 +0000 @@ -2168,10 +2168,13 @@ $line = filter_generate_user_rule($rule); $ret['rule'] = $line; $ret['interface'] = $rule['interface']; - if($rule['descr'] != "" and $line != "") + if ($rule['tracker'] != "" and $line != "") { + $ret['descr'] = "label \"" . fix_rule_label("USER_RULE: {$rule['tracker']}") . "\""; + } elseif ($rule['descr'] != "" and $line != "") { $ret['descr'] = "label \"" . fix_rule_label("USER_RULE: {$rule['descr']}") . "\""; - else + } else { $ret['descr'] = "label \"USER_RULE\""; + } return $ret; }
Base Directory:/etc/inc/
Description:firewall_rules_patch
Patch Contents:--- firewall_rules.orig.php 2015-08-11 13:27:15.000000000 +0000 +++ firewall_rules.php 2015-08-21 17:13:30.000000000 +0000 @@ -46,10 +46,72 @@ require_once("functions.inc"); require_once("filter.inc"); require_once("shaper.inc"); +require_once("rule_count.inc"); $pgtitle = array(gettext("Firewall"),gettext("Rules")); $shortcut_section = "firewall"; +//Get rule Hit count +function get_rule_ht($tracker,$sum_ht=array()){ + global $g,$rules_count_array; + //check if there is previous values + $packets=(isset($sum_ht['packets']) ? $sum_ht['packets'] : 0); + $states=(isset($sum_ht['bytes']) ? $sum_ht['bytes'] : 0); + $rules_title=(isset($sum_ht['title']) ? $sum_ht['title'] : ""); + $rules_id=array(); + if (preg_match("/\s+/",$tracker)){ + $rules_title.="$tracker\n"; + } + if (is_array($rules_count_array) && array_key_exists($tracker,$rules_count_array)) { + $packets +=$rules_count_array[$tracker]['Packets']; + $states +=$rules_count_array[$tracker]['States']; + foreach ($rules_count_array[$tracker] as $rck => $rcv) { + switch($rck){ + case "Label": + $label=$rcv; + break; + case "RuleId": + $ruleid=$rcv; + break; + default: + $rules_title.= "$rck: ".bd_nice_number($rcv)."\n"; + } + } + } + $hitcount=bd_nice_number($packets)."/".bd_nice_number($states); + if ($states > 0){ + //icon_log.gif + ///themes/pfsense_ng/images/icons/icon_log_d.gif + //$html= + $html="{$hitcount} "; + $html.="![](\"./themes/{$g['theme']}/images/icons/icon_block.gif\")"; + //$resp_info="Kill Rule States {$rulelabel}" . $resp; + } else { + $html="{$hitcount}"; + } + return (array( 'title'=> $rules_title, + 'packets' =>$packets, + 'states' =>$states, + 'html' =>$html + )); +} + +function bd_nice_number($n) { + // first strip any formatting; + $n = (0+str_replace(",","",$n)); + + // is this a number? + if(!is_numeric($n)) return false; + + // now filter it; + if($n>1000000000000) return round(($n/1000000000000),1).'t'; + else if($n>1000000000) return round(($n/1000000000),1).'g'; + else if($n>1000000) return round(($n/1000000),1).'m'; + else if($n>1000) return round(($n/1000),1).'k'; + + return number_format($n); +} + function delete_nat_association($id) { global $config; @@ -135,6 +197,70 @@ $savemsg = sprintf(gettext("The settings have been applied. The firewall rules are now reloading in the background. You can also %s monitor %s the reload progress"),"[","](status_filter_reload.php)"); } + /* handle AJAX operations */ + if($_POST['action'] == "KillRuleStates") { + if (isset($_POST['label'])){ + $rulelabel=html_entity_decode($_POST['label']); + $cnt_pfctlk=array(); + exec("/sbin/pfctl -k label -k \"{$rulelabel}\" 2>&1",$cnt_pfctlk); + } else { + echo gettext("invalid input"); + } + if (!empty($cnt_pfctlk)) { + foreach($cnt_pfctlk as $line) { + print "$line\n"; + } + } + return; + } + if($_POST['action'] == "ShowRuleStates") { + $td1=""; + $td2=""; + //$td2=""; + $resp = ""; + $resp .= ""; + $resp .= $td1 . gettext("Proto") . ""; + $resp .= $td1 . gettext("Source -> Router -> Destination") . ""; + $resp .= $td1 . gettext("State") . ""; + $resp .= $td1 . gettext("Packets") . ""; + $resp .= $td1 . gettext("bytes") . ""; + $resp .= ""; + $state_count=0; + /*if (isset($_POST['label'])){ + $rulelabel=html_entity_decode($_POST['label']); + } + if (isset($_POST['packets'])){ + $packets=html_entity_decode($_POST['packets']); + } + */ + if (isset($_POST['hitcount'])){ + $hitcount=html_entity_decode($_POST['hitcount']); + } + if (isset($_POST['ruleid']) && preg_match("/\d+/",$_POST['ruleid'])){ + $ruleid=html_entity_decode($_POST['ruleid']); + $cnt_pfctls=array(); + exec("/sbin/pfctl -vvss | /usr/bin/grep -EB2 \"rule ({$ruleid})\"",$cnt_pfctls); + } else { + echo gettext("invalid input"); + } + if (!empty($cnt_pfctls)) { + foreach($cnt_pfctls as $line) { + if (preg_match("/^\w+\s+(\w+)\s+(.*)(.-.)(.*)\s+(\w+:\w+)/",$line,$mcon)) { + $state_count++; + $resp .= "{$td2}{$mcon[1]}{$td2}{$mcon[2]}{$mcon[3]}{$mcon[4]}{$td2}{$mcon[5]}"; + } + elseif (preg_match("/age.*, (\S+) pkts, (\S+) bytes, rule (\d+)/",$line,$mrule)) { + list($pkt1,$pkt2)=split(":",$mrule[1],2); + list($bt1,$bt2)=split(":",$mrule[2],2); + $resp .= "{$td2}".bd_nice_number($pkt1)." / ".bd_nice_number($pkt2)."{$td2}".bd_nice_number($bt1)." / ".bd_nice_number($bt2).""; + } + } + } + $resp .= " "; + $html.="<u>{$hitcount}</u>"; + print ($html); + return; + } } if ($_GET['act'] == "del") { @@ -233,7 +359,66 @@ <form action="firewall_rules.php" method="post"> + @@ -272,7 +457,7 @@ - + "> pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_id_tablehead"); ?> @@ -319,11 +504,12 @@ || ((count($config['interfaces']) == 1) && ($if == 'wan')))): $alports = implode(' ', filter_get_antilockout_ports(true)); + $rule_hit_count=get_rule_ht("anti-lockout rule"); ?> ![pass](./themes/<?= $g['theme']; ?>/images/icons/icon_pass.gif) - + pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_id_tr_antilockout"); ?> @@ -351,11 +537,15 @@ - ++ $rule_hit_count=get_rule_ht("Block private networks from " . strtoupper($if) . " block 192.168/16"); + $rule_hit_count=get_rule_ht("Block private networks from " . strtoupper($if) . " block 127/8",$rule_hit_count); + $rule_hit_count=get_rule_ht("Block private networks from " . strtoupper($if) . " block 172.16/12",$rule_hit_count); + $rule_hit_count=get_rule_ht("Block private networks from " . strtoupper($if) . " block 10/8",$rule_hit_count);?> ![block](./themes/<?= $g['theme']; ?>/images/icons/icon_block.gif) - + * * @@ -379,11 +569,14 @@ - ++ $rule_hit_count=get_rule_ht("block bogon IPv4 networks from ".strtoupper($if)); + $rule_hit_count=get_rule_ht("block bogon IPv6 networks from ".strtoupper($if),$rule_hit_count); + ?> ![block](./themes/<?= $g['theme']; ?>/images/icons/icon_block.gif) - + * * @@ -606,9 +799,10 @@ $printicon = true; } } + $rule_hit_count=get_rule_ht($filterent['tracker']); ?> - - + + pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_id_tr"); @@ -816,6 +1010,7 @@ </form> +
Base Directory:/usr/local/www/
Passo 4:
Edit e salve qualquer regra para atualizar o pfctl e começar a ver os hit counts na interface web. -
Este é o Marcello Coutinho…
Seguramente um dos caras que mais contribui no mundo todo com patches e pacotes para o pfSense!
Parabéns novamente pelo trabalho marcelloc!
Abraços!
Jack -
Fantástico!
-
Sempre senti falta desta feature.
Marcelo está de parabéns!
[Off]
Uma coisa que eu mesmo estou pesquisando sobre como fazer é um categorizador, onde o mesmo faria um busca por expressões regulares nas listas do Squidguard. -
Este patch poderia já ser incorporado ao código em uma próxima versão heim Marcelo!? :D
-
Este patch poderia já ser incorporado ao código em uma próxima versão heim Marcelo!? :D
Essa parte não depende de mim. É possível que eu faça o pull request e ele caia no esquecimento…
-
Parabéns Marcelo.
Testado e aprovado em meu ambiente -
Parabéns
Vou testar!
-
Este patch poderia já ser incorporado ao código em uma próxima versão heim Marcelo!? :D
Essa parte não depende de mim. É possível que eu faça o pull request e ele caia no esquecimento…
Trágico.
Marcelo, largue essa vida e vá trabalhar no Core Team rsrs.
Forte abraço
-
Parabéns Marcelo.
Testado e aprovado em meu ambienteJá coloquei em uns 5 :) e já não sei como era pra debugar quantidade de conexões antes disso. :D
-
Marcello, pelo que vi só vai fazer a contagem das regras que o log está ativo?
-
Marcello, pelo que vi só vai fazer a contagem das regras que o log está ativo?
Não, todas as regras criadas pelo sysadmin.
Depois de rodar o php que cria os hashes,```
cp /conf/config.xml /root/config.bkp.xml && php /root/create_rule_hashes.phpRegras criadas pelo nat precisam de um edit/save pra criar o hash.
-
E mais uma vez senhor Marcelo mandando ver!. :D
Fico me perguntando….se esse cara morrer, o que vai ser desse fórum?!PS.
Já revisou seu seguro de vida Marcelo?!...kkkkkkkkkkkk. -
Show de bola! Muito bom esse recurso.
Parabéns pela contribuição.
Abraço!
-
Marcello sei que já falou sobre isso, mas envia novamente essa contribuição, quem sabe dessa vez eles aceitam!
-
Marcello sei que já falou sobre isso, mas envia novamente essa contribuição, quem sabe dessa vez eles aceitam!
vou tentar sim, o Jimp não rejeitou a idéia, o que já é metade do caminho.
Estou reescrevendo ele todo para 2.2, ele testando, vejo se o processo burocratico começa novamente ou se ele mesmo pode fazer o merge na 2.3
https://forum.pfsense.org/index.php?topic=97925.0
-
Legal, vai ficar bom.
-
Publiquei no fórum internacional uma nova vesão que mostra o hit de todas as regras, até as "automaticas" para o pfsense 2.2.4.
https://forum.pfsense.org/index.php?topic=97925.0