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

(-)a/Koha/Middleware/RealIP.pm (-1 / +2 lines)
Lines 81-89 sub get_real_ip { Link Here
81
81
82
    my $trusted_proxies = get_trusted_proxies();
82
    my $trusted_proxies = get_trusted_proxies();
83
83
84
    #X-Forwarded-For: <client>, <proxy1>, <proxy2>
85
    my $real_ip = shift @forwarded_for;
84
    my @unconfirmed = ( @forwarded_for, $remote_addr );
86
    my @unconfirmed = ( @forwarded_for, $remote_addr );
85
87
86
    my $real_ip;
87
    while (my $addr = pop @unconfirmed) {
88
    while (my $addr = pop @unconfirmed) {
88
        my $has_matched = 0;
89
        my $has_matched = 0;
89
        foreach my $netmask (@$trusted_proxies) {
90
        foreach my $netmask (@$trusted_proxies) {
(-)a/t/Koha/Middleware/RealIP.t (-55 / +98 lines)
Lines 20-26 Link Here
20
20
21
use strict;
21
use strict;
22
use warnings;
22
use warnings;
23
use Test::More tests => 13;
23
use Test::More tests => 11;
24
use Test::Warn;
24
use Test::Warn;
25
25
26
use t::lib::Mocks;
26
use t::lib::Mocks;
Lines 28-89 use_ok("Koha::Middleware::RealIP"); Link Here
28
28
29
my ($remote_address,$x_forwarded_for_header,$address);
29
my ($remote_address,$x_forwarded_for_header,$address);
30
30
31
$remote_address = "1.1.1.1";
31
subtest "No X-Forwarded-For header" => sub {
32
$x_forwarded_for_header = "";
32
    plan tests => 1;
33
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
33
    $remote_address = "1.1.1.1";
34
is($address,'1.1.1.1',"There is no X-Forwarded-For header, so just use the remote address");
34
    $x_forwarded_for_header = "";
35
36
$remote_address = "1.1.1.1";
37
$x_forwarded_for_header = "2.2.2.2";
38
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
39
is($address,'1.1.1.1',"Don't trust 1.1.1.1 as a proxy, so use it as the remote address");
40
41
$remote_address = "1.1.1.1";
42
$x_forwarded_for_header = "2.2.2.2";
43
t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.1');
44
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
45
is($address,'2.2.2.2',"Trust proxy (1.1.1.1), so use the X-Forwarded-For header for the remote address");
46
47
48
$remote_address = "1.1.1.1";
49
$x_forwarded_for_header = "2.2.2.2,3.3.3.3";
50
t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.1 3.3.3.3');
51
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
52
is($address,'2.2.2.2',"Trust multiple proxies (1.1.1.1 and 3.3.3.3), so use the X-Forwaded-For <client> portion for the remote address");
53
54
$remote_address = "1.1.1.1";
55
$x_forwarded_for_header = "2.2.2.2,3.3.3.3";
56
t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad configuration');
57
warnings_are {
58
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
35
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
59
} ["could not parse bad","could not parse configuration"],"Warn on misconfigured koha_trusted_proxies";
36
    is($address,'1.1.1.1',"There is no X-Forwarded-For header, so just use the remote address");
60
is($address,'1.1.1.1',"koha_trusted_proxies is misconfigured so ignore the X-Forwarded-For header");
37
};
38
39
subtest "No configuration" => sub {
40
    plan tests => 1;
41
    $remote_address = "2.2.2.2";
42
    $x_forwarded_for_header = "1.1.1.1";
43
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
44
    is($address,'2.2.2.2',"No trusted proxies available, so don't trust 2.2.2.2 as a proxy, instead use it as the remote address");
45
};
46
47
subtest "Bad configuration" => sub {
48
    plan tests => 4;
49
    $remote_address = "1.1.1.1";
50
    $x_forwarded_for_header = "2.2.2.2,3.3.3.3";
51
    t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad configuration');
52
    warnings_are {
53
        $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
54
    } ["could not parse bad","could not parse configuration"],"Warn on misconfigured koha_trusted_proxies";
55
    is($address,'1.1.1.1',"koha_trusted_proxies is misconfigured so ignore the X-Forwarded-For header");
56
57
    $remote_address = "1.1.1.1";
58
    $x_forwarded_for_header = "2.2.2.2";
59
    t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad 1.1.1.1');
60
    warning_is {
61
        $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
62
    } "could not parse bad","Warn on partially misconfigured koha_trusted_proxies";
63
    is($address,'2.2.2.2',"koha_trusted_proxies contains an invalid value but still includes one correct value, which is relevant, so use X-Forwarded-For header");
64
};
65
66
subtest "Fail proxy isn't trusted" => sub {
67
    plan tests => 1;
68
    $remote_address = "2.2.2.2";
69
    $x_forwarded_for_header = "1.1.1.1";
70
    t::lib::Mocks::mock_config('koha_trusted_proxies', '3.3.3.3');
71
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
72
    is($address,'2.2.2.2',"The 2.2.2.2 proxy isn't in our trusted list, so use it as the remote address");
73
};
74
75
subtest "The most recent proxy is trusted but the proxy before it is not trusted" => sub {
76
    plan tests => 1;
77
    $remote_address = "3.3.3.3";
78
    $x_forwarded_for_header = "1.1.1.1, 2.2.2.2";
79
    t::lib::Mocks::mock_config('koha_trusted_proxies', '3.3.3.3');
80
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
81
    is($address,'2.2.2.2',"We trust 3.3.3.3, but we don't trust 2.2.2.2, so use 2.2.2.2 as the remote address");
82
};
83
84
subtest "Success one proxy" => sub {
85
    plan tests => 1;
86
    $remote_address = "2.2.2.2";
87
    $x_forwarded_for_header = "1.1.1.1";
88
    t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.2');
89
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
90
    is($address,'1.1.1.1',"Trust proxy (2.2.2.2), so use the client IP from the X-Forwarded-For header for the remote address");
91
};
92
93
subtest "Success multiple proxies" => sub {
94
    plan tests => 1;
95
    $remote_address = "2.2.2.2";
96
    $x_forwarded_for_header = "1.1.1.1,3.3.3.3";
97
    t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.2 3.3.3.3');
98
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
99
    is($address,'1.1.1.1',"Trust multiple proxies (2.2.2.2 and 3.3.3.3), so use the X-Forwaded-For <client> portion for the remote address");
100
};
101
102
subtest "Test alternative configuration styles" => sub {
103
    plan tests => 3;
104
    $remote_address = "2.2.2.2";
105
    $x_forwarded_for_header = "1.1.1.1";
106
    t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.0/24');
107
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
108
    is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using CIDR notation, so use the X-Forwarded-For header for the remote address");
61
109
62
$remote_address = "1.1.1.1";
110
    $remote_address = "2.2.2.2";
63
$x_forwarded_for_header = "2.2.2.2";
111
    $x_forwarded_for_header = "1.1.1.1";
64
t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad 1.1.1.1');
112
    t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2');
65
warning_is {
66
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
113
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
67
} "could not parse bad","Warn on partially misconfigured koha_trusted_proxies";
114
    is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using abbreviated notation, so use the X-Forwarded-For header for the remote address");
68
is($address,'2.2.2.2',"koha_trusted_proxies contains an invalid value but still includes one correct value, which is relevant, so use X-Forwarded-For header");
115
69
116
    $remote_address = "2.2.2.2";
70
$remote_address = "1.1.1.1";
117
    $x_forwarded_for_header = "1.1.1.1";
71
$x_forwarded_for_header = "2.2.2.2";
118
    t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.0:255.255.255.0');
72
t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.0/24');
119
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
73
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
120
    is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using an IP address and netmask separated by a colon, so use the X-Forwarded-For header for the remote address");
74
is($address,'2.2.2.2',"Trust proxy (1.1.1.1) using CIDR notation, so use the X-Forwarded-For header for the remote address");
121
};
75
122
76
$remote_address = "1.1.1.1";
123
subtest "Client IP is properly processed even if it is in koha_trusted_proxies" => sub {
77
$x_forwarded_for_header = "2.2.2.2";
124
    $remote_address = "1.1.1.2";
78
t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1');
125
    $x_forwarded_for_header = "1.1.1.1";
79
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
126
    t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.0/24');
80
is($address,'2.2.2.2',"Trust proxy (1.1.1.1) using abbreviated notation, so use the X-Forwarded-For header for the remote address");
127
    $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
81
128
    is($address,'1.1.1.1',"The X-Forwarded-For value matches the koha_trusted_proxies, but there is no proxy specified");
82
$remote_address = "1.1.1.1";
129
    done_testing(1);
83
$x_forwarded_for_header = "2.2.2.2";
130
};
84
t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.0:255.255.255.0');
85
$address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
86
is($address,'2.2.2.2',"Trust proxy (1.1.1.1) using an IP address and netmask separated by a colon, so use the X-Forwarded-For header for the remote address");
87
131
88
subtest "IPv6 support" => sub {
132
subtest "IPv6 support" => sub {
89
    my ($remote_address,$x_forwarded_for_header,$address);
133
    my ($remote_address,$x_forwarded_for_header,$address);
90
- 

Return to bug 25950