individual pfctl snort2c tables per interface only blocking IPs for specific interface when a rule triggers in snort/suricata
Feature Request Background:
The snort2c table is used for blocking any connections to any IP address which is put into the table.
Snort as well as suricata create entries for IP addresses that triggered a rule and if blocking has been enabled.
Since different interfaces may have different types of traffic / users this results in the necessity of having different IPS/IDS rules applied resulting in IPs that need blocking only for a specific interface, but not another.
The current central approach results in IP addresses being blocked for all users on all interfaces despite the need to have users from one network segment to continue to connect to that address. With suricata or snort rules where actually traffic content or app_ids are used to block / log / allow connectivity and not a static IP it seems more than necessary to have a feature allowing to distinguish between the different needs of network segments. Since an increase of segmentation in order to achieve isolation of services / equipment and users is more and more common a more individual approach per segment becomes necessary.
The legacy type of operation (snort2c table usage) seems likely to stay for a while as some combinations of features do not allow the usage of the inline mode with netmap, such as lagg devices with vlans.
The easiest approach seems to create individual snort2_intfX tables for each network interface. Then have snort or suricata submit the IPs to be blocked only to the one specific table for the interface where a rules triggered a block.
Then use the different tables only to block respectively the traffic for the specific IPs in the files that are associated with the interface. Hence this should allow to have different sets of blacklists (snort2c tables) which can be managed separately. The GUI could reflect this by having a drop down menu in the suricata blocked hosts section for each interface, allowing to pull the relevant entries for review / removing. Furthermore the Diagnostics - Tables view could include the different tables for the interfaces.
This should be available for physical and logical interfaces, including lagg interfaces with vlans as well as physical vlan trunks and individual vlan interfaces.
Thank you for your consideration.
#1 Updated by Bill Meeks about 2 months ago
I'm not sure I completely understand your request reasoning. In a typical default installation of the IDS packages all locally-attached networks are automatically added to the default Pass List and won't be blocked. For example, assume a firewall with four interfaces as follows:
Local hosts in LAN1, LAN2 and DMZ will not be blocked. But any host they talk to outside of the locally-attached networks will be blocked. Typically this would be hosts on the Internet (accessed via the WAN interface). So in this scenario the "bad guy" is out on the Internet. So I would think you would want all internal hosts on locally-attached networks to be blocked from accessing the "bad guy" IP address. The current setup implements this logic. But the Pass List will always let a local host communicate with another local host without blocks (assuming the default Pass List is used). If an admin creates a custom Pass List for an interface, that behavior can be changed.
Sounds like in your request you want a situation where a host on LAN1 is blocked from acessing say "bad host1 on the Internet" but you want a host on LAN2 and/or the DMZ to continue to be able to communicate with "bad host1 on the Internet". Is that correct? If so, why would that be a good idea? I'm thinking an identified "bad host" should be inaccessible for all local hosts (unless maybe you have an internal honey pot).
Help me better understand your use case for the feature. Implementing it would require changes in the pfSense base code that are beyond what packages normally do. The snort2c table is created by the pfSense base code no matter if an IDS package is installed or not. The IDS packages simply use the feature. The custom blocking module currently used in both Snort and Suricata has the capability of accepting the specific pf table name the module should add IP addresses to. So changes in the IDS package would be minimal. It's the changes in the pfSense base that would be more problematic I think.
#2 Updated by Felix S about 2 months ago
Bill, thank you for getting back to me that fast!
Indeed you are correct with you summary. A main challenge is the differentiation of different use cases as they apply to different networks attached to the pfsense when reaching out to internet resources. What is "bad" for one network can be "totally fine" for another. This includes leveraging the snort / suricata rules for identifying different applications reaching out to the internet and blocking them for one network while allowing them for another (VPNs, TeamViewer, Cloud Services (DropBox, G-services, Apple-services etc.)). Network types / use cases include "normal users", "guests", "lab", "training", "online investigations", "special users", "administration networks", "IoT networks", "DMZs" etc.
For more details / examples see my wording below.
Networks where users and automated processes investigate potentially dangerous events or search for relevant information. They need to reach out to many categories of sites which are not deemed safe for normal users and hence are separated. Nevertheless, those networks are behind the pfsense. If a normal user tries to contact any such site it automatically ends up in snort2c triggered by the rule, blocking any further connection. While this is good for the normal user network it is bad for the network investigating things as this is blocked from reaching the very same site.
Other networks are of a "lab/training" type where things are tried out / experimented with which, depending on the use case, might need to reach out for sites that are not "normal" for end users, therefore they get blocked for normal user networks, but are fine for lab networks (for example establishing VPN connections, usage of cloud services etc.). However, there are other rules that still need to trigger and prevent certain internet connectivity as it isn't an "anything goes" type of scenario.
Then again there are "guest" networks where the use case can not be predicted and therefore is an "open" not restricted environment with regard to where on the internet connections are established to and which applications are allowed to be used that reach out to the internet. If I have a rule triggering for trying to establishing a VPN connection, usage of TeamViewer, SSH, chat applications, G-services, A-services etc. on one network it will prevent others that may have a legit use case from doing so as it relates to outside connectivity.
Any inadvertent connection to any site which is not deemed ok for normal users results in other networks being prevented from connecting to outside resources due to a single snort2c table being applied to all networks.
Furthermore there are networks which are allowed to use application types (that reach out to the internet) which are identified by snort_app-detect.rules and others while those are not allowed for users on other networks (chats, file sharing types, code repositories etc.). Leveraging those rules for preventing users from using them automatically results in other network users being unable to use them as they reach out to the internet.
The logic here is that we have the possibility in pfsense to create / apply different rules for different networks for snort / suricata, but any triggering of those rules as it relates to outside networks is applied for all of them even though we have different rules. If we can not differentiate here, then why have the possibility to configure different rule sets for different interfaces at all as it relates to outside resources. If any related to the outside trigger whether it is DMZ, guest, lab, investigation network, normal users etc. then they all get blocked. From that perspective I am looking for flexibility / granularity while still being able to leverage a central system for administering the rules for the environment.
I admit that if you only have one use case with regard to what should be allowed to be connected to on the Internet the current solution works fine. However, as soon as you start having multiple use cases in one environment it gets difficult with the current implementation. Another approach would be to have a separate pfsense box for each use case, however this becomes an administration challenge pretty quickly.
Having separate tables for each interface also allows you to restore connectivity for a network/service, when a rule triggers inadvertently, very precisely without interrupting other networks.
#3 Updated by Bill Meeks about 2 months ago
I understand better now. I am not against having unique blocking tables for each interface, but implementing that requires the buy-in and support of the pfSense developers. I am only a volunteer package creator/maintainer for the Snort and Suricata packages. I don't make decisions for the bigger pfSense world.
As I mentioned in my first reply, the custom blocking module currently has the capability of handling unique pf table names for an interface. In fact it requires simply changing a single line in the snort.conf or suricata.yaml configuration file for the interface. The real work is on the pfSense side of things. Off the top of my head, I don't think any other changes would be needed in the Snort or Suricata GUI package code.
The next step will be to hear from the pfSense developer team to see what they think about implementing this feature. The most logical location for any additional snort2c-type block tables is near the start of the rule chain for an interface like the current snort2c table. And also make the rule a hidden system rule as it is now.