Skip to content

Commit

Permalink
Support X-Forwarded-For under Plack (closes #8)
Browse files Browse the repository at this point in the history
  • Loading branch information
abh committed May 13, 2011
1 parent 2837866 commit 01bf6fa
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 48 deletions.
10 changes: 10 additions & 0 deletions PLACK.md
@@ -0,0 +1,10 @@
# Upgrade notes from Apache to Plack version

* proxyip_forwarders are not "chained"; only the most recent header is
read. Plack::Middleware::ReverseProxy would have to be changed to fix
that.

* When using proxyip_forwarders, X-Forwarded-Server, X-Forwarded-Host,
X-Forwarded-Port, X-Forwarded-HTTPS and X-Forwarded-Proto headers are
also supported.

47 changes: 0 additions & 47 deletions apache/conf/startup.pl
Expand Up @@ -15,53 +15,6 @@ BEGIN

use Combust::Constant qw(OK);

my $config = new Combust::Config;

my $trust_all = 0;
my $net_netmask_loaded;
my @forwarders;

for my $ip ($config->proxyip_forwarders) {

$ip eq '*' and $trust_all = 1 and next;

unless ($ip =~ m!/!) {
push @forwarders, $ip;
next;
}

unless ($net_netmask_loaded or ($net_netmask_loaded = eval { require Net::Netmask; 1; })) {
warn "Net::Netmask not installed, could not use $ip as a proxyip_forwarder";
next;
}

$ip = Net::Netmask->new2($ip);
warn "Error defining trusted upstream proxy: " . Net::Netmask::errstr() unless $ip;
push @forwarders, $ip if $ip;

}

sub ProxyIP::handler {
my $r = shift;

return OK unless $trust_all or trusted_ip($r->connection->remote_ip);

my @ip = split(/,\s*/, ($r->headers_in->{'X-Forwarded-For'} || ''));
while (my $ip = pop(@ip)) {
$r->connection->remote_ip($ip);
last unless trusted_ip($ip);
}
return OK;
}

sub trusted_ip {
my $ip = shift;
for my $fw (@forwarders) {
return 1 if (ref $fw ? $fw->match($ip) : ($ip eq $fw));
}
return 0;
}

if ($ENV{CBROOTLOCAL}) {
my $file = "$ENV{CBROOTLOCAL}/apache/conf/startup.pl";
require $file if -e $file;
Expand Down
54 changes: 53 additions & 1 deletion lib/Combust/App.pm
Expand Up @@ -7,6 +7,8 @@ use Combust::Config;
use Combust::Site;
use Combust::Request::Plack;

my $config = Combust::Config->new;

use namespace::clean -except => 'meta';

has sites => (
Expand Down Expand Up @@ -102,7 +104,6 @@ sub reference {
$self->init;
my $app = sub { $self->exec(@_) };

my $config = Combust::Config->new;
my $log_path = $config->log_path;

my $logfh;
Expand Down Expand Up @@ -141,10 +142,61 @@ sub reference {
$logfh->autoflush(1);
STDERR->autoflush(1);

my $trust_all = _get_forwarders();

builder {
# TODO: match combust setting
enable_if {
my $remote_ip = $_[0]->{REMOTE_ADDR};
$trust_all or _trusted_ip($remote_ip)
} "Plack::Middleware::ReverseProxy";
enable "AccessLog", logger => sub { print $logfh @_ };
return $app;
}
}

my $_forwarders = [];

sub _trusted_ip {
my $ip = shift;
for my $fw (@$_forwarders) {
return 1 if (ref $fw ? $fw->match($ip) : ($ip eq $fw));
}
return 0;
}


sub _get_forwarders {

my $trust_all = 0;
my $net_netmask_loaded;
my @forwarders;

for my $ip ($config->proxyip_forwarders) {

if ($ip eq '*') {
return (1, []);
}

unless ($ip =~ m!/!) {
push @forwarders, $ip;
next;
}

unless ($net_netmask_loaded or ($net_netmask_loaded = eval { require Net::Netmask; 1; })) {
warn "Net::Netmask not installed, could not use $ip as a proxyip_forwarder";
next;
}

$ip = Net::Netmask->new2($ip);
warn "Error defining trusted upstream proxy: " . Net::Netmask::errstr() unless $ip;
push @forwarders, $ip if $ip;

}

$_forwarders = \@forwarders;

return 0;
}

1;

0 comments on commit 01bf6fa

Please sign in to comment.