Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - jonny5

#1
One:
Running IDS mode via PCAP, with buffer modifications

Two:
I've modified the suricata service file to achieve this, not a permanent fix, wanting to discuss and see if it helps others before attempting to see how to integrate this improvement

The whole of my /usr/local/etc/rc.d/suricata:
#                Default: root
# suricata_pidfile (str):    Pidfile to store pid of suricata process
#                Default: /var/run/suricata.pid

. /etc/rc.subr

name="suricata"
rcvar=suricata_enable

start_precmd="suricata_prestart"
command="/usr/local/bin/suricata"

load_rc_config $name

[ -z "$suricata_enable" ]    && suricata_enable="NO"
[ -z "$suricata_conf" ]        && suricata_conf="/usr/local/etc/suricata/suricata.yaml"
# [ -z "$suricata_flags" ]    && suricata_flags="-D"
suricata_flags="-D --pcap-buffer-size=2147483647 -F /usr/local/etc/suricata/capture-filter.bpf"
[ -z "$suricata_divertport" ]    && suricata_divertport="8000"
[ -z "$suricata_netmap" ]    && suricata_netmap="NO"
[ -z "$suricata_user" ]        && suricata_user="root"
[ -z "$suricata_pidfile" ]    && suricata_pidfile="/var/run/suricata.pid"

if [ -n "$suricata_interface" ]; then
    for interface in $suricata_interface; do
        suricata_flags="$suricata_flags --pcap=$interface"
    done
elif [ "$suricata_netmap" != "NO" ]; then
    suricata_flags="$suricata_flags --netmap"
else
    suricata_flags="$suricata_flags -d $suricata_divertport"
    info "Inline Mode on divert port $suricata_divertport (suricata_interface not defined)"
fi

pidfile=$suricata_pidfile
suricata_flags="$suricata_flags --pidfile $pidfile"

[ -n "$suricata_conf" ]    && suricata_flags="$suricata_flags -c $suricata_conf"

suricata_prestart()
{
    if ! run_rc_command status > /dev/null; then
        rm -f "$pidfile"
    fi
}
run_rc_command "$1"

Three:
I've found that if I watch the interfaces/trunks that have the VLANs I get less drops and I believe this is because of fewer "interfaces", I update/modify this in my custom.yaml in /usr/local/etc/suricata/conf.d/custom.yaml it gets loaded after the suricata.yaml and is a permanent element of OPNSense that can be manually changed

Important elements of my custom.yaml:
host-mode: auto
runmode: autofp
default-packet-size: 1584
max-pending-packets: 25000
defrag:
  memcap: 2gb
  hash-size: 65536
  trackers: 65535
  max-frags: 65535
  prealloc: yes
  timeout: 60
flow:
  memcap: 6gb
  hash-size: 65536
  prealloc: 25600
  emergency-recovery: 30
vlan:
  use-for-tracking: true
stream:
  memcap: 6gb
  # memcap-policy: ignore
  checksum-validation: no
  prealloc-sessions: 262144
  #midstream: false
  #midstream-policy: ignore
  inline: no
  bypass: yes
  # midstream-policy: bypass
  reassembly:
    memcap: 1gb
    # memcap-policy: bypass
    depth: 2mb
    toserver-chunk-size: 2560
    toclient-chunk-size: 2560
    randomize-chunk-size: yes
    # randomize-chunk-range: 10
    # raw: yes
    segment-prealloc: 4096
    # check-overlap-different-data: true
mpm-algo: hs
spm-algo: auto
threading:
  set-cpu-affinity: yes
  detect-thread-ratio: 0.75
pcap:
  - interface: ix0
    buffer-size: 2147483647
  - interface: ix1
    buffer-size: 2147483647
  - interface: lagg0
    buffer-size: 2147483647

With PCAP in Autofp mode and threading:set-cpu-affinity: yes and threading:detect-thread-ratio: 0.75 then at least one or more cores is free to IRQ/etc. and with the BPF I have a two stage filter (was three, the author learned more about 'vlan' and how it works in BPF, post has since been updated)

The file we will be creating is "/usr/local/etc/suricata/capture-filter.bpf" and it gets used/called with the suricata service file modification listed above

