Snort (pfSense 2.8.1 / package 4.1.6_28) – DNP3 rules not triggering but working in standalone Snort 2.9.20_8
-
I’m currently testing Snort integration on pfSense 2.8.1-RELEASE using the Snort package version 4.1.6_28, which depends on Snort 2.9.20_8.
I’ve run into an issue where DNP3 rules (with dnp3_func) are not triggering in pfSense, even though the exact same rules and PCAPs work correctly when I run Snort standalone.What I tested (standalone Snort)
In a separate Ubuntu environment, I built Snort 2.9.20 from source, and configured the following:
- stream5 enabled
- dnp3 preprocessor enabled
- modbus preprocessor enabled
- custom local.rules
Example rule:
alert tcp any any -> any 20000 \ (msg:"OT DNP3 DIRECT OPERATE observed"; \ dnp3_func:direct_operate; \ sid:6100005; rev:1;)Running command:
snort -r dnp3_cut.pcap -c snort.conf -A console -k noneResults:
Alerts are generated correctly
DNP3 parser works
Modbus parser works
Different dnp3_func values match depending on PCAPSame test in pfSense
On pfSense:
- Same PCAPs
- Same rules (via custom rules / local.rules equivalent)
- Snort enabled on the appropriate interface
- Didn't tweak with any advanced settings apart from enabling SCADA preprocessors
Observations:
Broad rule on port 20000 works (see below):alert tcp any any -> any 20000 \ (msg:"ANY DNP3 TRAFFIC"; sid:1000001; rev:1;)
Modbus rules (modbus_func) work correctly
DNP3 rules with dnp3_func do NOT trigger (e.g. below):alert tcp any any -> any 20000 \ (msg:"DNP3 READ"; dnp3_func:read; sid:1000002; rev:1;)Hence, DNP3 preprocessor does not appear to be active or parsing the traffic.
What I’m trying to confirm
- Does Snort package 4.1.6_28 include full DNP3 preprocessor support?
- Is there any additional GUI setting required to enable DNP3 (similar to other preprocessors)?
- Has anyone successfully used dnp3_func rules in pfSense Snort recently?
-
Your path to the snort.conf file is incorrect when running against your PCAP file.
I maintained the Snort package and created and maintained the Suricata package on pfSense for many years, but I recently retired from that role at the start of this year.
Snort on pfSense does NOT use any of the files in
/usr/local/etc/snort/directly. Instead, each time you save the config in the GUI or start/stop the service from the GUI, the PHP code creates a new snort.conf file in the/usr/local/etc/snort/snort_xxxx/subdirectory where the "xxxx" is replaced by a UUID and the physical interface device name the Snort instance is using. When Snort is started within the GUI or automatically by pfSense during a reboot, the Snort binary is passed the proper custom path where it can find the snort.conf file appropriate for the interface.So, the configuration you make in the GUI is only respected when run against the correct snort.conf file in that subdirectory.
TL/DR answer is: "Snort in pfSense does NOT behave at all like a standalone Snort install on Linux or even FreeBSD does." It uses custom paths for the configuration file, for the rules, and for logging. Those custom paths are named with a UUID and the physical interface name. This is so you can run multiple instances of Snort on different interfaces with each having its own unique configuration and logging settings.
Your command line execution should look like this:
snort -r dnp3_cut.pcap -c /usr/local/etc/snort/snort_xxxx/snort.conf -A console -k nonewhere you replace "xxxx" with the proper UUID and physical interface name.
When you run Snort with the command line parameter you are using for the snort.conf file, it will use the default snort.conf file in
/usr/local/etc/snort/which will not have the necessary preprocessors enabled nor will it be pointing to the directory where the correct rules are located. That's why you are not seeing any alerts. The DNP3 preprocessor is not enabled in the default snort.conf file. But it will be enabled if you enable it in the GUI and then point Snort to the proper conf file in the appropriate subdirectory as I indicated above. -
Hi @bmeeks, thanks for the detailed explanation.
Just to clarify, I’m not running Snort from the CLI on pfSense, and I’m not using any snort.conf. I should have explained better my setup, sorry for misleading you.My setup is:
- Snort configured via pfSense GUI
- Snort running on a specific interface
- Traffic generated by replaying a PCAP from a separate VM to another VM (pfSense sits in between)
- pfSense Snort inspecting that traffic live on the interface
So Snort is operating within pfSense exactly as intended (via the GUI), not via manual command-line execution.
I will edit the post to make it more clear.
-
@honeybadger101 said in Snort (pfSense 2.8.1 / package 4.1.6_28) – DNP3 rules not triggering but working in standalone Snort 2.9.20_8:
Hi @bmeeks, thanks for the detailed explanation.
Just to clarify, I’m not running Snort from the CLI on pfSense, and I’m not using any snort.conf. I should have explained better my setup, sorry for misleading you.My setup is:
- Snort configured via pfSense GUI
- Snort running on a specific interface
- Traffic generated by replaying a PCAP from a separate VM to another VM (pfSense sits in between)
- pfSense Snort inspecting that traffic live on the interface
So Snort is operating within pfSense exactly as intended (via the GUI), not via manual command-line execution.
I will edit the post to make it more clear.
Sorry, I did misunderstand your initial post with regards to how you were running Snort.
With the DNP3 preprocessor enabled under the PREPROCESSORS tab in the GUI, Snort should behave the same on pfSense as on the Ubuntu machine. The specific configuration for each preprocessor is generated based on the GUI settings for it and then written to the
snort.conffile. I would start by comparing the DNP3 preprocessor sections in the twosnort.conffiles to see if anything is different. Also wouldn't be a bad idea to run a packet capture on the pfSense interface to be 100% the traffic you expect to be there is actually there. -
This post is deleted! -
@bmeeks said in Snort (pfSense 2.8.1 / package 4.1.6_28) – DNP3 rules not triggering but working in standalone Snort 2.9.20_8:
I maintained the Snort package and created and maintained the Suricata package on pfSense for many years, but I recently retired from that role at the start of this year.
@bmeeks nice to hear from you!
Do you know if the package is still supported by Negate?
There was no notification or I missed it.@honeybadger101 sorry for the off topic post.
-
This post is deleted! -
@bmeeks
So yes, traffic is 100% there. I compared the two snort.conf files as suggested and they look pretty much the same. I uploaded both configs, could you please take a look at them as I don't see anything outstanding? -
Sorry to be late on the reply. Was away from home for several hours today.
I don't see any immediate differences in the two
snort.conffiles for the DNP3 preprocessor, but the Ubuntu one is very "bare bones".I assume you have reviewed the official Snort 2.9.x documentation here: http://manual-snort-org.s3-website-us-east-1.amazonaws.com/node17.html#SECTION003223000000000000000 ??
Two possibilities stand out to me from reviewing the Dependency Requirements and Configuration sections of the above link. First, I would ensure that all the items under "Dependency Requirements" are met. Second, I see that if
check_crcis specified and there is any CRC frame error, the packet will be ignored. It's possible there is some difference in how CRC checks are performed and bubbled up in Linux versus FreeBSD. Don't know for sure, but worth investigating. Maybe try removing thecheck_crcargument for testing. Removing that parameter will require editing one of the PHP source files as follows:In file
/usr/local/pkg/snort/snort_generate_conf.phpfind the section beginning at line #878 as shown below.# DNP3 preprocessor # preprocessor dnp3: \ ports { {$dnp3_ports} } \ memcap 262144 \ check_crcModify it to appear as follows and save the change. Notice the
check_crcline is removed as is the trailing backslash on thememcapline above it.# DNP3 preprocessor # preprocessor dnp3: \ ports { {$dnp3_ports} } \ memcap 262144After editing and saving the file, stop and start Snort on the interface to force a rebuild of the
snort.conffile with the new information. -
@bmeeks Thanks. Due to a couple of reasons I had to step out of the office this week, so apologies for not getting back to it earlier. I hope to try what you suggested when I am back end of the week.
-
Hi @bmeeks, sorry for the late reply. I had some vacation weeks and couldn't follow-up.
Unfortunately I haven't solved this issue even with your great support.
I doubled checked the dependency requirements and changed the configuration as suggested to disable CRC checks but still, rules don't fire.
I have attached some screenshots that show the requirements both in pfsense GUI and conf file. Could you please double-check, just to be sure I'm not missing anything?
Thanks again for your help on this.






