Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    Supressing an entire ruleset, where the ruleset needs to be enabled

    Scheduled Pinned Locked Moved IDS/IPS
    16 Posts 2 Posters 1.3k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      justme2 @bmeeks
      last edited by

      Correct. This is on the external. Not necessarily "normal" and ensures that those addresses can't even reach a service that may be port forwarded/proxied via the firewall on the external interface. eg: the socket [itself] cannot be reached. It also means that the inside doesn't even have to deal with seeing the traffic if the outside instance drops them [at arm's length]. Said differently, if someone were running a proxied NAT/Rule or haproxy (or anything else) that would allow something "past" the firewall rule - why even let "known bad" near those in the first place. Simply improves overall posture and reduce potential for issue.

      Agree that for all other ports, it would make sense as to avoid even "looking" at those packets but in this case it puts a protective [and selective] veil over the "outside" of things.

      1 Reply Last reply Reply Quote 0
      • bmeeksB
        bmeeks
        last edited by bmeeks

        Are you using Legacy Blocking Mode or Inline IPS Mode? Take a look at the two diagrams below that shows how the two IDS/IPS packages are plumbed into the network path.

        ids-ips-network-flow-legacy-mode.png

        ids-ips-network-flow-ips-mode.png

        If using Legacy Mode Blocking, then the firewall is doing the blocking anyway so you may as well allow the default deny rule to work in your favor and not waste cycles scanning with the IDS/IPS. Legacy Mode Blocking works by sending copies of packets to the IDS/IPS for processing while the original packet continues straight to the firewall engine. Only if the copied packet triggers an IDS/IPS rule will a block be inserted into the firewall for "future" packets to hit (but not the current packet that caused the initial alert).

        If using Inline IPS Mode, then it's true the IPS can drop a packet before the firewall sees it. But I will also offer this bit of info. pfBlockerNG and an IP list matching the CIARMY list will accomplish the same thing more efficiently as it won't be scanning every packet. You lose a significant fraction of throughput when using Inline IPS Mode because every packet is scanned.

        J 2 Replies Last reply Reply Quote 0
        • J
          justme2 @bmeeks
          last edited by

          Using inline.

          1 Reply Last reply Reply Quote 0
          • bmeeksB
            bmeeks
            last edited by bmeeks

            I've said this many times over the last couple of years when giving IDS/IPS configuration advice. You are not using the IDS/IPS to protect your firewall. You use it to protect the hosts behind the firewall.

            When running on an internal interface all local hosts are still perfectly protected as no traffic can reach them without traversing the IDS/IPS anyway. Consider that when running on the LAN, no traffic can get from the firewall engine to a LAN host without traversing the IPS when using Inline IPS mode. That means it would go from Internet through WAN rules and then get routed to LAN rules, then finally through the IPS before reaching an internal host. Refer to the diagrams I posted above.

            Putting the IDS/IPS on the LAN side helps relieve pressure on it as it will no longer be scanning those "noise" packets. The pf firewall engine will have dealt with the majority of those.

            J 1 Reply Last reply Reply Quote 0
            • J
              justme2 @bmeeks
              last edited by

              There are more lists than "just" the ciarmy stuff that are in the rule feeds. Basically any "list" of IPs/networks is applied externally. If there was a 1:1 with pfBlockerNG - would look to go down that path, but (at least time I checked) there simply wasn't sufficient parity.

              bmeeksB 1 Reply Last reply Reply Quote 0
              • bmeeksB
                bmeeks @justme2
                last edited by bmeeks

                @justme2 said in Supressing an entire ruleset, where the ruleset needs to be enabled:

                There are more lists than "just" the ciarmy stuff that are in the rule feeds. Basically any "list" of IPs/networks is applied externally. If there was a 1:1 with pfBlockerNG - would look to go down that path, but (at least time I checked) there simply wasn't sufficient parity.

                May be so as I have not tried to find a CIARMY duplicate for pfBlockerNG. But I still stand by my advice to move your sensor to the internal interface (or interfaces) to make better use of CPU cycles -- unless you just have CPU and RAM to burn.

                Not saying putting it on the WAN is "wrong", but just offering suggestions to improve efficiency in throughput and resource utilization on the firewall.

                A beneficial side effect of putting it on an internal interface is it would eliminate the alerts/blocks you don't want to see (that Internet noise I mentioned). I would want to see if one of my internal hosts communicated with a CIARMY IP address, though. Having the sensor on the inside interface would accomplish both goals.

                1 Reply Last reply Reply Quote 0
                • J
                  justme2 @bmeeks
                  last edited by

                  There's a key element in this which is that means putting 100% trust that something like haproxy/.... won't end up with a flaw that can exploited given the attack access to the firewall. As haproxy runs as root - a flaw opens a broad door. Why not simply "close" the risk [at least] from known nefarious sources?

                  bmeeksB 1 Reply Last reply Reply Quote 0
                  • bmeeksB
                    bmeeks @justme2
                    last edited by

                    @justme2 said in Supressing an entire ruleset, where the ruleset needs to be enabled:

                    putting 100% trust that something like haproxy/.... won't end up with a flaw that can exploited given the attack access to the firewall

                    Well, you have the same vulnerability exposure in the IDS/IPS as well, don't you? If you search the Suricata Redmine site, for example, you will find a few past bugs that allowed bypassing of packet inspection. Who's to say another such bug won't pop up? I would say the risk is about the same.

                    J 1 Reply Last reply Reply Quote 0
                    • bmeeksB
                      bmeeks
                      last edited by

                      Nothing wrong with putting the IDS/IPS where you have it, but one limitation you will have to live with is you won't be able to easily accomplish what your original post asked about. There is no way short of typing in every single individual SID to suppress an entire category of alerts.

                      J 1 Reply Last reply Reply Quote 0
                      • J
                        justme2 @bmeeks
                        last edited by

                        Agreed, but at least having a couple measures in place to "try to" provide protection is better than not. Seems easier to justify consumption of more CPUs and/or faster cores for more potential protection than having to explain the inverse if something were to happen. Nothing is 100% and applying as much "reasonable" protection should be applied where possible - throughout the path of data flow (not "just" the firewall). Making the cost of more/faster CPUs "cheap" even if seemingly burdensome.

                        bmeeksB 1 Reply Last reply Reply Quote 0
                        • J
                          justme2 @bmeeks
                          last edited by

                          That is what I was trying to determine - ?if? there was an easy/existing means. if not, it simply means some effort to create something for purpose. Not the end of the world, but will add "maintenance" to the effort.

                          bmeeksB 1 Reply Last reply Reply Quote 0
                          • bmeeksB
                            bmeeks @justme2
                            last edited by bmeeks

                            @justme2 said in Supressing an entire ruleset, where the ruleset needs to be enabled:

                            Agreed, but at least having a couple measures in place to "try to" provide protection is better than not. Seems easier to justify consumption of more CPUs and/or faster cores for more potential protection than having to explain the inverse if something were to happen. Nothing is 100% and applying as much "reasonable" protection should be applied where possible - throughout the path of data flow (not "just" the firewall). Making the cost of more/faster CPUs "cheap" even if seemingly burdensome.

                            I understand the "defense in depth" concept for cyber security. Worked in that area of nuclear power for several years before retiring. We were regulated like no tomorrow with a long line of NRC inspectors imagining every conceivable manner of "what if" 🙂. I think they must have gotten a larger bonus the more far-out-there their idea of a perceived threat was.

                            Of course nothing was connected to the Internet, and everything was isolated from other internal company networks via one-way data diode appliances. The only real threat was portable media (USB sticks and CD/DVDs) and a laptop. All of those were heavily policed, controlled, and scanned before use with multiple malware scanning techniques. And all the critical networks were behind multiple layers of physical security including guys with guns.

                            1 Reply Last reply Reply Quote 0
                            • bmeeksB
                              bmeeks @justme2
                              last edited by bmeeks

                              @justme2 said in Supressing an entire ruleset, where the ruleset needs to be enabled:

                              That is what I was trying to determine - ?if? there was an easy/existing means. if not, it simply means some effort to create something for purpose. Not the end of the world, but will add "maintenance" to the effort.

                              You could perhaps get creative with sed and regex to pull out the rule SIDs from the rules category file. The master file will be in /usr/local/etc/snort/rules/ if using Snort, and in /usr/local/share/suricata/rules if using Suricata. The rules files are just plain text.

                              You would write the extracted SIDs, with the correct suppresion list syntax, to a file. I would begin by creating a custom Suppress List and assigning it to the interface. Then using a crontab driven script to update it each time the rules update.

                              J 1 Reply Last reply Reply Quote 0
                              • J
                                justme2 @bmeeks
                                last edited by

                                Had a few in-between other activities and came up with this. RE: bonus on ideas - "..things that make you go Hmmmmm....." lol

                                Including if useful to anyone else - this appears to solve the riddle..... Not "pretty" but addresses the need with a few options that can be applied to satisfy some conditions. Could probably be augmented to enable specification of "interface" to further simplify.

                                #!/usr/local/bin/perl
                                #
                                use strict;
                                use Getopt::Long;
                                $| = 1;
                                #
                                GetOptions('debug'=>\$PROC::DEBUG,'include=s'=>\$PROC::INCLUDE,'severity=s'=>\$PROC::SEVERITY,'targetfile=s'=>\$PROC::TGTFILE,'mergefile=s'=>\$PROC::MRGFILE,);
                                if (defined($PROC::DEBUG)) { $PROC::DEBUG=1; } else { $PROC::DEBUG=0; }
                                %PROC::INCS=();
                                if (defined($PROC::INCLUDE)) {
                                    foreach(split(/,/,$PROC::INCLUDE)) { $PROC::INCS{$_}=0; }
                                    }
                                #
                                @PROC::DIRS=('/usr/local/share/suricata/rules','/usr/local/etc/snort/rules',);
                                %PROC::HASH=();
                                #
                                foreach(@PROC::DIRS) {
                                    my $RDIR=$_;
                                    opendir(DIR, "$RDIR"); rewinddir(DIR);
                                    while(my $FILE=readdir(DIR)) {
                                        if ($FILE=~/\.rules$/) {
                                            my $CHECK=$FILE; $CHECK=~s/\.rules$//;
                                            if ((keys(%PROC::INCS)>0) && (exists($PROC::INCS{$CHECK}))) { &procFile("$RDIR/$FILE"); } elsif
                                               (keys(%PROC::INCS)==0) { &procFile("$RDIR/$FILE"); }
                                            }
                                        }
                                    closedir(DIR);
                                    }
                                #
                                if (defined($PROC::MRGFILE)) {
                                    open(INF, "<$PROC::MRGFILE");
                                    while(my $LINE=<INF>) {
                                        chomp($LINE);
                                        if (($LINE!~/^#/) && ($LINE!~/^[[:space:]]{0,}$/) && ($LINE=~/^suppress[[:space:]]{1,}/)) {
                                            my $GID=$LINE; $GID=~s/^.*gen_id[[:space:]]{1,}//; $GID=~s/,.*//;
                                            my $SID=$LINE; $SID=~s/^.*.sig_id[[:space:]]{1,}//; if ($SID=~/,/) { $SID=~s/,.*//; }
                                            if (exists($PROC::HASH{$GID}{$SID})) { delete($PROC::HASH{$GID}{$SID}); }
                                            }
                                        }
                                    close(INF);
                                    }
                                my $FH;
                                if (defined($PROC::TGTFILE)) { open $FH, ">", "$PROC::TGTFILE" || die("ERROR: $PROC::TGTFILE $!\n"); select($FH); } elsif
                                   (defined($PROC::MRGFILE)) { open $FH, ">>", "$PROC::MRGFILE" || die("ERROR: $PROC::MRGFILE $!\n"); select($FH); print $FH ("\n"); }
                                foreach my $ID (keys %PROC::HASH) {
                                    foreach my $SID (sort {$a<=>$b} keys %{$PROC::HASH{$ID}}) {
                                        my $MSG=$PROC::HASH{$ID}{$SID}{msg};
                                        my $FILE=$PROC::HASH{$ID}{$SID}{file};
                                        print ("# ($FILE) $MSG\nsuppress gen_id $ID, sig_id $SID\n\n");
                                        }
                                    }
                                if (defined($PROC::TGTFILE) || defined($PROC::MRGFILE)) { close $FH; }
                                #
                                if (defined($PROC::MRGFILE)) {
                                    my $F = do { local $/ = undef; open my $FH, "<", "$PROC::MRGFILE"; <$FH>; };
                                    $F=~s/\n//g; $F=~s/#/\n\n#/g; $F=~s/suppress[[:space:]]{1,}/\nsuppress /g; $F=~s/^\n{1,}//;
                                    open(OUF, ">$PROC::MRGFILE"); print OUF ("$F\n"); close(OUF);
                                    }
                                #
                                sub procFile {
                                my ($FILE)=(shift);
                                if ($PROC::DEBUG==1) { print ("\tFILE : $FILE\n"); }
                                open(INF, "<$FILE");
                                while(my $LINE=<INF>) {
                                    chomp($LINE);
                                    if ($LINE=~/^alert ip \[/) {
                                        my $SID=$LINE; $SID=~s/^.*.sid://; $SID=~s/;.*//;
                                        my $MSG=$LINE; $MSG=~s/^.*.msg://; $MSG=~s/;.*//; $MSG=~s/"//g;
                                        my $SEV=$LINE; $SEV=~s/^.*.signature_severity //; $SEV=~s/,.*//;
                                        my $F=$FILE; $F=~s/\.rules$//; $F=~s/^.*.\///;
                                        if ($PROC::DEBUG==1) { print ("\t\t1 : $SID : $F : $SEV\n"); }
                                        if (defined($PROC::SEVERITY) && ($SEV eq $PROC::SEVERITY)) {
                                            $PROC::HASH{1}{$SID}{msg}=$MSG;
                                            $PROC::HASH{1}{$SID}{file}=$F;
                                            } elsif (!defined($PROC::SEVERITY)) {
                                            $PROC::HASH{1}{$SID}{msg}=$MSG;
                                            $PROC::HASH{1}{$SID}{file}=$F;
                                            }
                                        }
                                    }
                                close(INF);
                                return;
                                }
                                #
                                __END__
                                ## 
                                ## Documentation
                                ##
                                =head1 NAME
                                
                                generate-suppress.pl
                                
                                =head1 SYNOPSIS
                                
                                generate-suppress.pl --debug --include=<include> --severity=<severity> --targetfile=<targetfile> --mergefile=<mergefile>
                                
                                =head1 DESCRIPTION
                                
                                Generates suppression data from source rules for "alert ip" style entries
                                
                                =head1 FUNCTION
                                
                                Insert or merge alert ip suppression data for SNORT/Suricata
                                
                                =head1 OPTIONS
                                
                                =over
                                
                                =item <debug>
                                
                                Enables debugging output.
                                
                                =item <include>
                                
                                Specifies which rule(s) to include in the resultant data. Comma separated - B<NO> spaces.
                                
                                =item <severity>
                                
                                Filter resultant rules to only those that match severity.
                                (As of creation, appears to be either "Major" or "Minor")
                                
                                =item <targetfile>
                                
                                If the target file exists, it B<WILL> be overwritten with the results.
                                
                                =item <mergefile>
                                
                                If the mergefile already exists, it will be read and only [missing] deltas will be added.
                                
                                =item NOTE
                                If neither targetfile nor mergefile are specified, the results are printed to STDOUT.
                                
                                =back
                                    
                                =head1 COMMON USAGE
                                
                                perl generate-suppress.pl --mergefile=/usr/local/etc/suricata/suricata_<ID>_<interface>/threshold.config
                                
                                =cut
                                

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post
                                Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.