in reply to Re^4: mod-perl2 re-using $ENV{REMOTE_ADDR}
in thread mod-perl2 re-using $ENV{REMOTE_ADDR}

This is really great, many many thanks!

So ideally:
I would like to order the IPs by those present in the HTTP_X_FORWARDED_FOR header, failing which it should use REMOTE_ADDR.
I would like to prefer the first public IP, alternatively the last valid private IP (closest to the client).

Your loop is much cleaner and easier to understand, avoids the double negative that I was doing (unshifting REMOTE_ADDR to the beginning of the array and then selecting the last entry). The problem that you high-lighted with my loop also explains the odd case where some small WISPs were transparently natting HTTP behind fake public IPs in their network.

use Data::Validate::IP qw(is_ip is_public_ip is_loopback_ip); my($valid_ip, $valid_public); my @IPs; if (defined $ENV{HTTP_X_FORWARDED_FOR}) { @IPs=split /,/, $ENV{HTTP_X_FORWARDED_FOR}; }; push(@IPs, $ENV{REMOTE_ADDR}); foreach my $check (@IPs) { # trim whitespaces $check =~ s/\s//g; # skip if not a valid IP next unless is_ip($check); # overwrite with last valid IP #$valid_ip //= $check; # select first valid ip $valid_ip = $check; # skip unless it's a public, loopback or proxy IP next if (not is_public_ip($check)) or (is_loopback_ip($check)) or ($check eq "192.0.2.90"); # overwrite with the last valid public IP $valid_public = $check; # select first public IP last; } # select public IP, if we found one, else last valid IP my $ip = $valid_public // $valid_ip; print "Content-type: text/html\nCache-Control: max-age=0,no-cache,no-s +tore,post-check=0,pre-check=0\n\n<html><head><title>Current IP Check< +/title></head><body>Current IP Address: $ip</body></html>";