Skip to content

Commit

Permalink
Item14380: More proxy detection work
Browse files Browse the repository at this point in the history
Add checkers for the proxy settings.

Don't print detection messages unless really in bootstrap mode.
  • Loading branch information
gac410 committed Nov 30, 2017
1 parent 3745b32 commit 63db4fa
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 67 deletions.
11 changes: 3 additions & 8 deletions ModPerlEngineContrib/lib/Foswiki/Engine/Apache.pm
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ sub prepareConnection {
: $this->{r}->connection->client_ip
);

if ( $Foswiki::cfg{PROXY}{UseForwardedForHeader}
# SMELL: Mod_perl should do this automatically ... see
# http://search.cpan.org/dist/Apache2-xForwardedFor/lib/Apache2/xForwardedFor.pm
if ( $Foswiki::cfg{PROXY}{UseForwardedFor}
&& defined $ENV{HTTP_X_FORWARDED_FOR} )
{
my @addrs = split /,\s?/, $ENV{HTTP_X_FORWARDED_FOR};
Expand Down Expand Up @@ -134,13 +136,6 @@ sub prepareHeaders {
$req->header( $header => $value );
}
$req->remoteUser( $this->{r}->user );
if ( $Foswiki::cfg{BehindProxy} ) {
if ( my $source = $req->header('X-Forwarded-For') ) {
my $ip = ( split /[, ]+/, $source )[-1];
$req->remoteAddress($1)
if defined $ip and $ip =~ /^((?:\d{1,3}\.){3}\d{1,3})$/;
}
}
}

sub preparePath {
Expand Down
38 changes: 29 additions & 9 deletions core/lib/Foswiki.spec
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
# be browseable from the web - if you expose any other directories (such as
# lib or templates) you are opening up routes for possible hacking attempts.

# **URL LABEL="Default Url Host" CHECK="noemptyok \
# **URL LABEL="Default Url Host" CHECK_ON_CHANGE="{PermittedRedirectHostUrls}" \
# CHECK="also:{PermittedRedirectHostUrls} \
# noemptyok \
# parts:scheme,authority \
# partsreq:scheme,authority \
# schemes:http,https \
Expand All @@ -65,7 +67,10 @@
# to return the {DefaultUrlHost}.
$Foswiki::cfg{ForceDefaultUrlHost} = $FALSE;

# **URILIST LABEL="Permitted Redirect Host Urls" EXPERT CHECK='emptyok \
# **URILIST LABEL="Permitted Redirect Host Urls" EXPERT \
# CHECK_ON_CHANGE="{DefaultUrlHost}" \
# CHECK='also:{DefaultUrlHost} \
# emptyok \
# parts:scheme,authority \
# authtype:hostip' **
# If your host has aliases (such as both =www.mywiki.net= and =mywiki.net=
Expand Down Expand Up @@ -1075,23 +1080,38 @@ $Foswiki::cfg{AccessibleHeaders} = ['Accept-Language', 'User-Agent'];
# http://username:password@proxy.your.company:8080.
$Foswiki::cfg{PROXY}{HOST} = undef;

# **BOOLEAN LABEL="Forwarded Headers" **
# Use the =Forwarded-*= headers to determine the Client IP, URL Protocol, Hostname and Port.
# **BOOLEAN LABEL="Forwarded For" **
# Use the =Forwarded-For*= header to determine the Client IP.
# Foswiki normally uses the local server information for identifying the connection information.
# However when a proxy server, load balancer, SSL Accelerator or other intermediate
# devices are present, this local information will most likely be incorrect.
# devices are present, this connection information will most likely be incorrect.
# Enable this setting to make use of the Proxy headers provided by the Client or intermediate devices:
# * =X-Forwarded-For= _Identifies the client IP, overrides REMOTE_ADDRESS variable._
# * =Forwarded For=...= _Identifies the client IP, overrides REMOTE_ADDRESS variable._
# <p/>
# *Caution:* These headers are easily spoofed. Only enable this flag if you are certain that
# a proxy server exists and that you trust the Proxy server.
# *The proxy server should strip any spoofed =x-Forwarded-*= headers sent by the client.*
# <p/>
# Note that this setting also impacts Logging, and CGI Session IP matching. Changing this setting
# will break all active sessions behind the proxy and require re-authentication.
$Foswiki::cfg{PROXY}{UseForwardedFor} = $FALSE;

# **BOOLEAN LABEL="Forwarded Headers" **
# Use the =Forwarded-*= headers to determine the URL Protocol, Hostname and Port.
# Foswiki normally uses the local server information for identifying the connection information.
# A reverse proxy will hide the URL used by the client.
# <p/>
# Enable this setting to make use of the Proxy headers provided by the Client or intermediate devices:
# * =X-Forwarded-Host= _Captures the hostname used by the client in it's initial request._
# * =X-Forwarded-Proto= _Specifies if the client used an HTTP or HTTPS secure connection._
# * =X-Forwarded-Port= _Specifies the original port used by the client._
# * =Forwarded:= _New standards based header replaces the X-Forwarded* headers._
# <p/>
# *Caution:* These headers are easily spoofed. Only enable this flag if you are certain that
# a proxy server exists and that you trust the Proxy server.
# <p/>
# Note that this setting also impacts CGI Session IP matching. Changing this setting
# will break all active sessions behind the proxy and require re-authentication.
# a proxy server exists and that you trust the Proxy server. If all users are behind the same
# proxy server, the preferred configuration is to enable {ForceDefaultURLHost} instead of using these
# headers for dynamic resolution.
$Foswiki::cfg{PROXY}{UseForwardedHeaders} = $FALSE;

#---++ Anti-spam
Expand Down
3 changes: 2 additions & 1 deletion core/lib/Foswiki/Configure/Bootstrap.pm
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,9 @@ sub bootstrapWebSettings {

$Foswiki::cfg{ForceDefaultUrlHost} = 0;

# Probe the connection data in bootstrap mode
my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);
Foswiki::Engine::_getConnectionData('b');

print STDERR
"AUTOCONFIG: Engine detected: client ($client) proto ($protocol) host ($host) port ($port) proxy ($proxy) )\n"
Expand Down
38 changes: 12 additions & 26 deletions core/lib/Foswiki/Configure/Checkers/DefaultUrlHost.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,21 @@ sub check_current_value {
);
}

my $host = $ENV{HTTP_HOST};
my $protocol = $ENV{HTTPS} ? 'https' : 'http';
# Probe the connection in bootstrap mode:
my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);
$port = ( $port && $port != 80 && $port != 443 ) ? ":$port" : '';