BPF Filter lightening the load on the CPUs:
1st group - the subnets and hosts and port and host combos I do not want, including the not element as we are excluding all of this:
not ((ether[12:2] = 0x0800 or ether[12:2] = 0x86DD) and ((net 192.168.15.0/24 and 192.168.16.0/24) or (net 192.168.32.0/24 and 192.168.89.0/24) or (net ipv6subnet1 and ipv6subnet2) or (net ipv6subnet2 and ipv6subnet3) or (broadcast or multicast) or (net 192.168.230/24 or 192.168.240.0/24 or 224.0.0.0/4 or ff00::/8 or fe80::/10) or (((icmp or icmp6) or (port 0 or 67 or 68 or 123 or 137 or 138 or 139 or 445 or 514 or 853 or 1900 or 2055 or 2056 or 3000 or 5044 or 5140 or 5142 or 5143 or 5353 or 5355 or 6060 or 8006 or 8291 or 9001 or 9090 or 9200 or 9600)) and (net 192.168.0.0/16 or ipv6subnet::/56)) or (host 192.168.33.44 or 192.168.55.66) or (host ipv6host1 or ipv6host2) or (src host publicip and ((dst port 853) or (src port 00000) or (src portrange 00000-00000 or 00000-00000))) or (dst host publicip and ((src port 853) or (dst port 00000) or (dst portrange 00000-00000 or 00000-00000))))) or 2nd group - the VLANs I do not want, and a repeat of the exclusions from above, following the above line (no return/new-line):
((ether[12:2] = 0x8100 or ether[12:2] = 0x88A8 or ether[12:2] = 0x9100) and ((ether[14:2] & 0x0fff = 200 or ether[14:2] & 0x0fff = 300) or (vlan and ((net 192.168.15.0/24 and 192.168.16.0/24) or (net 192.168.15.0/24 and 192.168.89.0/24)) or (net ipv6subnet1 and ipv6subnet2) or (net ipv6subnet1 and ipv6subnet3) or (broadcast or multicast) or (net 192.168.230/24 or 192.168.240.0/24 or 224.0.0.0/4 or ff00::/8 or fe80::/10) or (((icmp or icmp6) or (port 0 or 67 or 68 or 123 or 137 or 138 or 139 or 445 or 514 or 853 or 1900 or 2055 or 2056 or 3000 or 5044 or 5140 or 5142 or 5143 or 5353 or 5355 or 6060 or 8006 or 8291 or 9001 or 9090 or 9200 or 9600)) and (net 192.168.0.0/16 or ipv6subnet::/56)) or (host 192.168.33.44 or 192.168.55.66) or (host ipv6host1 or ipv6host2) or (src host publicip and ((dst port 853) or (src port 00000) or (src portrange 00000-00000 or 00000-00000))) or (dst host publicip and ((src port 853) or (dst port 00000) or (dst portrange 00000-00000 or 00000-00000))))))
^ Note about the above bit of BPF, it seems with the Code block when you copy misses the space at the end, the first group has a space after the "or" and before the next group, be sure to add it back

Extra edit: Thought I had really dialed it in, my understanding of vlan was a little off, and it works best at the end as it masks all the work after it to shift all subsequent packet payload byte offsets forward by 4 bytes. The original 3 groups are now just two and it appears to work even better. Still in testing to be fair.
#2
In https://opnsense/ui/firewall/source_nat#:

Since I believe our Firewall Rule Migration, when you create a Source NAT Firewall rule, and try to select a port alias you have created that is a numeric port/portrange the UI will tell you that you must use a port name word to select that port.

The error message:
Please specify a valid port number (1-65535). A service name is also possible (afs3-fileserver, aol, auth, avt-profile-1, cvsup, domain, ftp, hbci, http, https, igmpv3lite, imap, imaps, ipsec-msft, ipsec-nat-t, isakmp, l2f, ldap, microsoft-ds, ms-streaming, ms-wbt-server, msnp, nat-stun-port, netbios-dgm, netbios-ns, netbios-ssn, nntp, ntp, openvpn, pop3, pop3s, pptp, radius, radius-acct, rfb, sip, smtp, snmp, snmptrap, ssh, submission, telnet, teredo, tftp, urd, wins).
Effectively to enter a natural port/portrange you have to type the numeric values in manually.

I would think that since the alias is a numeric value it would work here, but you have to select "Single port or range" and then enter the numeric value manually?

