diff --git a/lib/Resmon/Config.pm b/lib/Resmon/Config.pm index 741603882b022ee0d6ca35afe254a11fa2a17da2..b8fdb9dd2fdbf5221519e6969fdd99f61c59435d 100755 --- a/lib/Resmon/Config.pm +++ b/lib/Resmon/Config.pm @@ -5,6 +5,23 @@ use warnings; use Sys::Hostname; + +sub split_ip_list { +# this code is taken from Marcel Gruenauer's <marcel@cpan.org> CPAN module Net::IP::Match + my $string = shift; + my $allow = shift; + my (@result,$quad,$bits,$matchbits,$int,$mask); + for (split (/\s*[,\s]\s*/, $string)) { + ($quad, $bits) = m!^(\d+\.\d+\.\d+\.\d+)(?:/(\d+))?!g; + $bits = 32 unless (defined($bits) && $bits ne ''); + $matchbits = 32 - $bits; + $int = unpack("N", pack("C4", split(/\./,$quad))); + $mask = $int >> $matchbits; + push @result => {mask => $mask, bits => $matchbits, allow => $allow}; +print STDERR "mask=$mask,bits=$matchbits,allow=$allow\n"; + } + return \@result; +} sub new { my $class = shift; my $filename = shift; @@ -130,6 +147,14 @@ sub new { elsif(/\s*AUTHPASS\s+(\S+)\s*;\s*/) { $self->{authpass} = $1; next; + } + elsif(/\s*HOSTS\s+ALLOW\s+([^;]+)\s*;\s*/) { + push (@{$self->{hostsallow}}, @{split_ip_list($1,1)}); + next; + } + elsif(/\s*HOSTS\s+DENY\s+([^;]+)\s*;\s*/) { + push (@{$self->{hostsallow}}, @{split_ip_list($1,0)}); + next; } elsif(/\s*INCLUDE\s+(\S+)\s*;\s*/) { my $incglob = $1; diff --git a/lib/Resmon/Status.pm b/lib/Resmon/Status.pm index 7755c8f837c7322d2a6065146170f6a1c3f908ff..19b6c2094755f5cb2b3d84fbae902797b925ac47 100644 --- a/lib/Resmon/Status.pm +++ b/lib/Resmon/Status.pm @@ -441,6 +441,8 @@ sub serve_http_on { my $port = shift; $self->{authuser} = shift; $self->{authpass} = shift; + my $hostsallow = shift; + if(!defined($ip) || $ip eq '' || $ip eq '*') { $ip = INADDR_ANY; } else { @@ -469,6 +471,25 @@ sub serve_http_on { while(1) { my $client = $handle->accept; next unless $client; + my $hersockaddr = getpeername($client); + my ($port, $iaddr) = sockaddr_in($hersockaddr); + my $denied; + for my $el (@{$hostsallow}) { + my $tmp = unpack("N",$iaddr); + $tmp = $tmp >> $el->{bits} if $el->{bits}; + if ($tmp == $el->{mask}) { + $denied = !$el->{allow}; + last; + } + } + if ($denied) { + my $response = "<html><head><title>IP denied</title></head>" . + "<body><h1>IP denied</h1></body></html>"; + $client->print(http_header(401, length($response), 'text/html', $denied)); + $client->print($response . "\r\n"); + $client->close(); + next + }; my $req; my $proto; my $close_connection; diff --git a/resmon b/resmon index f3fd6fcb1481fc0841e3b0d14e5c262ef556bff8..fd78b852d33f7fae6de53ca9f1545a5f4ee27a8c 100755 --- a/resmon +++ b/resmon @@ -84,7 +84,7 @@ my $list = []; $status = Resmon::Status->new($config->{statusfile}); $status->open(); $status->serve_http_on($config->{interface}, $config->{port}, - $config->{authuser}, $config->{authpass}) + $config->{authuser}, $config->{authpass}, $config->{hostsallow}) if($config->{port}); while(1) { diff --git a/resmon.conf.sample b/resmon.conf.sample index f36b848c24f5d56d6bebbcec9e8ab5c36e81ab8f..13196713b28a86f24477673329b862bcc0675d82 100755 --- a/resmon.conf.sample +++ b/resmon.conf.sample @@ -3,6 +3,15 @@ PORT 81; STATUSFILE /var/run/resmon-status.txt; TIMEOUT 10; +HOSTS ALLOW 10.80.116.112, 127.0.0.1; +# HOSTS {ALLOW/DENY} lists are the coma or blank separated lists of +# a dotted decimal IPv4 addresses of the form a.b.c.d. to match incoming machine’s IP address exactly, +# or an 'ipaddr/n' where ipaddr is the IP address and n is the number of one bits in the netmask. +# the first match gives the result, if nothing matches IP is allowed. +HOSTS DENY 10.80.117.128/25 +HOSTS ALLOW 10.80.116.0/23 +HOSTS DENY 0.0.0.0/0; + # Resmon health check. Shows the hostname, svn revision and # any problems with modules or the configuration file. Core::Resmon { diff --git a/resources/check_resmon_metric b/resources/check_resmon_metric index dda68457d8e029137c8c74b567a812c1264f06b2..1171f1db76a6f9b0eaeb647bfb217f22ce1def5b 100755 --- a/resources/check_resmon_metric +++ b/resources/check_resmon_metric @@ -374,6 +374,9 @@ eval { } if (defined $regex) { + if (!defined($value)) { + $value = ''; + } if ($value =~ /$regex/) { $state = "OK"; } else {