Skip Menu |

This queue is for tickets about the libnet CPAN distribution.

Report information
The Basics
Id: 77052
Status: open
Priority: 0/
Queue: libnet

People
Owner: Nobody in particular
Requestors: chris_carr [...] bitcard.ccarr.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Compensate for bad PASV response
Some mis-configured FTP servers, not realizing that they are behind a firewall, will send a non-routable address in response to the PASV command. E.g.: Net::FTP=GLOB(0x21582d8)>>> PASV Net::FTP=GLOB(0x21582d8)<<< 227 Entering Passive Mode (10,0,0,253,126,206) I request that Net::FTP be extended so as to compensate for such incorrect responses. I have altered the _dataconn method of my local copy of Net/FTP.pm as follows: + my $peerAddr = join(".", @port[0 .. 3]); + if ( + $port[0] == 10 or # Class A unroutable + ($port[0] == 172 and $port[1] > 15 and $port[1] < 32) or # Class B unroutable + ($port[0] == 192 and $port[1] == 168) ) { # Class C unroutable + carp "Server sent us an unroutable address, $peerAddr, in the pasv response. Use the server address instead.\n"; + $peerAddr = ${*$ftp}{'net_ftp_host'}; + } $data = $pkg->new( + PeerAddr => $peerAddr, - PeerAddr => join(".", @port[0 .. 3]), PeerPort => $port[4] * 256 + $port[5], LocalAddr => ${*$ftp}{'net_ftp_localaddr'}, Proto => 'tcp' ); I offer it to the community under the same license as libnet. Note that it assumes that any private address is unroutable, which is true in my case. To be generally useful, it should probably be controlled by a parameter in the constructor.
Subject: Re: [rt.cpan.org #77052] Compensate for bad PASV response
Date: Mon, 7 May 2012 17:25:24 -0500
To: bug-libnet [...] rt.cpan.org
From: Graham Barr <gbarr [...] pobox.com>
Your suggested patch would break the use of Net::FTP for connecting to ftp servers that are on a local private network. If the remote server is broken, or the firewall it is behind is not configured to rewrite this, then there is not much Net::FTP can do. The remote server or the firewall needs to be fixed Graham.
From: chris_carr [...] bitcard.ccarr.com
On Mon May 07 18:25:53 2012, gbarr@pobox.com wrote: Show quoted text
> Your suggested patch would break the use of Net::FTP for connecting to > ftp servers that are on a local private network. > > If the remote server is broken, or the firewall it is behind is not > configured to rewrite this, then there is not much Net::FTP can do. > The remote server or the firewall needs to be fixed > > Graham. >
I agree. This is why I suggested adding a parameter to the constructor. Chris
Subject: [rt.cpan.org #77052]
Date: Tue, 19 Nov 2013 10:40:01 +0100
To: bug-libnet [...] rt.cpan.org
From: Juan Antonio Castillo Dayer <juan.castillo [...] meteologica.com>
Hi all, I've used a similar solution to NcFTP Client program, in the same place that the first message. So the solution would be good for local private network too. ============================================= if (defined ${*$ftp}{'net_ftp_pasv'}) { my @port = map { 0 + $_ } split(/,/, ${*$ftp}{'net_ftp_pasv'}); + my $peerAddr = join(".", @port[0 .. 3]); + + # To solve the control address to a control IP, for if it were a name. + my $controlAddr = inet_ntoa(inet_aton(${*$ftp}{'net_ftp_host'})); + # To Check the control address has been resolved and it has an IP format. + if(defined $controlAddr and $controlAddr =~ m/^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}$/){ + # If the obtained from the PASV IP is different from the control IP, I check if it belongs to a private IP range. + if($peerAddr ne $controlAddr){ + # Private IPs ranges. + my @privateNetworks = qw(192.168. 10. 172.16. 172.17. 172.18. 172.19. 172.20. 172.21. 172.22. 172.23. 172.24. 172.25. 172.26. 172.27. 172.28. 172.29. 172.30. 172.31. undef); + my $i; + for($i=0; defined $privateNetworks[$i]; $i++){ + # If the PASV IP matches with some pattern. + if(substr($peerAddr, 0, length $privateNetworks[$i]) eq $privateNetworks[$i]){ + last; + } + } + + if(defined $privateNetworks[$i] and substr($controlAddr, 0, length $privateNetworks[$i]) ne $privateNetworks[$i]){ + # If the obtained by PASV IP is private, but the control IP isn't private, I changed it. + carp "Server sent us an unroutable address, $peerAddr, in the PASV response. Use the server address instead ($controlAddr)"; + $peerAddr = ${*$ftp}{'net_ftp_host'}; + } + } + } + $data = $pkg->new( - PeerAddr => join(".", @port[0 .. 3]), + PeerAddr => $peerAddr, PeerPort => $port[4] * 256 + $port[5], LocalAddr => ${*$ftp}{'net_ftp_localaddr'}, Proto => 'tcp' ); } ============================================= I believe that together we can improve this patch. Regards, Juan
Would it not be prudent, to avoid a lot of checking back and forth whether it is a private address or not, to just check the IP returned from the initial connection (an IP presumably exists as a result of logging into a server) against the IP returned from PASV? If they are different, assume a bad IP address from PASV and try the original connection IP. Or am I missing something?