Extra:
Other than this, it would appear quite an improvement to move into 27 and now 27.2, also love the fix to the Service status, looks great!!
#3
Happened across a possible typo in documentation specifying FE80::/8 as the link-local subnet for IPv6 at https://docs.opnsense.org/manual/ipv6.html#router-advertisement-ra and according to everything I can find, the IPv6 Link-Local unicast subnet is FE80::/10.

I have not checked any working code to see if this value made its way into development or production code, but wanted to share the finding as it would appear to be a technical inaccuracy so we can start by updating the documentation.

Extra:
There is a "/8" but it is found in FF00::/8 which is IPv6 Multicast and not IPv6 Link-Local unicast (FE80 != FF00).
#4
For starters, if you hit the "advanced" toggle at the top, it shows all editable fields normally - this is okay and more or less required now to see and edit all fields correctly.

Second, without hitting the advanced toggle on a rule edit you will not be able to edit the Source Port, and the inner-menu toggles to open or hide additional Source/Destination/etc. options is inconsistent (you end up hiding Destination elements by trying to show more elements).

For now, it would appear the best method to use the editor is to click the toggle for advanced when editing a Source NAT (Destination NAT does not appear to have this issue).

Everything appears to be working well, just a GUI bug it would seem on the menu interface around editing Source NAT rules.
#5
26.1, 26,4 Series / PF/Alias list update oddity
June 25, 2026, 04:58:01 PM
Already feeling bad about making this post, but, if someone else has this happen - hope you find this and we can figure it out together.

My OPNSense upgraded to 26.1.10 w/no issue, and I have CrowdSec installed and the Firewall Blocker feature enabled (this means there are two PF/Alias lists that CrowdSec manages updates for).

Instead of configuring my Firewall to use the "CrowdSec managed lists" aliases, I have made a new alias/list where I included the CrowdSec lists (IPv4 and IPv6), SpamHaus list, and a personally kept list as my combined blocklist. This is my blocklist for Inbound and Outbound traffic - works great!

Some time ago, I realized I could have "Uptime Kuma" check an alias/list via API to see how recently it has been updated and let me know if it starts aging too much. After a while I found that the 25 minute marker was good for watching this combined blocklist that I had created - more or less, it near always updates within 25 minutes.

For those wondering, it is a JSON check:
URL: https://opnsense.domain.tld/api/firewall/alias/getItem/<UUIDOfList>
Check: (($millis() - $toMillis(alias.last_updated)) / 60000)

Here is the issue:
Yesterday there was an alert that my combined blocklist hadn't updated, and it was getting into its 4th hour. After restarting the PF service, restarting the CrowdSec Firewall Blocker, and trying to modify my combined blocklist (basically open to edit and hit save) in the Alias list, my combined blocklist would never update. The CrowdSec managed lists were updating (even though you cannot see an edit date, you can tell their count had gone down as it didn't add up to the total sum of my combined blocklist), but my combined blocklist held its aging modify/update time and high count.

Once I restarted the OPNSense, things returned to normal and now the next day, continues to do so. No idea what happened there, but, I would recommend you watch your lists and make sure you track the last update date in case they get locked too. If it happens again (this has only happened once so far), I hope to be able to do more to figure out what the hang up is - would love ideas to check!
#6
Wanted to start with a thank you, the /usr/local/etc/suricata/conf.d/custom.yaml appears persistent and this allows us to further customize Suricata, thank you OPNSense!! We have had difficulty customizing and having it persist until now.

The issue found appears to be that BPF Filtering via netmap in the Suricata config does not appear to work, hosts/networks filtered still show up in the Suricata alerts. The netmap area of suricata.yaml from OPNSense 25.x to OPNSense 26.x appears to have gone through a lot of changes.

The new divert feature being one of the new elements I have not had a chance to explore, I'm using PCAP IPD mode for Suricata.

The documentation for BPF-Filtering within Suricata shows this as an example:
not (host IP1 or IP2 or IP3 or net NET/24)
A most desired filter is between a subnet and one or more other subnets, and I've tried this in several methods, here's the most basic I have tried:
not ((net NET1/24 and NET2/24) or (net NET2/24 and NET3/24) or (net NET3/24 and NET1/24))
So far none of the BPF filters work with Suricata - does anyone use this and/or have experience?

