[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)
    • Re: Long time taking for Single user to logon
      ... Actually connectivity is established through the Hardware firewall. ... which login normally through this firewall. ... IP config for the users points to the DNS in main office. ... Also, if you only have one domain, ALL domain controllers should be a GC. ...
      (microsoft.public.windows.server.active_directory)