-
I don't immediately see any misconfiguration. In some additional web research I did find this post from 2012 on the Snort blog about SCADA capabilities in Snort 2.9.x: https://blog.snort.org/2012/01/snort-292-scada-preprocessors.html. I also found some discussion of the new SCADA capability in Snort 2.9.x at SANS here: https://isc.sans.edu/diary/12346.
I am not really familiar with using either of these SCADA protocols. Although I did work early in my career as an Instrumentation and Controls Technician and understood the basics of SCADA, that area was not my primary job focus. Later as a cyber security analyst working to secure industrial controls systems I again was not specifically tasked with the SCADA side of things. I specialized more in firewalls and L3 stuff instead of deep diving into SCADA.
With DNP3 in particular, I would double-check to be sure your PCAP matches the possibly more primitive protocol decoding present in Snort 2.9.20 as compared to Snort3.
It's been a while since I've visited this thread, but I seem to recall that you tested your PCAP on a standalone Linux install of Snort 2.9.20. If possible, I would repeat that test on a standalone install of Snort 2.9.20 on a FreeBSD installation. This would rule out any potential network stack differences between Linux and FreeBSD that might be at play (not saying there are any, but it is certainly possible).
Running Snort in IDS mode (not IPS) on pfSense uses the
libpcaplibrary to obtain a copy of all packets traversing the targeted interface. The default mode of Snort on pfSense also enables Promiscuous Mode packet capture so that every packet seen by the interface is captured for Snort.