Edit:
For a while I was only looking at the suricata.yaml file and didn't realize the level of control that went into the command line execution of arguments sent to suricata on service start. For a while I was trying to put netmap in IDS mode thinking that's how the traffic was going and wondering why the BPF filter for netmap wasn't working.
#7
Did the upgrade to 26.1.3, everything so far was working, except a home grown automation to sync stuff gathered from the OPNSense API, Portainer, and kept in a Redis Cache to my BIND setup. This is done by a Python script.

In a most strangest interaction, use case testing Python using requests, http, or httpx and was not able to reach and more correctly connect to OPNSense's API, but Postman/CURL both could - and got valid responses back. Tested the HTTP/1.1 or HTTP/2 nature, always worked for Postman and CURL, never worked for Python.

So I went back to the OPNSense, maybe I could re-reset some stuff, started simple - restarted the System Configuration Daemon and then Web GUI services from the Web GUI, suddenly Python is working again.

Also did a another restart of the OPNSense (it restart initially after the upgrade), and the issue did not present itself again. So this is just a heads up to any that might hit whatever edge case I did, restart services and/or host, should work again.
#8
Just wanted to extend OPNSense, the community, FreeBSD, associated projects, and the Open Source community a thank you!!

I wrote a Linux ran multi-threaded Python detail to update several Aliases (two of which have 10k+ IPs) with IP lists via OPNSense API, and on average it is completing now in about 30% less time (that means I block an attacker (CrowdSec enabled Reverse Proxy + Suricata) at Layer 3 faster).

No change to my code, I've already tweaked it for speed in about every way (nice in Linux, pre-compiling Python...) and this speed up is purely because OPNSense continues to become a more lean/mean beast.
#9
Environment detail:
OPNSense Unbound for DNS Upstream + Overrides (so when external to OPNSense local domain BIND is down critical infra still works), Hosts use PiHoles, and both OPNSense Unbound and PiHoles use local BIND infra for the Local Domain. The Local BIND has the forward and reverse lookup all setup, and populated, and Unbound and the PiHoles are set to forward for the local domain and all /24 IPv4 and /64 IPv6 subnets for reverse DNS lookup. This worked previously - I am considering going back to verify.

Upgrade journey:
Migrated from ISC to KEA, Upgraded, did the firewall migration, removed ISC plugin, most everything works well - most hosts seem to correctly populate their Alias content counts for IPs to Hostnames.

Testing the process:
There is a Python script I wrote that updates forward and reverse records in the local Bind infra for the hostnames via OPNSense(ARP/NDP/Reservations)/Portainer(Docker Hosts) and I can
drill fqdn @pihole or
drill -x ip @pihole for A and AAAA/IPv4 and IPv6, and together I get 2+ IPs back as expected. In this case the hostname happens to be "plex.localdomain.home" (not really but close enough), and yeah, most/all other hostnames appear to correctly populate their counts (especially those that are overridden via IPv4 and IPv6 entries in Unbound's Override space).

Problem:
The issue is that the OPNSense Firewall Alias for the FQDN in question only has one value for its "content", or just one IP resolved. This FQDN is not overridden in Unbound. OPNSense's Host discovery / Host detect sees all the IPs for the FQDN's associated MAC address, and all of them resolve to the FQDN against PiHoles/BIND, but Alias does not? Seems odd. I'm curious where the configuration/direction for OPNSense's firewall to resolve hosts comes from - which DNS source of truth is it using?

!!! Interesting:
Doing a drill against the OPNSense for that FQDN and AAAA returns nothing, but from either PiHole or BIND, results. Interestingly though, if I do a reverse lookup on the FQDN's IPv6 against the OPNSense it would seem Unbound responds with the IPv6's FQDN, so A (IPv4 forward DNS) and IPv4 and IPv6 PTR (both IPv4 and IPv6 reverse DNS) works, but AAAA (IPv6 forward DNS) does not for Unbound query forward/response?
!!! Further:
After disabling all Unbound Overrides for the local domain, it still has the same issue - AAAA query for local domains fails - and yes, I have the local domain added to the "Private Domains" in Unbound's Advanced settings. Extra, in this, it would seem to only know about the IPv6 addresses for FQDNs that were overridden, and is unable to do a conditionally forwarded AAAA/forward-ipv6 lookup (unless the FQDN in question is IPv6 overridden manually, and then it isn't forwarding/asking, it is merely answering if you will).

