#!/usr/local/bin/perl use strict; use IO::Socket::INET; use Getopt::Std; my %opt; getopts('n:tu', \%opt); my @proto; push @proto, 'TCP' if($opt{t}); push @proto, 'UDP' if($opt{u}); warn "no -t and/or -u: performing ping test only\n" unless($opt{t} || $opt{u}); my %size = (32 => 1, 31 => 2, 30 => 4, 29 => 8, 28 => 16, 27 => 32, 26 => 64, 25 => 128, 24 => 256, ); my %ports = (TCP => [qw/21 22 23 25 43 53 70 80 110 119 123 143 443 465 993 995 2049 4321 5060/], UDP => [qw/53 69 123 161 1645 2049 5060/], ); my %name = (21 => 'FTP', 22 => 'SSH', 23 => 'Telnet', 25 => 'SMTP', 43 => 'Whois', 53 => 'DNS', 69 => 'TFTP', 70 => 'Gopher', 80 => 'HTTP', 110 => 'POP', 119 => 'NNTP', 123 => 'NTP', 143 => 'IMAP', 161 => 'SNMP', 443 => 'HTTPS', 465 => 'SMTPS', 993 => 'IMAPS', 995 => 'POPS', 1645 => 'RADIUS', 2049 => 'NFS', 4321 => 'Rwhois', 5060 => 'SIP', ping => 'Ping', ); my ($netblock,$cidr) = split /\//, $opt{n}; if($netblock =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3})\.(\d{1,3})$/){ my $net = $1; my $oct4 = $2; $cidr = 24 unless($cidr); die "cannot scan network that big\n" unless($cidr >= 24); if($oct4){ die "insane network: $opt{n}\n" if($oct4 % $size{$cidr}); } open(F, ">config.new") || die "cannot write to config.new: $!\n"; my ($user,$pass,$input); until($user =~ /^[a-z0-9_-]{2,20}$/){ print "enter administrative username to log into Argus web page with: "; chop($user=); } system "stty -echo"; until($pass =~ /^\S{3,20}$/){ print "invalid password - 3-20 characters\n" if($pass); print "enter password for $user: "; chop($pass=); } system "stty echo"; print "\n"; srand(time() ^($$ + ($$ << 15))); my @a = grep {/[a-zA-Z0-9]/} map {chr($_)} (0..256); my $salt = $a[ rand( @a ) ] . $a[ rand(@a) ]; my $crypt = crypt($pass, $salt); open (U, ">users.new") || die "cannot write to users.new: $!\n"; print U "$user\t$crypt\tTop\troot\n"; close U; my $n=1; my @email; until(($n > 1) && (! $input)){ print "enter email address #${n} to send notifications"; print " (enter to finish)" if($n > 1); print ": "; chop($input=); if($input =~ /^([a-z0-9_\.\+\-\=\?\^\#]){1,64}\@(([a-z0-9\-]){1,251}\.){1,252}[a-z0-9]{2,4}$/i){ push @email, $input; $n++; }elsif(($input eq '') && ($n > 1)){ last; }else{ print "invalid email address: $input\n"; } } my $string; foreach my $email (@email){ $string .= "mail:${email} "; } chop($string); print F "notify: $string\n"; $input = undef; until(($input =~ /^\d+$/) && ($input > 9 && $input < 241)){ print "invalid frequency: choose above 9 and below 241.\n" if($input); print "how often should Argus check things (seconds) [60]: "; chop($input=); $input = 60 unless($input); } print F "frequency: $input\n"; my $gw = '0.0.0.0'; if(open(N, "netstat -nr 2>&1 |")){ while(){ if(/^(?:default|0\.0\.0\.0)\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s/){ $gw = $1; last; } } close N; } my $gateway; until($gateway =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/){ print "enter your default gateway [$gw]: "; chop($gateway=); $gateway = $gw if($gateway eq ''); } print F "Resolv {\n", "\tfrequency:\t60\n", "\ttimeout:\t20\n", "}\n\n"; my %data; if($cidr == 32){ $data{$netblock} = scan($netblock); }else{ $oct4++; # skip netblock my $i=1; # skip broadcast while($i < $size{$cidr}){ $data{"$net.$oct4"} = scan("$net.$oct4"); $i++; $oct4++; } } print F "Group \"Machines\" {\n"; foreach my $key (keys %data){ if(@{$data{$key}}){ my $hostname; eval { local $SIG{ALRM} = sub { die "timed out on $key\n"; }; my $packed = pack('C4', split /\./, $key); alarm(1); $hostname = gethostbyaddr($packed,2); alarm(0); }; alarm(0); $hostname = $key unless($hostname); print F "\tHost \"$hostname\" {\n"; foreach my $value (@{$data{$key}}){ if(my $x = $name{$value->[0]}){ print F "\t\tService "; print F "\t$value->[1]/" if($value->[1]); print F "\t$x\n"; }else{ warn "skipping $value->[0]/$value->[1]\n"; } } print F "\t}\n"; } } print F "}\n", "Group \"Other\" {\n", "\tGroup \"My Stats\" {\n", "\t\tgraph:\tyes\n", "\t\tService Self/Notifs\n", "\t\tService Self/idle {\n", "\t\t\ttitle:\tPercent Idle\n", "\t\t\tcalc:\tave-rate\n", "\t\t\tscale:\t0.01\n", "\t\t\tminvalue:\t20\n", "\t\t\tmessagedn:\ttime to buy a faster server\n", "\t\t}\n", "\t\tService Self/tested {\n", "\t\t\ttitle\tMonitor Rate\n", "\t\t\tylabel:\ttests per second\n", "\t\t\tcalc:\tave-rate\n", "\t\t}\n", "\t\tService Prog {\n", "\t\t\t# your ps may be different\n", "\t\t\tcommand:\tps -p \$ARGUS_PID -o vsz | tail -1\n", "\t\t\tuname:\tVSZ\n", "\t\t\ttitle:\tMemory Use\n", "\t\t\tylabel:\tkBytes\n", "\t\t}\n", "\t}\n", "}\n", "Group \"Upstream Connections\" {\n", "\tHost \"$gateway\" {\n", "\t\tService Ping\n", "\t}\n", "}\n"; close F; print 'done. rename "users.new" to "users" and "config.new" to "config".', "\n"; }else{ die "invalid network: $opt{n}\n"; } sub scan { my $host = shift; my @services; my $res = `ping $host 1`; if($res =~ /is alive/){ push @services, ['ping']; } foreach my $proto (@proto){ foreach my $port (@{$ports{$proto}}){ warn "$host -> $port/$proto\n"; my $sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => $proto, Timeout => 1); if($sock){ push @services, [$port, $proto]; close $sock; } } } return(\@services); }