diff --git a/src/etc/inc/rrd.inc b/src/etc/inc/rrd.inc index 16b604743..c3dea903b 100644 --- a/src/etc/inc/rrd.inc +++ b/src/etc/inc/rrd.inc @@ -323,14 +323,7 @@ function rrd_configure($verbose = false, $bootup = false) /* the pf states gathering function. */ $rrdupdatesh .= "\n"; - $rrdupdatesh .= "pfctl_si_out=\"`$pfctl -si > /tmp/pfctl_si_out`\"\n"; - $rrdupdatesh .= "pfctl_ss_out=\"`$pfctl -ss > /tmp/pfctl_ss_out`\"\n"; - $rrdupdatesh .= "pfrate=\"`cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}' | tail -1`\"\n"; - $rrdupdatesh .= "pfstates=\"`cat /tmp/pfctl_ss_out | egrep -v \"<-[^<]*<-|->[^-]*->\" | wc -l | sed 's/ //g'`\"\n"; - $rrdupdatesh .= "pfnat=\"`cat /tmp/pfctl_ss_out | egrep '<-[^<]*<-|->[^-]*->' | wc -l | sed 's/ //g'`\"\n"; - $rrdupdatesh .= "srcip=\"`cat /tmp/pfctl_ss_out | egrep -v '<-[^<]*<-|->[^-]*->' | grep -- '->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u | wc -l | sed 's/ //g'`\"\n"; - $rrdupdatesh .= "dstip=\"`cat /tmp/pfctl_ss_out | egrep -v '<-[^<]*<-|->[^-]*->' | grep -- '<-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u | wc -l | sed 's/ //g'`\"\n"; - $rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n"; + $rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:`/usr/local/opnsense/scripts/system/rrd_pfstate_info.py`\n\n"; /* End pf states statistics */ /* CPU, create CPU statistics database */ diff --git a/src/opnsense/scripts/system/rrd_pfstate_info.py b/src/opnsense/scripts/system/rrd_pfstate_info.py new file mode 100755 index 000000000..d2455c5d5 --- /dev/null +++ b/src/opnsense/scripts/system/rrd_pfstate_info.py @@ -0,0 +1,52 @@ +#!/usr/local/bin/python3 + +""" + Copyright (c) 2023 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import subprocess + +if __name__ == '__main__': + result = {'pfrate': 0.0, 'pfstates': 0, 'pfnat': 0, 'srcip': 0, 'dstip': 0} + for row in subprocess.run(['/sbin/pfctl', '-si'], capture_output=True, text=True).stdout.split('\n'): + parts = row.split() + if len(parts) < 2: + continue + elif parts[0] in ['inserts', 'removals']: + result['pfrate'] += float(parts[-1].split('/')[0]) + + src_ips = set() + dst_ips = set() + for row in subprocess.run(['/sbin/pfctl', '-ss'], capture_output=True, text=True).stdout.split('\n'): + parts = row.split() + result['pfstates'] += 1 + if row.find('(') > -1 and row.find(')') > -1: + result['pfnat'] += 1 + if row.find('->') > -1: + src_ips.add(parts[2].split(':')[0]) + elif row.find('<-') > -1: + dst_ips.add(parts[2].split(':')[0]) + result['srcip'] = len(src_ips) + result['dstip'] = len(dst_ips) + print('%(pfrate)0.1f:%(pfstates)d:%(pfnat)d:%(srcip)d:%(dstip)d' % result,end='')