Bug 24593: Rewrite marc21_default_matching_rules to YAML
[koha.git] / Koha / Middleware / RealIP.pm
blob88a843dbcf361defa3ec476fe3e12d24a1a09a79
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 my @unconfirmed = ( @forwarded_for, $remote_addr );
86 my $real_ip;
87 while (my $addr = pop @unconfirmed) {
88 my $has_matched = 0;
89 foreach my $netmask (@$trusted_proxies) {
90 $has_matched++, last if $netmask->match($addr);
92 $real_ip = $addr, last unless $has_matched;
95 return $real_ip;
98 =head2 get_trusted_proxies
100 This method returns an arrayref of Net::Netmask objects for all
101 the trusted proxies given to Koha.
103 =cut
105 sub get_trusted_proxies {
106 my $proxies_conf = C4::Context->config('koha_trusted_proxies');
107 return unless $proxies_conf;
108 my @trusted_proxies_ip = split( / /, $proxies_conf );
109 my @trusted_proxies = ();
110 foreach my $ip (@trusted_proxies_ip){
111 my $mask = Net::Netmask->new2($ip);
112 if ($mask){
113 push(@trusted_proxies,$mask);
115 else {
116 warn "$Net::Netmask::error";
119 return \@trusted_proxies;
123 =head1 AUTHORS
125 Kyle M Hall <kyle@bywatersolutions.com>
127 =cut