Important Info About Passlists with Suricata Inline IPS Mode
bmeeks last edited by
If you use Suricata and have a network card that fully supports Inline IPS Mode, then this notice is important to you so read on. If you use Legacy Mode blocking, then none of what is said below applies to you and you can skip it if you desire.
History of Passlists
The idea of passlists sprang from the old Legacy Mode Blocking used in Snort and later in Suricata when that package was created. Legacy Mode uses a custom plugin that runs within the Suricata binary. This plugin intercepts every ALERT triggered by the rules. The plugin extracts the IP addresses from the ALERT (source and destination) and then inserts one or both of them into the snort2c table that lives in the pf (packet filter) firewall engine in pfSense. Any IP address inserted into that pf table will be subsequently blocked by the firewall. So that is how Legacy Mode blocking really works. IP addresses extracted from ALERTS are put into that snort2c table and the pf firewall takes it from there. Some options were added to the Legacy Mode plugin that allow the user to specify which IP address from the alerting packet to block (SRC, DST or BOTH). Another requested feature was the abilty to exempt certain IP addresses from ever being blocked even if they triggered an ALERT. Thus was born the idea of the Passlist. The Passlist is simply a list of IP addresses or IP network subnets that should never be blocked. The Legacy Mode plugin consults this list of Passlist IP addresses before sending the IP from an alert packet over to the pf firewall's snort2c table. If the IP is on the Passlist, then it is not sent over to pf and thus is not blocked.
A passlist was needed in Legacy Mode because once an IP address gets into the snort2c table, all further traffic coming from or going to that IP address is blocked. This includes even non-malicious traffic. So "blocked" really means blocked until the address is physically removed from the snort2c table. This can be done by the user manually, by rebooting the firewall or by means of a cron task that periodically removes addresses from that table.
Why Inline IPS Mode Generally Negates the Need for a Passlist
Inline IPS Mode is a different animal when it comes to blocking traffic. It does not use the firewall at all. Instead, it creates a netmap pipe between the NIC driver and the pfSense kernel and pf firewall. You can visualize this as literally a pipeline that connects these two endpoints. All network traffic to and from the network interface must go through that pipe. Suricata sits in the middle of that pipe and acts like a gatekeeper. If a Suricata rule with the DROP action is triggered, the packet that triggered the rule is literally just dropped by Suricata and not passed on to the other end of the pipe. So assume a packet was coming from the NIC on the way to the kernel and pf firewall for processing and that packet triggered a Suricata DROP rule; then that packet is just ignored by Suricata and never forwarded on to the kernel and pf firewall for futher processing. However, if the packet triggers just an ALERT rule or no rule at all; then it is passed on to the kernel and pf firewall for futher processing.
One key point to note here is that this inspection and passing/dropping is done on a packet-by-packet basis. So since no IP address gets put into the firewall table, you don't have to worry about subsequent non-malicious traffic to or from the same IP host being blocked. This is an important point! Bad packets are dropped for an IP address, but good packets pass for that same IP address. Compare this to the old Legacy Mode where once an IP address was put into the snort2c table all traffic with that IP address in it was blocked (both malicious and non-malicious). So this difference in the way blocks are handled minimizes the need for a Passlist with Inline IPS Mode. In fact, in most instances, you should never need or want a Passlist with Inline IPS Mode.
Suricata 4.0.3 Inline IPS Mode and Default Automatic Passlists
Okay, this is the section where I admit making a mistake by allowing myself to be talked into including a default Passlist option when using Suricata Inline IPS Mode. I added that capability a while back (I think it was when 4.0.1 came out). Anyway, you have the option at the moment on the INTERFACE SETTINGS tab of choosing "none", "default" or any other user-created Passlist for the Passlist Setting on the interface when using Inline IPS Mode. The help text associated with the Passlist control recommends you choose "none", and so do I! Here's why. If you choose "default", then a potentially bad thing happens. Some PASS rules get automatically created that effectively whitelist your entire LAN. By "whitelist" I mean no alerts or drops from anything whose IP address is in your LAN or any other locally-attached firewall networks. And what's worse, this whitelist extends to traffic flow in both directions: (1) FROM a device on your LAN to elsewhere; and (2) from elsewhere TO a device on your LAN. This is not good as bad stuff can flow to/from your LAN hosts and other locally-attached firewall networks and Suricata won't care! This bad situation came courtesy of the existing default passlist code used for Legacy Mode operation.
Here are some examples of how the automatic default Passlist rules can be bad –
The current "default" passlist includes locally-attached networks if you select that option when creating a pass list (and it is checked by default). So assume your LAN is the subnet 192.168.1.0/24. So Suricata will create this pass rule for the default Passlist when the option to include locally-attached networks is checked:
pass ip 192.168.1.0/24 any <-> any any (msg: "Pass List Entry - allow all traffic to/from 192.168.1.0/24"; sid:1000006;
This rule says when the SRC or DST is an IP address in the 192.168.1.0/24 subnet, then let it pass with no inspection. Pass rules in Suricata mean just that – pass the traffic unconditionally with no further inspection. And pass rules are the very first rules the Suricata engine evaluates. So this default pass rule is bad (very bad actually). Some of the other automatic default passlist rules are more restrictive and specify only a single IP address instead of the whole subnet, but even then it still is generally not a good idea to totally whitelist most hosts.
So unless you are totally convinced you need a Passlist with Inline IPS Mode, go right now and set your PassList entry on the INTERFACE SETTINGS tab to "none", save the change and then restart Suricata. Choosing "none" turns off the automatic passlist. In the next Suricata GUI package update, the ability to assign and use a passlist will be removed from Inline IPS Mode operation to prevent users from inadvertently neutering their IPS when running Inline IPS Mode.
What If I Really Need a Passlist with Inline IPS Mode?
If you truly do need to whitelist a specific host for some reason (or perhaps more rarely an entire subnet), then you should probably create your own Custom Rules for this and forget about using a passlist. Custom rules allow you to be more specific. For example, you could specify an IP, a flow direction and even a port or port range to limit the traffic that bypasses normal Suricata inspection (remember that a passlist when using Inline IPS Mode means passlist addresses get evaluated by no rules; any host or network on the passlist bypasses all Suricata inspection). The very first test in the Suricata engine is to check if the SRC or DST addresses, ports and protocol match any PASS rules. If there is a match, the packet is passed on to the netmap pipe endpoint and bypasses all of the other Suricata rules.
So a rule like this is much more limited than the earlier rule:
pass ip 192.168.1.22/32 80 <- any any (msg: "Pass List Entry - allow all traffic to/from 192.168.1.22/32"; sid:1000006;
This rule only passes traffic where the destination is IP address 192.168.1.22 and the port is 80. Only traffic matching that specific criteria bypasses further Suricata inspection.
To create custom passlist rules like this, go to the RULES tab for the interface, choose CUSTOM RULES in the Category drop-down and then type in the rules you need. There are plenty of examples on the web. You can add restrictions by protocol, port and source or destination IP address. Just really think about what your rule is allowing when creating it. It's easy to bypass your Suricata protection with a Passlist! That's why I intend to remove that capability for Inline IPS Mode operation in the next update. Folks needing to whitelist a host or network can do so with custom PASS rules instead.
Realistically, about the only application I can imagine for a Passlist is if you are running a honeypot host and you actually want bad stuff to find its way to that host. In that situation, a passlist makes sense. For about any other case, it does not. So get ready to see Pass Lists disappear from Suricata in the next version when using Inline IPS Mode, and get prepared to use custom PASS rules instead if you really need passlist functionality.
For those looking to create their own rules, the "sid:1000006;" part of the example is NOT a reference to an existing SID. It needs to be a unique number otherwise Suricata won't load the rule.
To whitelist for a rule for an IP, search for the SID in /usr/local/etc/suricata/suricata_(interface)/rules/suricata.rules. Duplicate the conditions like "flow:from_server,established; content:"403"; http_stat_code;" into the custom rule so it matches, like
pass ip 192.168.1.22/32 80 <- any any (msg: "Pass List Entry - allow all traffic to/from 192.168.1.22/32"; flow:from_server,established; content:"403"; http_stat_code;sid:1000006;)
Otherwise with only the IP address, port, and unique SID it will allow all traffic for that IP.
Also note the directional (<-) only allows for two directions..."both" or "left."