1package Perlbal::Plugin::XFFExtras; 2 3use strict; 4use warnings; 5 6use Danga::Socket 1.53; # Need newer Danga::Socket than perlbal to have local_port 7use Perlbal 1.74; # is_ssl support was added in 1.74 8use Perlbal::BackendHTTP (); 9use Perlbal::Service (); 10 11sub load { 12 Perlbal::Service::add_tunable( 13 send_backend_port => { 14 check_role => 'reverse_proxy', 15 des => "Send an X-Forwarded-Port header to backends to indicate the peer's remote address", 16 check_type => 'bool', 17 default => 0, 18 } 19 ); 20 Perlbal::Service::add_tunable( 21 send_backend_proto => { 22 check_role => 'reverse_proxy', 23 des => "Send an X-Forwarded-Proto header to backends to indicate the peers connecting protocol", 24 check_type => 'bool', 25 default => 0, 26 } 27 ); 28} 29 30# magical Perlbal hook return value constants 31use constant HANDLE_REQUEST => 0; 32use constant IGNORE_REQUEST => 1; 33 34sub register { 35 my ($class, $svc) = @_; 36 37 my $cfg = $svc->{extra_config} ||= {}; 38 39 $svc->register_hook(XFFExtras => backend_client_assigned => sub { 40 my Perlbal::BackendHTTP $be = shift; 41 my $hds = $be->{req_headers}; 42 my $client = $be->{client}; 43 my $client_ip = $client->peer_ip_string; 44 45 my $trusted = $svc->trusted_ip($client_ip); 46 my $blind = $svc->{blind_proxy}; 47 if (($trusted && !$blind) || !$trusted) { 48 if ($cfg->{send_backend_port}) { 49 # Danga::Socket has no accessor for the peer_port, so we break object 50 # boundaries for now to implement this. Force to integer because D::S 51 # also likes to store string error messages in this field too. 52 $client->local_ip_string; 53 my $local_port = $client->{local_port} + 0; 54 $hds->header("X-Forwarded-Port", $local_port); 55 } 56 if ($cfg->{send_backend_proto}) { 57 my $proto = $client->{is_ssl} ? 'https' : 'http'; 58 $hds->header("X-Forwarded-Proto", $proto); 59 } 60 } 61 62 return HANDLE_REQUEST; 63 }); 64} 65 661; 67 68__END__ 69 70=head1 NAME 71 72Perlbal::Plugin::XFFExtras - Perlbal plugin that can optionally add an 73X-Forwarded-Port and/or X-Forwarded-Proto header to reverse proxied requests. 74 75=head1 SYNOPSIS 76 77 # in perlbal.conf 78 79 LOAD XFFExtra 80 81 CREATE POOL web 82 POOL web ADD 10.0.0.1:80 83 84 CREATE SERVICE proxy 85 SET role = reverse_proxy 86 SET listen = 0.0.0.0:80 87 SET pool = web 88 89 SET plugins = XFFExtras 90 91 SET send_backend_port = yes 92 SET send_backend_proto = yes 93 ENABLE proxy 94 95=head1 DESCRIPTION 96 97This plugin adds optional headers to be sent to backend servers in reverse proxy mode. 98 99=head1 HEADERS 100 101=over 4 102 103=item * B<X-Forwarded-Port> 104 105This header will contain an integer value indicating the port that the peer connected to. 106This will correspond to the port number specified on the listen line of the perlbal service 107that initially handled the connection. 108 109=item * B<X-Forwarded-Proto> 110 111This header will contain a string indicating the protocol the client connected to perlbal 112via. Currently this will be either 'http' or 'https'. 113 114=back 115 116=head1 AUTHOR 117 118Jonathan Steinert, E<lt>hachi@kuiki.netE<gt> 119 120=head1 COPYRIGHT AND LICENSE 121 122Copyright (C) 2012 by Say Media Inc, E<lt>cpan@saymedia.comE<gt> 123 124This library is free software; you can redistribute it and/or modify it under 125the same terms as Perl itself, either Perl version 5.8.6 or, at your option, 126any later version of Perl 5 you may have available. 127 128=cut 129