View | Details | Raw Unified | Return to bug 39789
Collapse All | Expand All

(-)a/Koha/Middleware/RealIP.pm (-18 / +25 lines)
Lines 51-63 sub call { Link Here
51
    my $self = shift;
51
    my $self = shift;
52
    my $env  = shift;
52
    my $env  = shift;
53
53
54
    # If no reverse_proxy_ip_header, just use HTTP_X_FORWARDED_FOR as the header to check, simplifies logic and is a bit faster that way
55
    my $reverse_proxy_ip_header = C4::Context->config('reverse_proxy_ip_header') || 'HTTP_X_FORWARDED_FOR';
54
    my $reverse_proxy_ip_header = C4::Context->config('reverse_proxy_ip_header') || 'HTTP_X_FORWARDED_FOR';
55
    my $require_trusted         = C4::Context->config('require_trusted_proxy_for_headers');
56
56
57
    # Check the env for the custom header, if the custom header is not set, fall back to HTTP_X_FORWARDED_FOR
58
    my $header = $env->{$reverse_proxy_ip_header} || $env->{'HTTP_X_FORWARDED_FOR'};
57
    my $header = $env->{$reverse_proxy_ip_header} || $env->{'HTTP_X_FORWARDED_FOR'};
58
    my $addr   = $env->{REMOTE_ADDR};
59
59
    if ($header) {
60
    if ($header) {
60
        my $addr = get_real_ip( $env->{REMOTE_ADDR}, $header );
61
        if ($require_trusted) {
62
63
            # Only trust header if REMOTE_ADDR is a trusted proxy
64
            my $trusted_proxies = get_trusted_proxies();
65
            my $is_trusted      = 0;
66
            foreach my $netmask (@$trusted_proxies) {
67
                if ( $netmask->match($addr) ) {
68
                    $is_trusted = 1;
69
                    last;
70
                }
71
            }
72
            if ($is_trusted) {
73
                $addr = get_real_ip( $env->{REMOTE_ADDR}, $header );
74
            }
75
        } else {
76
77
            # Always trust the header
78
            $addr = get_real_ip( $env->{REMOTE_ADDR}, $header );
79
        }
61
        $ENV{REMOTE_ADDR} = $addr;
80
        $ENV{REMOTE_ADDR} = $addr;
62
        $env->{REMOTE_ADDR} = $addr;
81
        $env->{REMOTE_ADDR} = $addr;
63
    }
82
    }
Lines 80-100 sub get_real_ip { Link Here
80
    my @forwarded_for = $header =~ /([^,\s]+)/g;
99
    my @forwarded_for = $header =~ /([^,\s]+)/g;
81
    return $remote_addr unless @forwarded_for;
100
    return $remote_addr unless @forwarded_for;
82
101
83
    my $trusted_proxies = get_trusted_proxies();
84
85
    #X-Forwarded-For: <client>, <proxy1>, <proxy2>
102
    #X-Forwarded-For: <client>, <proxy1>, <proxy2>
86
    my $real_ip     = shift @forwarded_for;
103
    my $real_ip = shift @forwarded_for;
87
    my @unconfirmed = ( @forwarded_for, $remote_addr );
104
    return $real_ip if $real_ip;
88
105
    return $remote_addr;
89
    while ( my $addr = pop @unconfirmed ) {
90
        my $has_matched = 0;
91
        foreach my $netmask (@$trusted_proxies) {
92
            $has_matched++, last if $netmask->match($addr);
93
        }
94
        $real_ip = $addr, last unless $has_matched;
95
    }
96
97
    return $real_ip;
98
}
106
}
99
107
100
=head2 get_trusted_proxies
108
=head2 get_trusted_proxies
101
- 

Return to bug 39789