Mojolicious-Plugin-ClientIP-Pluggable

 view release on metacpan or  search on metacpan

lib/Mojolicious/Plugin/ClientIP/Pluggable.pm  view on Meta::CPAN

detect IP address from C<X-Forwarded-For> header, detect IP address from C<forwarded> header
(rfc-7239), or use C<remote_address> environment.

The plugin is inspired by L<Mojolicious::Plugin::ClientIP>.

=head1 METHODS

=head2 client_ip

Find a client IP address from the specified headers, with optional fallbacks. The address is
validated that it is publicly available (aka routable) IP address. Empty string is returned
if no valid address can be found.

=head1 OPTIONS

=head2 analyzed_headers

Define order and names of cloud provider injected headers with client IP address.
For C<cloudflare> we found the following headers are suitable:

    plugin 'ClientIP::Pluggable',

lib/Mojolicious/Plugin/ClientIP/Pluggable.pm  view on Meta::CPAN

            push @candidates, @ips;
        } elsif ($fallback eq 'remote_address') {
            push @candidates, $c->tx->remote_address;
        } elsif ($fallback eq 'rfc-7239') {
            my $f = $headers->header('forwarded');
            next unless $f;
            my @pairs = map { split $comma_re, $_ } split ';', $f;
            my @ips = map {
                my $ipv4_mask = qr/\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/;
                # it is not completely valid ipv6 mask, but enough
                # to extract address. It will be validated later
                my $ipv6_mask = qr/[\w:]+/;
                if (/for=($ipv4_mask)|(?:"?\[($ipv6_mask)\].*"?)/i) {
                    ($1 // $2);
                } else {
                    ();
                }
            } @pairs;
            push @candidates, @ips;
        } else {
            warn "Unknown fallback option $fallback, ignoring";

lib/Mojolicious/Plugin/ClientIP/Pluggable.pm  view on Meta::CPAN

                # generic check
                next unless Data::Validate::IP::is_ip($ip);

                # classify & check
                my $address_family = _classify_ip($ip);
                next unless $address_family;

                # possibly limit to acceptable address family
                next if $restrict_family && $restrict_family ne $address_family;

                # validate by family
                my $validator = $validator_for{$address_family};
                next unless $validator->($ip);

                # address seems valid, return its textual representation
                return $ip;
            }
            return '';
        });

    return;



( run in 0.440 second using v1.01-cache-2.11-cpan-39bf76dae61 )