Firewall Wizards mailing list archives
pulling configs from pixes over ssh script
From: Vladimir Parkhaev <vladimir () arobas net>
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
Current thread:
- pulling configs from pixes over ssh script Vladimir Parkhaev (May 28)