[fw-wiz] pulling configs from pixes over ssh script

From: Vladimir Parkhaev (vladimir_at_arobas.net)
Date: 05/28/03

  • Next message: Paul Robertson: "Re: [fw-wiz] Benefit of firewall over NAT-only 'protected' network"
    To: firewall-wizards@honor.icsalabs.com
    Date: Wed, 28 May 2003 09:28:55 -0400
    

    Well, I see that a lot of people out there still manage their firewall
    via telnet. It is a no-no in my books but not all products out there
    have decent SSH daemons... Cisco PIX has one (SSH1), but automating
    tasks like pulling configs or getting failover status seemed still
    impossible.

    Being a perl dude, I tried Net::SSH::Perl module but
    'perldoc Net::SSH::Perl' said:

    "NOTE: the SSH-1 protocol does not support running multiple
           commands per connection, unless those commands are chained
           together so that the remote shell can evaluate them.
           Because of this, a new socket connection is created each
           time you call cmd, and disposed of afterwords."

    Basically you cannot go into enable mode - you get disconnected.

    I knew there had to be a (at least one) way to do it :) And there is!
    I was able to use this method with both Cisco PIXes and Routers.
    Anyway to make a long story short, I just want to share my code.
    You can adapt it to your needs if you are familiar with basics
    of programming...

    #!/usr/local/bin/perl -w
    # This script pulls config from Cisco PIX device over SSH1.
    # Written by Vladimir Parkhaev
    # This code is free as a bird.
    # If you have any questions run:
    # perl -e 'print scalar reverse "ten.sabora\@rimidalv"' to get my email.
    # Special mention to Benjamin::Trott- Net::SSH::Perl and Net::SFTP rock!
    #
    # Steps:
    # 1. login
    # 2. go to enable mode ('en')
    # 3. execute 'no pager' to disable paging
    # 4. execute 'show conf'
    # 5. read the config
    # 6. logout
    # 7. deal with config
    # Looks like config arrives as one line at the time
    #
    $|++;
    use strict;
    use Net::SSH::Perl;
    use Net::SSH::Perl::Constants qw( :msg );
    use constant SKIP_PROMPT => 1; # pix prints login prompt twice, skip first

    my $host = shift || die "Usage: $0 pix_name\n";
    my $time2login = 10;
    my $time2run = 20;

    # modify these in case of prompt (hostname) changes
    # assuming alphanumeric characters only:
    # [a-zA-Z0-9] is actually \w, but some hosts have '_' or '-' in their names
    my $enb_prompt = qr/(?:[a-zA-Z0-9]+#)\s*/; # alphanumeric followed by '#'
    my $reg_prompt = qr/(?:[a-zA-Z0-9]+>)\s*/; # alphanumeric followed by '>'
    my $pass_prompt = qr/Password:\s*/;

    my ($prompt_cnt,$save,$done) = (0,0,0);
    my ($ssh, @config);

    # login on the device
    eval {
       local $SIG{'ALRM'} = sub { die 'TimedouT' };
       alarm $time2login;
       $ssh = Net::SSH::Perl->new($host, protocol=>1, cipher=>'DES', port=>22);
       $ssh->login('pix','PASSWD_HERE');
       alarm 0;
    };

    ($@)? ( die '[',scalar localtime,'] ', ($@ =~ /TimedouT/)?
                                           "Takes too long to login on $host.\n" :
                                           "Unexpected eval err: $@.\n"
          ) : undef;

    # set up handler and intercept everything that goes to STDOUT

    $ssh->register_handler(SSH_SMSG_STDOUT_DATA, sub {
       my($ssh, $packet) = @_;
       my $str = $packet->get_str;

       if ( $save ) { # reading config

          if ( $str =~ /$enb_prompt$/ ) { # last line of the config + prompt
             my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
             $packet->put_str('exit ' . "\n");
             $packet->send;
             $done++;
          }

          $str =~ s/\cM//g;
          chomp $str;
           
          # skip echo of the command and logout sequence
          push @config, $str unless ( $done || $str =~ /^(\w|\s)$/ ||
                                      $str =~ /^:/ || $str eq '' );
        }
        else { # login part
           if ($str =~ /$reg_prompt$/) { # go to enable mode
              $prompt_cnt++; # pix prints login prompt twice, remember
              return unless $prompt_cnt > SKIP_PROMPT;
              my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
              $packet->put_str('enable' . "\n");
              $packet->send;
              $prompt_cnt = 0; # will resuse it in enable mode
           }
           elsif ( $str =~ /$pass_prompt$/ ) {
              # going into enable mode....
              my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
              $packet->put_str("ENABLED PWD HERE\n");
              $packet->send;
           }
           elsif ( $str =~ /$enb_prompt$/ && !$prompt_cnt ) {
              # exec first command in enable mode
              my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
              $packet->put_str('no pager' . "\n");
              $packet->send;
              $prompt_cnt++;
           }
           elsif ( $str =~ /$enb_prompt$/ && $prompt_cnt ) {
              # exec second command in enable mode, ready to rock
              my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
              $packet->put_str('show conf' . "\n");
              $packet->send;
              $save++;
           }
           else {
              # Uncomment this for debug purposes
              # print "Useless data: $str\n";
           }
       }

    });

    eval {
       local $SIG{'ALRM'} = sub { die 'TimedouT' };
       alarm $time2run;
       $ssh->cmd(''); # thaaaat's right, nothing at all
       alarm 0;
    };

    ($@)? ( die '[',scalar localtime,'] ', ($@ =~ /TimedouT/)?
                                           "Timed out while pulling from $host.\n" :
                                           "Unexpected eval err: $@.\n"
          ) : undef;

    pop @config if $config[-1] =~ /^Cryptochecksum/; # who needs it?
    shift @config if $config[0] =~ /^PIX/; # and version too....

    # at this point you have config in @config
    # do whatever you need to do with it
    print join "\n", @config, '';

    __END__

    -- 
    .signature: No such file or directory
    _______________________________________________
    firewall-wizards mailing list
    firewall-wizards@honor.icsalabs.com
    http://honor.icsalabs.com/mailman/listinfo/firewall-wizards
    

  • Next message: Paul Robertson: "Re: [fw-wiz] Benefit of firewall over NAT-only 'protected' network"

    Relevant Pages

    • Re: EPP Cost vs. Coupon Cost?
      ... Jay is right, don't get the, McAfee Security Center with ... VirusScan, Firewall, Spyware Removal, 15-months. ... i routinely buy the 1.83 for around $800 in your config. ... Network Card and Modem Integrated 10/100 Network Card and Modem ...
      (alt.sys.pc-clone.dell)
    • RE: Configure Firewall fails
      ... 39856232-Configure Firewall fails. ... Microsoft CSS Online Newsgroup Support ... This newsgroup only focuses on SBS technical issues. ... <configuration, it completes all steps (Network Config, Secure Web Site ...
      (microsoft.public.windows.server.sbs)
    • RE: [fw-wiz] Cisco VPN Client "Stateful Firewall (Always On)"
      ... under network config in Windows 2000/NT. ... I have insisted that a firewall be included in this ... Basically, as I understand it, this feature allows all outbound ... connections while active, and all inbound connections originally established ...
      (Firewall-Wizards)
    • Re: ip masquerading
      ... > Your firewall rules look, uh, ugly, meaning, not meant for human eyes. ... > resulted from the inclusion of the rp-pppoe.so plugin in my DSL config ...
      (Debian-User)
    • [VulnWatch] FVS318 Config stores usernames/passwds in plain text
      ... Netgear's FVS318 Firewall/VPN/Router stores Usernames and Passwords ... ProSafe VPN Firewall provides business-class protection at a NAT router ... The web interface includes a backup option to store your current config ...
      (VulnWatch)