Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Sifting through firewall rules using a script

by Fletch (Bishop)
on Dec 23, 2021 at 13:29 UTC ( [id://11139861]=note: print w/replies, xml ) Need Help??


in reply to Sifting through firewall rules using a script

Depending on the number of IPs it might be slightly better performance if you used Regexp::Common and $RE{net}{IPv4} to extract out IP-address-looking-things from rule lines, then checked those against a hash for hits of interesting ones. Rather than running n different regular expressions over each firewall rule line n times, this runs one over only as many times as necessary to get out the IP-ish things in any given rule line and then you're doing a (much faster) hash existence test to see if that IP is a wanted one.

use Regexp::Common qw( net ); my %interesting_ips; while( <IPS> ) { chomp; $interesting_ips{ $_ } = 1; } while( my $fw_line = <RULES> ) { while( my( $addr ) = $fw_line =~ m{($RE{net}{IPv4})}g ) { say qq{$.: found interesting address '$addr'} if exists $interesting_ips{ $addr }; } }

The cake is a lie.
The cake is a lie.
The cake is a lie.

Replies are listed 'Best First'.
Re^2: Sifting through firewall rules using a script
by networkdude (Initiate) on Jan 10, 2022 at 01:17 UTC

    Hi Team! I was on Christmas break so just got back and found your amazing answers! THANK YOU SO MUCH!

    I have adjusted the script according to your collective feedback and I also realised I need to explain a bit more what I am trying to do

    I have two files; one file with all my interesting IPs in it; and another file with all the firewall rules in it. I need to sift through the firewall rules and PRINT THE ENTIRE FW RULE LINE in the FW rules file if it matches any of the IPs in the interesting IP address file.

    My interesting IP file:

    1.1.1.1 2.2.2.2 10.198.0.0 3.3.3.3 10.198.1.0
    My FW rules file:
    133 bba33132-6192-51e8-4d78-c1b7bfd47251 any V072-AklC-DB MOSSACSQLAdm +inGroup 10.198.0.0/16 10.210.0.0/16 MOSS_SQLAD_10-208-22-1/28 accept + always RDP TCP17338 TCP18230 PING all change 125213 157309 + 136 a5ea4ee8-6192-51e8-0252-2017208af83d any V071-AklC-Web ACHenderson +RDPUsers 10.198.1.0/16 10.210.0.0/16 MOSS_InternalWeb_10-208-22-16/28 + accept always FTP all
    My adjusted script:
    use strict; use warnings; use Regexp::Common qw( net ); open ( IPS, '<', "TEST_IPS.txt" ) || die "can't open IPS!"; open ( RULES, '<', "test_rules.txt" ) || die "can't open file!"; my %interesting_ips; while( <IPS> ) { chomp; $interesting_ips{ $_ } = 1; } while( my $fw_line = <RULES> ) { while( my( $addr ) = $fw_line =~ m{($RE{net}{IPv4})}g ) { print ( $fw_line); } }
    When I run the script, two things happen:
    1. It only matches the first match and never moves on to the second match, and
    2. It does not exit and I have to ctrl+c to get it to stop filling the screen with the first match

    What am I doing wrong please?

    I can repay the help in honey from my backyard beehives. It's very very yummy!

      Minor stylistic nitpicks before anything substantive: lexical filehandles are better than bareword globals like you've used, and you want to include $! in the error message so you know why the open failed.

      open( my $ips, '<', 'TEST_IPS.txt' ) or die "Can't open IPS: $!\n";

      That out of the way you're close but you don't consult %interesting_ips in any way to tell if you have a match. You also want to pull the list of matching IPs out differently.

      #!/usr/bin/env perl use strict; use warnings; use Regexp::Common qw( net ); open ( my $ips_fh, '<', "TEST_IPS.txt" ) or die "can't open IPS: $!\n" +; open ( my $rules_fh, '<', "test_rules.txt" ) or die "can't open rules: + $!\n"; my %interesting_ips; while( <$ips_fh> ) { chomp; $interesting_ips{ $_ } = 1; } close( $ips_fh ); while( my $fw_line = <$rules_fh> ) { chomp( $fw_line ); my( @addresses ) = $fw_line =~ m{ ($RE{net}{IPv4}) }gx; for my $addr ( @addresses ) { next unless exists $interesting_ips{ $addr }; print qq{$.:interesting '$addr': $fw_line\n}; } } close( $rules_fh ); exit 0; __END__ $ perl pm_foo.plx 1:interesting '10.198.0.0': 133 bba33132-6192-51e8-4d78-c1b7bfd47251 a +ny V072-AklC-DB MOSSACSQLAdminGroup 10.198.0.0/16 10.210.0.0/16 MOSS_ +SQLAD_10-208-22-1/28 accept always RDP TCP17338 TCP18230 PING all + change 125213 157309 2:interesting '10.198.1.0': 136 a5ea4ee8-6192-51e8-0252-2017208af83d a +ny V071-AklC-Web ACHendersonRDPUsers 10.198.1.0/16 10.210.0.0/16 MOSS +_InternalWeb_10-208-22-16/28 accept always FTP all

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        I've been debugging it and I wonder if it is a perl version problem, based on this error:

        Regexp::Common::_decache(/usr/share/perl5/Regexp/Common.pm:138): 138: my $cache = get_cache(@nonflags); 139: _croak "Can't create unknown regex: \$RE{" 140: . join("}{",@args) . "}"

        And this error

        Use of uninitialized value $_ in print at (eval 42)[/usr/share/perl/5. +30/perl5db.pl:738] line 2, <$rules_fh> line 1. at (eval 42)[/usr/share/perl/5.30/perl5db.pl:738] line 2, <$rules_fh> + line 1.

        I have tried to get your last edit to work and now it doesn't match anything

        grumpy@DC5CG1243JCB:/mnt/c/Linux/Scripts$ perl -w -T rulechecker6.pl grumpy@DC5CG1243JCB:/mnt/c/Linux/Scripts$

        Nuthin... I wonder what is going on

        interesting - I got it to work exactly as you posted it using an Ubuntu box but on the WSL (Windows Linux), it does not work at all!

      I almost got it to work but no dice. It matches everything. Must be the if line. What does the regex m{($RE{net}{IPv4})}g actually do here? I know what the line means from the documentation for that module, but what is the exact purpose in this script?

      use strict; use warnings; use Regexp::Common qw( net ); open ( IPS, '<', "TEST_IPS.txt" ) || die "can't open IPS!"; open ( RULES, '<', "test_rules.txt" ) || die "can't open file!"; my %interesting_ips; while( <IPS> ) { chomp; $interesting_ips{ $_ } = 1; } while( my $fw_line = <RULES> ) { if ($fw_line =~ m{($RE{net}{IPv4})}g ) { print ( $fw_line); } }

        False alarm - it still doesn't work. Not even with the latest awesome recommendations. See my other replies...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11139861]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-04-23 11:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found