(Extra - I'm considering setting up the BIND plugin on the OPNSense just so I can have my existing Primary BIND send updates to what would be OPNSense's Secondary BIND. Want to possibly understand why it doesn't already work, and maybe explore what is necessary to configure the BIND plugin to be a secondary BIND server as a part of my existing infra while keeping the state in OPNSense conf/backup - fix 1 problem w/possibly 2 or more problems lol, but if anyone has pointers on the original issue, pls lmk)

Ok - so it was the "Register DHCP Static Mappings" which more or less cancelled the forwarding for the local domain, with that disabled, it follows forwarding rules...
#10
Currently still on 25.7.11_9 and have transitioned from ISC to KEA, and so far things are working okay.

With ISC, I could find all of my leases for DHCPv4 and DHCPv6, but with KEA, that does not seem accessible. I tried looking into "host discovery" / "host watch", but maybe it isn't built out in 25.7.x yet. Curious what we can expect to use "host discovery" for and if the data will be available via the API?

Are there plans with KEA to allow us to see our DHCPv6 leases via API, both reserved and un-reserved?
#11
As the CrowdSec default firewall is only stopping incoming for items on the list, I wanted to upgrade how that feature worked, and honestly allow a few hosts I have to not be blocked by the firewall - an unfiltered host if you will.

So, I made my own "Hosts" based Firewall Alias, and have a Python script that will get the latest list and put it in there.

This took a little bit usually, and so I tried to see if I could thread the operation to increase speed, I might try to multi-process it next as the dual sends is about the fastest send (two sub lists, each about 30,000 items) and if there is a change I just update the whole sublist that changed and do a reconfigure.

Still, this takes too long as 10 seconds. The other kinds of aliases are interesting to me, such as Internal and External.

It would seem (and I did this too... but didn't understand how to 'reconfigure' or set the updates as active) that you can do it faster via pfctl via python, but, how do you reconfigure after updating a "Hosts" based Alias? Do the Internal or External Alias types not need a 'reconfigure' to have their populations be active in the rules that use them?

I'm fairly new to pf/FreeBSD so please do not take for granted anything I might 'should' or 'could' know, teach me!
#12
Issue:
Last two updates, on restart, WAN has IPv6 address but no IPv4 address

Further:
The solve is easy, I just go to WAN interface and hit 'Save' at the bottom, it applies, and then I have an IPv4 address on WAN followed by a little later the IPv6 address shows up again on WAN. LAN interfaces have their IPv6 (and IPv4) details, but the missing IPv4 on WAN is initially keeping a few things from working after the update.

I will be able to do more testing later as far as the reboot w/out an update, but I do not have that change management window right now.
#13
External hosts includes internal IPs, Internal hosts includes external IPs

I'm only in detection for 3 LAN Interfaces, I do have RSS enabled (it suggests I disable it... but it has been around for years now and certainly appears to work for everything else including Suricata)

The "Traffic Graph (Throughput)" Dashboard that shows activity, only shows activity for Upload, not Download (even if I speed test Up/Down, just shows Upload)

Any ideas, I'm completely new to Zenarmor and have a free account but have it integrated to their Cloud too?

That said, I have had a few detections for hosts going to odd FQDNs, not bad!
#14
I have several WOL hosts on my network, and I can trigger them to turn on, that works.

What does not work is the 'active status' on the WOL Plug-in Dashboard on the OPNSense. Further, it seems you have to 'wake all' now from the Wake On LAN plug-in menu... it seems you cannot select a specific device to wake up when in the plug-ins menu?
#15
Just released, open for testing, if you BIND with your OPNSense and Docker (w/Portainer), this might be of interest!

As I have ran my own internal BIND DNS setup for a while, and did not explore the built-in that OPNSense has (wanted to learn-it-all), and then wanted to resolve IPv6 for my network this became an eventual desire and then creation. It uses the OPNSense API as well as the Portainer API, then directly and securely interacts with BIND via TSIG.

Please feel free to check it out, comment, or even suggest how else one would do the same in a different way:

Homelab DNS Updater (Github)
#16
After having implemented IPv6, there is a need to be able to update the DNS Servers in this list dynamically, and I do not want to be limited to the two DNS servers for each ISC DHCP entry (and I am not using 'Kea DHCP' yet)

It is great that we have eight fields to add DNS Servers to in the System -> Settings -> General area, but it seems you cannot update these elements via the API, can anyone point out how to do it, or would this be a feature request?

Further, just want to say thank you to whoever got the ARP and NDP lists to be available via API - that is amazing and has let me dynamically update my BIND from MAC <-> Hostname for IPv6 rather easily. Also, just want to say to the network-gurus inventing things, thank-goodness MACs for IPv6 == MACs for IPv4. <3
#17
There's a comment I made on the plugins pull but I thought I would share here too:
https://github.com/opnsense/plugins/pull/2945

It would possibly be even better to allow us to select which auto rules get created instead of having to accept all or none, but if in the CrowdSec plugin we could get this option that would be acceptable.

That said, my intent here is to keep all of the rest of the functionality - so, I want the two aliases to be kept up to date by the plugin - I want to create my own rule to use those aliases but do not want the 'auto rule' getting in the way as it isn't deployed where or how I would want it.

The default rule only blocks in as a source, and does not block as a destination. Might be paranoid, but, I prefer to not even reach out to the badness as well. Further, I have a few hosts that I do not want to filter the traffic this way for, and want to let them interact with the IPs if they are on the CrowdSec blocklist or not.

Certainly interested to hear feedback on the idea/methods to help build it/how to get started.

Thank you all for all you do, I'd like to help but am a little inexperienced to take such a large bite.

Edit - Thank you OPNSense!!
#18
Huge thanks as always!!

Using:
VLANs and Multi-Interface LAN FW Group
DHCP ISC
Unbound
APCUPSD
Crowdsec
Suricata IDS
Wireguard VPN for Clients
NAT Inbound Port Forwarding
Outbound NAT Forwarding
UPnP
mDNS Repeater
IGMP Proxy

Extra:
DHCP -> Side BIND environment

Moded:
Suricata-update w/125k+ rules modified enabled in ~5 minutes
Crowdsec (only running Agent now, and parsing default and suricata eve logs too)
#19
So you are doing port forwarding, and you also have a blocking rule present on at least the WAN (ideally also the LAN(s)). It might be the Crowdsec IPv4 & IPv6 rules the plugin installs, or you maybe made the Spamhaus block rules and the Alias to sync the list from their sources.

What you might not realize is happening is, the Port Forward happens BEFORE any firewall rule on the WAN, so, it will forward in and then block on the LAN (if you have your rules blocking there) and this means extra work.

You can block at WAN and not forward!!

Just enable the 'Source' on the Port Forward rule, and set the 'Inverse' option, select your Blocklist (you can make a new list and have it hold multiple other lists that are syncing so you just give yourself one complete list to add to things) and hit save.

Do this on your Outbound NAT as well, just more or less in reverse - do the 'Destination' + 'Inverse' + your Blocklist, enjoy!

See image in attachments to this post! Hope this has helped someone, and happy Routing! Note - I did modify the image to remove my Proxy's Internal IP - so the blank field with no IP in it is only that way because of that.
#20
TLDR;
The issue is it appears at least the CrowdSec rule matches inconsistently, and I must admit, I wonder if other rules do too, or if this is due to alias <-> rule update sync/propagation, or some other elements of the pf/OPNSense management feature set?

The Long;
After 25.1, I noticed some oddity with the CrowdSec firewall rule entries and if they got matches or not

So I created two aliases, threatIPv4=CrowdSecIPv4+SpamhausIPv4 and threatIPv6=CrowdSecIPv6+SpamhausIPv6

Then I created two rules in Floating applied to both WAN and LAN that would match IPv4+IPv6 and In, one "Source Threatlist Block Inbound" for Source=threatIPv4+threatIPv6, the second "Destination Threatlist Block Outbound" for Destination=threatIPv4+threatIPv6

See the Floating Rules Screenshot_2025-02-13_20-42-38.png

What as happened since 25.1.1 is I am seeing blocks on the default "CrowdSec IPv4" list again, but, I am seeing my added "Source Threatlist Block Inbound" as well but not as many. Not sure if I have seen a default IPv6 show up in the Dashboard dial

See the Dashboard Firewall Screenshot_2025-02-13_20-41-03.png

In full transparency, I am logging this stuff to a data-lake, but the parsing of the hex rule eludes me and getting the matching rule text and applying it further eludes me. That said, our refreshed Dashboard is my source of detail and IMHO, appears correct and is currently my primary indicator of which rule is hitting