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

(-)a/C4/Auth.pm (+2 lines)
Lines 57-62 BEGIN { Link Here
57
        else            { exit }
57
        else            { exit }
58
    }
58
    }
59
59
60
    C4::Context->set_remote_address;
61
60
    $debug     = $ENV{DEBUG};
62
    $debug     = $ENV{DEBUG};
61
    @ISA       = qw(Exporter);
63
    @ISA       = qw(Exporter);
62
    @EXPORT    = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions);
64
    @EXPORT    = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions);
(-)a/C4/Context.pm (+20 lines)
Lines 1099-1104 sub temporary_directory { Link Here
1099
    return C4::Context->config('tmp_path') || File::Spec->tmpdir;
1099
    return C4::Context->config('tmp_path') || File::Spec->tmpdir;
1100
}
1100
}
1101
1101
1102
=head3 set_remote_address
1103
1104
set_remote_address should be called at the beginning of every script
1105
that is *not* running under plack in order to the REMOTE_ADDR environment
1106
variable to be set correctly.
1107
1108
=cut
1109
1110
sub set_remote_address {
1111
    if ( C4::Context->config('koha_trusted_proxies') ) {
1112
        require CGI;
1113
        my $cgi    = CGI->new;
1114
        my $header = $cgi->http('HTTP_X_FORWARDED_FOR');
1115
1116
        if ($header) {
1117
            require Koha::Middleware::RealIP;
1118
            $ENV{REMOTE_ADDR} = Koha::Middleware::RealIP::get_real_ip( $ENV{REMOTE_ADDR}, $header );
1119
        }
1120
    }
1121
}
1102
1122
1103
1;
1123
1;
1104
1124
(-)a/Koha/Middleware/RealIP.pm (+118 lines)
Line 0 Link Here
1
package Koha::Middleware::RealIP;
2
3
# Copyright 2019 ByWater Solutions and the Koha Dev Team
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
16
#
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>.
19
20
use Modern::Perl;
21
22
use parent qw(Plack::Middleware);
23
24
use C4::Context;
25
26
use Net::Netmask;
27
use Plack::Util::Accessor qw( trusted_proxy );
28
29
=head3 prepare_app
30
31
This method generates and stores the list of trusted ip's as Netmask objects
32
at the time Plack starts up, obviating the need to regerenate them on each request.
33
34
=cut
35
36
sub prepare_app {
37
    my $self = shift;
38
    $self->trusted_proxy( get_trusted_proxies() );
39
}
40
41
=head3 call
42
43
This method is called for each request, and will ensure the correct remote address
44
is set in the REMOTE_ADDR environment variable.
45
46
=cut
47
48
sub call {
49
    my $self = shift;
50
    my $env  = shift;
51
52
    if ( $env->{HTTP_X_FORWARDED_FOR} ) {
53
        my @trusted_proxy = @{ $self->trusted_proxy } if $self->trusted_proxy;
54
55
        if (@trusted_proxy) {
56
            my $addr = get_real_ip( $env->{REMOTE_ADDR}, $env->{HTTP_X_FORWARDED_FOR}, \@trusted_proxy );
57
            $ENV{REMOTE_ADDR} = $addr;
58
            $env->{REMOTE_ADDR} = $addr;
59
        }
60
    }
61
62
    return $self->app->($env);
63
}
64
65
=head3 get_real_ip
66
67
my $address = get_real_ip( $remote_addres, $x_forwarded_for_header );
68
69
This method takes the current remote address and the x-forwarded-for header string,
70
determines the correct external ip address, and returns it.
71
72
=cut
73
74
sub get_real_ip {
75
    my ( $remote_addr, $header ) = @_;
76
77
    my @forwarded_for = $header =~ /([^,\s]+)/g;
78
    return $remote_addr unless @forwarded_for;
79
80
    my $trusted_proxies = get_trusted_proxies();
81
82
    my @unconfirmed = ( @forwarded_for, $remote_addr );
83
84
    my $real_ip;
85
    while (my $addr = pop @unconfirmed) {
86
        my $has_matched = 0;
87
        foreach my $netmask (@$trusted_proxies) {
88
            $has_matched++, last if $netmask->match($addr);
89
        }
90
        $real_ip = $addr, last unless $has_matched;
91
    }
92
93
    return $real_ip;
94
}
95
96
=head3 get_trusted_proxies
97
98
This method returns an arrayref of Net::Netmask objects for all
99
the trusted proxies given to Koha.
100
101
=cut
102
103
sub get_trusted_proxies {
104
    my $proxies_conf = C4::Context->config('koha_trusted_proxies');
105
    return unless $proxies_conf;
106
    my @trusted_proxies_ip = split( / /, $proxies_conf );
107
    my @trusted_proxies = map { Net::Netmask->new($_) } @trusted_proxies_ip;
108
    return \@trusted_proxies;
109
}
110
111
112
=head1 AUTHORS
113
114
Kyle M Hall <kyle@bywatersolutions.com>
115
116
=cut
117
118
1;
(-)a/debian/templates/koha-conf-site.xml.in (+5 lines)
Lines 345-350 __END_SRU_PUBLICSERVER__ Link Here
345
 <plack_max_requests>50</plack_max_requests>
