Bug 18958: Make hold_fill_targets specific to reserves
[koha.git] / Koha / Middleware / RealIP.pm
blobfc9f280ff68bb72ef39871916a432b463b3ca9e4
1 package Koha::Middleware::RealIP;
3 # Copyright 2019 ByWater Solutions and the Koha Dev Team
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Modern::Perl;
22 use parent qw(Plack::Middleware);
24 use C4::Context;
26 use Net::Netmask;
27 use Plack::Util::Accessor qw( trusted_proxy );
29 =head1 METHODS
31 =head2 prepare_app
33 This method generates and stores the list of trusted ip's as Netmask objects
34 at the time Plack starts up, obviating the need to regerenate them on each request.
36 =cut
38 sub prepare_app {
39 my $self = shift;
40 $self->trusted_proxy( get_trusted_proxies() );
43 =head2 call
45 This method is called for each request, and will ensure the correct remote address
46 is set in the REMOTE_ADDR environment variable.
48 =cut
50 sub call {
51 my $self = shift;
52 my $env = shift;
54 if ( $env->{HTTP_X_FORWARDED_FOR} ) {
55 my @trusted_proxy = $self->trusted_proxy ? @{ $self->trusted_proxy } : undef;
57 if (@trusted_proxy) {
58 my $addr = get_real_ip( $env->{REMOTE_ADDR}, $env->{HTTP_X_FORWARDED_FOR}, \@trusted_proxy );
59 $ENV{REMOTE_ADDR} = $addr;
60 $env->{REMOTE_ADDR} = $addr;
64 return $self->app->($env);
67 =head2 get_real_ip
69 my $address = get_real_ip( $remote_addres, $x_forwarded_for_header );
71 This method takes the current remote address and the x-forwarded-for header string,
72 determines the correct external ip address, and returns it.
74 =cut
76 sub get_real_ip {
77 my ( $remote_addr, $header ) = @_;
79 my @forwarded_for = $header =~ /([^,\s]+)/g;
80 return $remote_addr unless @forwarded_for;
82 my $trusted_proxies = get_trusted_proxies();
84 #X-Forwarded-For: <client>, <proxy1>, <proxy2>
85 my $real_ip = shift @forwarded_for;
86 my @unconfirmed = ( @forwarded_for, $remote_addr );
88 while (my $addr = pop @unconfirmed) {
89 my $has_matched = 0;
90 foreach my $netmask (@$trusted_proxies) {
91 $has_matched++, last if $netmask->match($addr);
93 $real_ip = $addr, last unless $has_matched;
96 return $real_ip;
99 =head2 get_trusted_proxies
101 This method returns an arrayref of Net::Netmask objects for all
102 the trusted proxies given to Koha.
104 =cut
106 sub get_trusted_proxies {
107 my $proxies_conf = C4::Context->config('koha_trusted_proxies');
108 return unless $proxies_conf;
109 my @trusted_proxies_ip = split( / /, $proxies_conf );
110 my @trusted_proxies = ();
111 foreach my $ip (@trusted_proxies_ip){
112 my $mask = Net::Netmask->new2($ip);
113 if ($mask){
114 push(@trusted_proxies,$mask);
116 else {
117 warn "$Net::Netmask::error";
120 return \@trusted_proxies;
124 =head1 AUTHORS
126 Kyle M Hall <kyle@bywatersolutions.com>
128 =cut