albus123 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have evaluated Net:SFTP and it fits my requirements - but the only issue is it does not support IPv6 (I have tried Net-SFTP-0.10 with Net-SSH-Perl-1.38). From my understanding, Net-SFTP-Foreign supports IPv6 but I do not want additional process being launched everytime (I would need to do a task repetitively) and would prefer to do it in perl - this would also eliminate Net::SFTP::Expect. If someone knows of a way to enhance Net::SFTP/SSH to support IPv6 (using a 'Glue'), please let me know. Or if there are pure perl-based implementations that support IPv6, that would also be great. Or if there is a way of making Net::SFTP use Net::OpenSSH (this supports IPv6), that would also work.

I have already gone through the following related links and I don't have an answer yet.

IPv6 Supported Perl Modules State of IPv6 package that can handle ftp, sftp, http etc ?

Thanks
  • Comment on Enhancing Net::SFTP (& Net::SSH) to support IPv6

Replies are listed 'Best First'.
Re: Enhancing Net::SFTP (& Net::SSH) to support IPv6
by salva (Canon) on Jul 23, 2015 at 07:04 UTC
    Use Net::SFTP::Foreign.

    When a SSH connection is started, the heavy part is the protocol handshake. Creating a process is in comparison, very cheap and anyway, one (or even several) processes are going to be created on the remote side.

    So, If that is not fast enough for you, the only solution will be to keep open the SSH or SFTP connections and reuse them.

    Net::SFTP::Foreign can run also on top of Net::OpenSSH (which uses external processes) and Net::SSH2 (which doesn't).

      Thank you. I would go with Net::SFTP::Foreign.
Re: Enhancing Net::SFTP (& Net::SSH) to support IPv6
by VinsWorldcom (Prior) on Jul 23, 2015 at 11:23 UTC

    I'm not familiar with Net::SFTP, but a quick read seems that it doesn't support passing a socket object, which is how modules like Net::Telnet (which as of 3.04, supports IPv6) and Net::SSH2 allowed for IPv6 support. I use Net::SSH2 because it's the only SSH module I was able to get to work on Windows - comes bundled with Strawberry Perl in vendor/lib.

    It goes something like this (following code passes 'perl -c'):

    #!perl use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); use Socket qw(inet_ntoa AF_INET IPPROTO_TCP); use Net::SSH2; # Conditional use of IO::Socket::IP, older than 5.16 doesn't have by d +efault my $HAVE_IO_Socket_IP = 0; eval "use IO::Socket::IP -register"; if(!$@) { $HAVE_IO_Socket_IP = 1 } else { eval "use IO::Socket::INET" } # Backward compatible, older versions of Socket don't have AF_INET6 my $AF_INET6 = eval { Socket::AF_INET6() }; # Get command line options for IPv4 or IPv6 and host my %opt; GetOptions( '4!' => sub { $opt{family} = AF_INET}, '6!' => sub { $opt{family} = $AF_INET6}, 'host' => $opt{host}, ); # If IPv6 and we don't have IO::Socket::IP, fail if (!$HAVE_IO_Socket_IP && defined $opt{family} && ($opt{family} == $A +F_INET6)) { print "$0: IO::Socket::IP required for IPv6\n"; exit 1 } # Default to IPv4 for backward compatiblity - THIS MAY CHANGE IN THE F +UTURE!!! if (!defined $opt{family}) { $opt{family} = AF_INET } # Open socket my $socket; if ($HAVE_IO_Socket_IP) { $socket = IO::Socket::IP->new( PeerHost => $opt{host}, PeerPort => 22, Family => $opt{family}, ) } else { $socket = IO::Socket::INET->new( PeerHost => $opt{host}, PeerPort => 22, ) } # Open Net::SSH2 connection with the IO::Socket::IP object my $ssh2 = Net::SSH2->new(); if ($ssh2->connect($socket)) { print "[Connected]\n"; # DO STUFF } else { warn "Unable to connect to host $opt{host}: $!\n" }
      I use Net::SSH2 because it's the only SSH module I was able to get to work on Windows

      Yes, I've long given up on the others.
      Note that Net::SFTP::Foreign::Backend::Net_SSH2 installs trivially and works fine with Net::SSH2 on Windows - and, IMO, generally provides a more user-friendly interface.

      With that module (and its prerequisite Net::SFTP::Foreign) installed, one can then pass a "Net::SSH2 object already connected to the remote host and authenticated" to the Net::SFTP::Foreign constructor - so I think that IPv6 would thereby also be enabled if one wished to use Net::SFTP::Foreign with the Net::SSH2 backend.

      Update: I forgot to thank you for the code you posted ... thanks !!

      Cheers,
      Rob

        Thanks - your notes on integration of Net::SFTP::Foreign::Backend::Net_SSH2 are useful - if I ever need SFTP functions. Lately, I've been looking to augment my Cisco scripts currently using Net::Telnet::Cisco with Net::SSH2 for the above reasons about Windows support. I was trying to find some integration so the API would be similar to Net::Telnet(::Cisco) - something like Net::SSH2::Cisco - see here: Child Net::SSH2 object trouble.

        Ultimately, I got a hack job working, but would love to see a better approach that does something like you mention about integrating modules on the back end so re-use instead of re-write code.

      That's something that could be integrated inside Net::SSH2. You should consider sending a bug report pointing to your code, or even a patch.

        I considered that, but according to rt://96147, there is already an IPv6 feature request for Net::SSH2 regarding IO::Socket::IP that's over a year old.

        I went that route with Net::Telnet author Jay Rogers around 2012 - talking to him first before filing a bug. He was very responsive, pointed me towards the '-fhopen' temporary fix and had test code to me in a week or two and eventually Net::Telnet version 3.04 which supports IPv6 directly.

      Thanks for sharing this code. I plan to go ahead with Net::SFTP::Foreign for my current requirement, but this is useful info. Thanks again.