345
 <plack_max_requests>50</plack_max_requests>
346
 <plack_workers>2</plack_workers>
346
 <plack_workers>2</plack_workers>
347
347
348
 <!-- Configuration for X-Forwarded-For -->
349
 <!--
350
 <koha_trusted_proxies>1.2.3.4 2.3.4.5 3.4.5.6</koha_trusted_proxies>
351
 -->
352
348
 <!-- Elasticsearch Configuration -->
353
 <!-- Elasticsearch Configuration -->
349
 <elasticsearch>
354
 <elasticsearch>
350
     <server>localhost:9200</server> <!-- may be repeated to include all servers on your cluster -->
355
     <server>localhost:9200</server> <!-- may be repeated to include all servers on your cluster -->
(-)a/debian/templates/plack.psgi (+2 lines)
Lines 68-75 my $apiv1 = builder { Link Here
68
builder {
68
builder {
69
    enable "ReverseProxy";
69
    enable "ReverseProxy";
70
    enable "Plack::Middleware::Static";
70
    enable "Plack::Middleware::Static";
71
71
    # + is required so Plack doesn't try to prefix Plack::Middleware::
72
    # + is required so Plack doesn't try to prefix Plack::Middleware::
72
    enable "+Koha::Middleware::SetEnv";
73
    enable "+Koha::Middleware::SetEnv";
74
    enable "+Koha::Middleware::RealIP";
73
75
74
    mount '/opac'          => $opac;
76
    mount '/opac'          => $opac;
75
    mount '/intranet'      => $intranet;
77
    mount '/intranet'      => $intranet;
(-)a/etc/koha-conf.xml (-1 / +5 lines)
Lines 161-166 __PAZPAR2_TOGGLE_XML_POST__ Link Here
161
 <plack_max_requests>50</plack_max_requests>
161
 <plack_max_requests>50</plack_max_requests>
162
 <plack_workers>2</plack_workers>
162
 <plack_workers>2</plack_workers>
163
163
164
 <!-- Configuration for X-Forwarded-For -->
165
 <!--
166
 <koha_trusted_proxies>1.2.3.4 2.3.4.5 3.4.5.6</koha_trusted_proxies>
167
 -->
168
164
 <!-- Elasticsearch Configuration -->
169
 <!-- Elasticsearch Configuration -->
165
 <elasticsearch>
170
 <elasticsearch>
166
     <server>__ELASTICSEARCH_SERVERS__</server>
171
     <server>__ELASTICSEARCH_SERVERS__</server>
167
- 

Return to bug 23068