if ( $ENV{HTTP_X_FORWARDED_HOST} ) {
my $detected = $protocol . '://' . $host . $port;

# Probably behind a proxy, override the host
$host = $ENV{HTTP_X_FORWARDED_HOST};

if (
(
$ENV{HTTP_REFERER}
&& $ENV{HTTP_REFERER} =~
m#^https://\Q$ENV{HTTP_X_FORWARDED_HOST}\E#i
)
)
{
# Browser is asking for https, so override protcol
$protocol = 'https';
}
}

if ( $host && $Foswiki::cfg{DefaultUrlHost} !~ m#$protocol://$host#i ) {
if ( $Foswiki::cfg{DefaultUrlHost} !~ m#\Q$detected\E#i
&& $Foswiki::cfg{PermittedRedirectHostUrls} !~ m#\Q$detected\E#i )
{
$reporter->WARN(
"Current setting does not match URL =$protocol://$host=");
"Current setting does not match URL =$protocol://$host$port=, and it is not listed in ={PermittedRedirectHostUrls}="
);
$reporter->NOTE(
'If the URL hostname is correct, set this to =http://'
. $host
. '= or if using SSL, =https://'
. $host . '= '
"If the URL hostname is correct, set this to =$protocol//$host$port= "
. 'If this setting and the URL are both correct, you could also add the URL to the \'expert setting\' =PermittedRedirectHostUrls=.'
);
}
Expand All @@ -60,7 +46,7 @@ sub check_current_value {
__END__
Foswiki - The Free and Open Source Wiki, http://foswiki.org/
Copyright (C) 2008-2016 Foswiki Contributors. Foswiki Contributors
Copyright (C) 2008-2017 Foswiki Contributors. Foswiki Contributors
are listed in the AUTHORS file in the root of this distribution.
NOTE: Please extend that file, not this notice.
Expand Down
21 changes: 17 additions & 4 deletions core/lib/Foswiki/Configure/Checkers/ForceDefaultUrlHost.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,28 @@ use strict;
use warnings;

use Foswiki::Configure::Checkers::URL ();
our @ISA = ('Foswiki::Configure::Checkers::URL');
our @ISA = ('Foswiki::Configure::Checker');

sub check_current_value {
my ( $this, $reporter ) = @_;

if ( $ENV{HTTP_X_FORWARDED_HOST} ) {
unless ( $Foswiki::cfg{ForceDefaultUrlHost} ) {
# Probe the connection in bootstrap mode:
my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);

if ($proxy) {
if ( !$Foswiki::cfg{PROXY}{UseForwardedHeaders}
&& !$Foswiki::cfg{ForceDefaultUrlHost} )
{
$reporter->WARN(
'It appears you may be running from behind a proxy. =ForceDefaultUrlHost= is the recommended setting.'
);
}
elsif ($Foswiki::cfg{PROXY}{UseForwardedHeaders}
&& $Foswiki::cfg{ForceDefaultUrlHost} )
{
$reporter->WARN(
'It appears you may be running from behind a proxy. =ForceDefaultUrlHost= should be enabled.'
'Both ={PROXY}{UseForwardedHeaders}= and ={ForceDefaultUrlHost}= are enabled. ={ForceDefaultUrlHost}= will override any Forwarded headers'
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# See bottom of file for license and copyright information
package Foswiki::Configure::Checkers::PROXY::UseForwardedForHeader;
package Foswiki::Configure::Checkers::PROXY::UseForwardedFor;

use strict;
use warnings;
Expand All @@ -10,21 +10,30 @@ our @ISA = ('Foswiki::Configure::Checker');
sub check_current_value {
my ( $this, $reporter ) = @_;

if ( $ENV{HTTP_X_FORWARDED_FOR} ) {
my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);

if ( $Foswiki::cfg{PROXY}{UseForwardedForHeader} ) {
$reporter->NOTE("Real client IP is =$ENV{HTTP_X_FORWARDED_FOR}=.");
if ($proxy) {

if ( $Foswiki::cfg{PROXY}{UseForwardedFor} ) {
$reporter->WARN(
"Be sure you trust the proxy server. Clients can use this header to spoof their IP addresses."
);
}
else {
$reporter->WARN(
"Proxy detected, Enable this switch if Foswiki should use the =HTTP_X_FORWARDED_FOR= header to obtain the real client IP address."
);
$reporter->NOTE(
"Remote Address is $ENV{REMOTE_ADDR}, Real client IP is =$ENV{HTTP_X_FORWARDED_FOR}=."
"Proxy detected, Enable this switch if Foswiki should use the =X-Forwarded-For= header to obtain the real client IP address."
);
}
$reporter->NOTE(
"Remote Address is $ENV{REMOTE_ADDR}, Real client IP is =$client=."
);
}
elsif ( $Foswiki::cfg{PROXY}{UseForwardedFor} ) {
$reporter->WARN(
"You have enabled ={PROXY}{UseForwardedFor}= but a proxy was not detected. The =X-Forwarded-For= header can be used by clients to mask their real IP address. Be sure this is what you want to do."
);
}

}

1;
Expand Down
75 changes: 75 additions & 0 deletions core/lib/Foswiki/Configure/Checkers/PROXY/UseForwardedHeaders.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# See bottom of file for license and copyright information
package Foswiki::Configure::Checkers::PROXY::UseForwardedHeaders;

use strict;
use warnings;

use Foswiki::Configure::Checker ();
our @ISA = ('Foswiki::Configure::Checker');

sub check_current_value {
my ( $this, $reporter ) = @_;

my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);

if ($proxy) {

$reporter->NOTE(
"Proxy server detected. Proxy URL is $protocol://$host:$port. Local server name is $ENV{HTTP_HOST}"
);

if ( $Foswiki::cfg{PROXY}{UseForwardedHeaders} ) {
$reporter->WARN(
"Note that =ForceDefaultUrlHost= is a more secure setting for supporting a reverse proxy. "
);
}
else {
$reporter->NOTE(
'This setting should be enabled if there are multiple proxy servers or there is a mix of proxied and non-proxied clients.'
);
}
}
else {
if ( $Foswiki::cfg{PROXY}{UseForwardedHeaders} ) {
$reporter->WARN(
'You have enabled this setting, but no proxy is detected. Be sure this is what you want to do.'
);
}
}

if ( $Foswiki::cfg{ForceDefaultUrlHost}
&& $Foswiki::cfg{PROXY}{UseForwardedHeaders} )
{
$reporter->ERROR(
'Both ={ForceDefaultUrlHost}= and ={PROXY}{UseForwardedHeaders}= are enabled. ={PROXY}{UseForwardedHeaders}= will be ignored.'
);
}
}

1;
__END__
Foswiki - The Free and Open Source Wiki, http://foswiki.org/
Copyright (C) 2008-2017 Foswiki Contributors. Foswiki Contributors
are listed in the AUTHORS file in the root of this distribution.
NOTE: Please extend that file, not this notice.
Additional copyrights apply to some or all of the code in this
file as follows:
Copyright (C) 2000-2006 TWiki Contributors. All Rights Reserved.
TWiki Contributors are listed in the AUTHORS file in the root
of this distribution. NOTE: Please extend that file, not this notice.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. For
more details read LICENSE in the root of this distribution.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
As per the GPL, removal of this notice is prohibited.
60 changes: 60 additions & 0 deletions core/lib/Foswiki/Configure/Checkers/PermittedRedirectHostUrls.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# See bottom of file for license and copyright information
package Foswiki::Configure::Checkers::PermittedRedirectHostUrls;

use strict;
use warnings;

use Foswiki::Configure::Checkers::URL ();
our @ISA = ('Foswiki::Configure::Checkers::URL');

sub check_current_value {
my ( $this, $reporter ) = @_;

foreach my $uri ( split /[,\s]/, $Foswiki::cfg{PermittedRedirectHostUrls} )
{
next unless $uri;
Foswiki::Configure::Checkers::URL::checkURI( $reporter, $uri );
}

# Probe the connection in bootstrap mode:
my ( $client, $protocol, $host, $port, $proxy ) =
Foswiki::Engine::_getConnectionData(1);
$port = ( $port && $port != 80 && $port != 443 ) ? ":$port" : '';

my $detected = $protocol . '://' . $host . $port;

if ( $Foswiki::cfg{DefaultUrlHost} !~ m#\Q$detected\E#i
&& $Foswiki::cfg{PermittedRedirectHostUrls} !~ m#\Q$detected\E#i )
{
$reporter->WARN(
"Current setting does not include =$protocol://$host$port=, and it is not the ={DefaultUrlHost}="
);
}
}

1;
__END__
Foswiki - The Free and Open Source Wiki, http://foswiki.org/
Copyright (C) 2008-2017 Foswiki Contributors. Foswiki Contributors
are listed in the AUTHORS file in the root of this distribution.
NOTE: Please extend that file, not this notice.
Additional copyrights apply to some or all of the code in this
file as follows:
Copyright (C) 2000-2006 TWiki Contributors. All Rights Reserved.
TWiki Contributors are listed in the AUTHORS file in the root
of this distribution.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. For
more details read LICENSE in the root of this distribution.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
As per the GPL, removal of this notice is prohibited.
Loading

0 comments on commit 63db4fa

Please sign in to comment.