#!perl -w # this plugin checks the relayclients config file and # $ENV{RELAYCLIENT} to see if relaying is allowed. # use Net::IP qw(:PROC); sub hook_connect { my ($self, $transaction) = @_; my $connection = $self->qp->connection; # Check if this IP is allowed to relay my $client_ip = $self->qp->connection->remote_ip; # @crelay... for comparing, @srelay... for stripping my (@crelay_clients, @srelay_clients); my @relay_clients = $self->qp->config("relayclients"); for (@relay_clients) { my ($range_ip, $range_prefix) = ip_splitprefix($_); if($range_prefix){ # has a prefix, so due for comparing push @crelay_clients, $_; } else { # has no prefix, so due for splitting push @srelay_clients, $_; } } if (@crelay_clients){ my ($range_ip, $range_prefix, $rversion, $begin, $end, $bin_client_ip); my $cversion = ip_get_version($client_ip); for (@crelay_clients) { # Get just the IP from the CIDR range, to get the IP version, so we can # get the start and end of the range ($range_ip, $range_prefix) = ip_splitprefix($_); $rversion = ip_get_version($range_ip); ($begin, $end) = ip_normalize($_, $rversion); # expand the client address (zero pad it) before converting to binary $bin_client_ip = ip_iptobin(ip_expand_address($client_ip, $cversion), $cversion); if (ip_bincomp($bin_client_ip, 'gt', ip_iptobin($begin, $rversion)) && ip_bincomp($bin_client_ip, 'lt', ip_iptobin($end, $rversion))) { $connection->relay_client(1); last; } } } # If relay_client is already set, no point checking again if (@srelay_clients && !$connection->relay_client) { my $more_relay_clients = $self->qp->config("morerelayclients", "map"); my %srelay_clients = map { $_ => 1 } @srelay_clients; $client_ip =~ s/::/:/; ($connection->relay_client(1) && undef($client_ip)) if $client_ip eq ":1"; while ($client_ip) { if (exists($ENV{RELAYCLIENT}) or exists($srelay_clients{$client_ip}) or exists($more_relay_clients->{$client_ip})) { $connection->relay_client(1); last; } $client_ip =~ s/(\d|\w)+(:|\.)?$//; # strip off another 8 bits } } return (DECLINED); }