Bug 39789: Add ability to specify an alternative header to X-Forwarded-For for finding the real ip address

Some services ( such as CloudFlare ) use alternative heads to X-Forwarded-For. Koha should be able to use a custom header instead of X-Forwarded-For if needed.

This patch updates the feature to allow both the custom header and X-Forwarded-For to work harmoniously

For example, CloudFlare has it's own custom header.
This patch allows a site to be configured for Cloudflare's proxy before the proxy is enabled.

Test Plan:
1) prove t/Koha/Middleware/RealIP.t

Signed-off-by: Lin Wei Li <lin-wei.li@inLibro.com>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Kyle M Hall 2025-04-30 11:16:09 -04:00 committed by Lucas Gass
parent 0a8182ba02
commit 13a4b44bc9
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
3 changed files with 20 additions and 8 deletions

View File

@ -915,7 +915,12 @@ variable to be set correctly.
sub set_remote_address {
if ( C4::Context->config('koha_trusted_proxies') ) {
require CGI;
my $header = CGI->http('HTTP_X_FORWARDED_FOR');
# 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
my $reverse_proxy_ip_header = C4::Context->config('reverse_proxy_ip_header') || 'HTTP_X_FORWARDED_FOR';
# Check the cgi for the custom header, if the custom header is not set, fall back to HTTP_X_FORWARDED_FOR
my $header = CGI->http($reverse_proxy_ip_header) || CGI->http('HTTP_X_FORWARDED_FOR');
if ($header) {
require Koha::Middleware::RealIP;

View File

@ -51,14 +51,15 @@ sub call {
my $self = shift;
my $env = shift;
if ( $env->{HTTP_X_FORWARDED_FOR} ) {
my @trusted_proxy = $self->trusted_proxy ? @{ $self->trusted_proxy } : undef;
# 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
my $reverse_proxy_ip_header = C4::Context->config('reverse_proxy_ip_header') || 'HTTP_X_FORWARDED_FOR';
if (@trusted_proxy) {
my $addr = get_real_ip( $env->{REMOTE_ADDR}, $env->{HTTP_X_FORWARDED_FOR}, \@trusted_proxy );
$ENV{REMOTE_ADDR} = $addr;
$env->{REMOTE_ADDR} = $addr;
}
# Check the env for the custom header, if the custom header is not set, fall back to HTTP_X_FORWARDED_FOR
my $header = $env->{$reverse_proxy_ip_header} || $env->{'HTTP_X_FORWARDED_FOR'};
if ($header) {
my $addr = get_real_ip( $env->{REMOTE_ADDR}, $header );
$ENV{REMOTE_ADDR} = $addr;
$env->{REMOTE_ADDR} = $addr;
}
return $self->app->($env);
@ -76,6 +77,9 @@ determines the correct external ip address, and returns it.
sub get_real_ip {
my ( $remote_addr, $header ) = @_;
my $enable_trusted_proxy_for_headers = C4::Context->config('enable_trusted_proxy_for_headers') // 1;
return $remote_addr unless $enable_trusted_proxy_for_headers;
my @forwarded_for = $header =~ /([^,\s]+)/g;
return $remote_addr unless @forwarded_for;

View File

@ -346,8 +346,11 @@ __END_SRU_PUBLICSERVER__
<plack_workers>2</plack_workers>
<!-- Configuration for X-Forwarded-For -->
<!-- Set enable_trusted_proxy_for_headers to 0 to never trust proxy headers, always use given REMOTE_ADDRESS -->
<!--
<koha_trusted_proxies>1.2.3.4 2.3.4.5 3.4.5.6</koha_trusted_proxies>
<reverse_proxy_ip_header>HTTP_X_FORWARDED_FOR</reverse_proxy_ip_header>
<enable_trusted_proxy_for_headers>1</enable_trusted_proxy_for_headers>
-->
<!-- Elasticsearch Configuration -->