Losing connection with Net::SSH::Perl - perl

SOLUTION BELOW
We have an ETL system that extracts data into a CSV, uploads it to another server, and then needs to connect to the other server and call a java jar to load the csv into memcache. I've got a script that can perform every step of this but loses the SSH connection for the final step. The process on the remote machine continues and completes.
I'm using Net::SSH::Perl for this and it receives a "Connection failed: Connection reset by peer" error after running for a short time. I've boiled the script down to this and replicated the results:
#!/usr/bin/perl
use strict;
use Net::SSH::Perl;
use Log::Log4perl;
my ($stdout, $stderr, $exit, $ssh);
$ssh = Net::SSH::Perl->new('sshost',
identity_files => ['/path/to/key.rsa'],
protocol => 2,
debug => 1);
$ssh->login('user');
my $cmd = "java -Xms4096m -Xmx4096m -DetlDate=20120427 -DmemcacheHosts=host1,host2 -cp etl-0.1-SNAPSHOT.jar com.nnn.platform.service.etl";
$ssh->register_handler("stdout", sub {
my($channel, $buffer) = #_;
print "STDOUT: ", $buffer->bytes;
});
$ssh->register_handler("stderr", sub {
my($channel, $buffer) = #_;
print "STDERR: ", $buffer->bytes;
});
$ssh->cmd("cd /usr/local/loader; $cmd");
The SSH debug info I get is:
localhost: Reading configuration data /home/user/.ssh/config
localhost: Reading configuration data /etc/ssh_config
localhost: Connecting to sshost, port 22.
localhost: Remote protocol version 2.0, remote software version OpenSSH_4.3
localhost: Net::SSH::Perl Version 1.34, protocol version 2.0.
localhost: No compat match: OpenSSH_4.3.
localhost: Connection established.
localhost: Sent key-exchange init (KEXINIT), wait response.
localhost: Algorithms, c->s: 3des-cbc hmac-sha1 none
localhost: Algorithms, s->c: 3des-cbc hmac-sha1 none
localhost: Entering Diffie-Hellman Group 1 key exchange.
localhost: Sent DH public key, waiting for reply.
localhost: Received host key, type 'ssh-dss'.
localhost: Host 'sshost' is known and matches the host key.
localhost: Computing shared secret key.
localhost: Verifying server signature.
localhost: Waiting for NEWKEYS message.
localhost: Send NEWKEYS.
localhost: Enabling encryption/MAC/compression.
localhost: Sending request for user-authentication service.
localhost: Service accepted: ssh-userauth.
localhost: Trying empty user-authentication request.
localhost: Authentication methods that can continue: publickey,gssapi-with-mic.
localhost: Next method to try is publickey.
localhost: Trying pubkey authentication with key file '/path/to/key.rsa'
localhost: Login completed, opening dummy shell channel.
localhost: channel 0: new [client-session]
localhost: Requesting channel_open for channel 0.
localhost: channel 0: open confirm rwindow 0 rmax 32768
localhost: Got channel open confirmation, requesting shell.
localhost: Requesting service shell on channel 0.
localhost: channel 1: new [client-session]
localhost: Requesting channel_open for channel 1.
localhost: Entering interactive session.
localhost: Sending command: cd /usr/local/loader; java -Xms4096m -Xmx4096m -DetlDate=20120427 -DmemcacheHosts=host1,host2 -cp etl-0.1-SNAPSHOT.jar com.nnn.platform.service.etl
localhost: Sending command: cd /usr/local/loader; java -Xms4096m -Xmx4096m -DetlDate=20120427 -DmemcacheHosts=host1,host2 -cp etl-0.1-SNAPSHOT.jar com.nnn.platform.service.etl
localhost: Requesting service exec on channel 1.
localhost: channel 1: open confirm rwindow 0 rmax 32768
The jar's output is then printed to STDERR and I see it returned. After 9 seconds it stops and I eventually get the connection reset by peer error. The STDERR handler is working as expected.
I'm not sure if this is an issue with Net::SSH::Perl handling commands that take awhile to run/return only over STDERR or something more. I've been considering switching to Net::SSH2 as it seems like a fuller featured library, but I'd really like to know why this is failing.
SOLUTION
The problem was with the output only going to STDERR. I edited my command to add 2>&1 and thereby redirect STDERR to STDOUT and suddenly everything worked as expected.

Net::SSH::Perl is not maintained anymore and has a long list of known unsolved bugs. Nowadays there are better modules available from CPAN as Net::SSH2 or Net::OpenSSH.
For instance:
my $ssh = Net::OpenSSH->new($sshost,
user => $user,
key_path => '/path/to/key.rsa');
my ($out, $err) = $ssh->capture2($cmd);

The problem was with the output only going to STDERR. I edited my command to add 2>&1 and thereby redirect STDERR to STDOUT and suddenly everything worked as expected.
my $cmd = "java -Xms4096m -Xmx4096m -DetlDate=20120427 -DmemcacheHosts=host1,host2 -cp etl-0.1-SNAPSHOT.jar com.nnn.platform.service.etl 2>&1";

Related

SFTP connection failure with Perl "Net::SFTP" module

I am trying to connect to SFTP server using Perl but I get the following connection error: Permission denied at /app/perl-5.24.3/lib/site_perl/5.24.3/Net/SFTP.pm line 63.
My connection code 'sftp_test2.pl':
use strict;
use warnings;
use Net::SFTP;
my $server = 'downloads-server';
my $user = 'user';
my $port = "10022";
my $password = '';
my %args = (
user => "$user",
port => "$port",
ssh_args => {
user => "$user",
identity_files => [ 'path/sftp_download'],
port => "$port",
protocol=>'2,1',
debug => 1,
}
);
my $sftp=Net::SFTP->new($server, %args) or die "could not open connection to $server\n";
execution:
$>perl sftp_test2.pl
Reading configuration data path/home/.ssh/config
Reading configuration data /etc/ssh_config
Connecting to downloads-server, port 10022.
Remote version string: SSH-2.0-CrushFTPSSHD
Remote protocol version 2.0, remote software version CrushFTPSSHD
Net::SSH::Perl Version 2.14, protocol version 2.0.
No compat match: CrushFTPSSHD.
Connection established.
Sent key-exchange init (KEXINIT), waiting for response.
Using diffie-hellman-group-exchange-sha256 for key exchange
Host key algorithm: ssh-rsa
Algorithms, c->s: aes256-ctr hmac-sha2-512-etm#openssh.com none
Algorithms, s->c: aes256-ctr hmac-sha2-512-etm#openssh.com none
Entering Diffie-Hellman Group Exchange.
SSH2_MSG_KEX_DH_GEX_REQUEST(2048<4096<8192) sent
Sent DH Group Exchange request, waiting for reply.
Received 4096 bit DH Group Exchange reply.
Generating new Diffie-Hellman keys.
Entering Diffie-Hellman key exchange.
Sent DH public key, waiting for reply.
Received host key, type 'ssh-rsa'.
Host 'downloads-server' is known and matches the host key.
Verifying server signature.
Send NEWKEYS.
Waiting for NEWKEYS message.
Enabling encryption/MAC/compression.
Sending request for user-authentication service.
Service accepted: ssh-userauth.
Trying empty user-authentication request.
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Trying password authentication.
Will not query passphrase in batch mode.
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Trying password authentication.
Will not query passphrase in batch mode.
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Trying password authentication.
Will not query passphrase in batch mode.
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Next method to try is publickey.
Publickey: testing agent key 'my-server'
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Next method to try is publickey.
Publickey: testing agent key 'path/home/.ssh/id_rsa'
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Next method to try is publickey.
Trying pubkey authentication with key file 'path/sftp_download'
Authentication methods that can continue: password,publickey,keyboard-interactive.
Next method to try is password.
Next method to try is publickey.
Permission denied at /app/perl-5.24.3/lib/site_perl/5.24.3/Net/SFTP.pm line 63.
I thought that it is related to my private key, but I can connect via unix command:
sftp -oPort=10022 -oIdentityFile=path/sftp_download user#downloads-server
Connecting to downloads-server...
sftp>
I tried to find a solution in many articles and also tried few code variations, but without a success.
Am I doing something wrong?
Is it a known bug? any workaround?
How can I debug it to find the reason (I am not very well familiar with SSH/FTP).
EDIT:
I suspected that it may be related to multiple connection failing attempts with password so I removed the password authentication from "%AUTH_MAP" in the file "app/perl-5.24.3/lib/site_perl/5.24.3/x86_64-linux/Net/SSH/Perl/AuthMgr.pm" and it connected as expected!
Is there a way to force using only/first key authentication?
Thanks in advance!
Mike
The code to disable password authentication (only authentication key) is:
ssh_args => {
user => $user,
options => [ 'PasswordAuthentication no' ],
identity_files => [ 'path/sftp_download'],
port => $port,
protocol =>'2,1',
debug => 1,
}

Unable to Login with Net::SSH:Perl

I am just starting to use Net::SSH::Perl and it seems that I ranning into something weird. If I set the interactive flag to 1 and input my password I am am to login remotely to the machine via ssh but if I leave the interactive flag off or set it to 0 the login fails. I confirm that I am able to use Net::SSH::Perl to log into my local machine so it must be something that I am doing wrong for this particular remote machine, which the under laying OS is SuSE. I also confirmed that I am able to ssh to the remote machine from a terminal window.
use Net::SSH::Perl;
my $cmd = 'uptime';
my $ssh = Net::SSH::Perl->new($host, interactive=> 0, debug => 1);
$ssh->login($user, $pass);
my($stdout, $stderr, $exit) = $ssh->cmd($cmd);
print $stdout;
Below is the logs that are output from debug when the interactive flag is set to 0.
localhost.localdomain: Reading configuration data /home/user/.ssh/config
localhost.localdomain: Reading configuration data /etc/ssh_config
localhost.localdomain: Connecting to 1.1.1.1, port 22.
localhost.localdomain: Remote version string: SSH-2.0-OpenSSH_5.1
localhost.localdomain: Remote protocol version 2.0, remote software version OpenSSH_5.1
localhost.localdomain: Net::SSH::Perl Version 1.38, protocol version 2.0.
localhost.localdomain: No compat match: OpenSSH_5.1
.
localhost.localdomain: Connection established.
localhost.localdomain: Sent key-exchange init (KEXINIT), wait response.
localhost.localdomain: Algorithms, c->s: 3des-cbc hmac-sha1 none
localhost.localdomain: Algorithms, s->c: 3des-cbc hmac-sha1 none
localhost.localdomain: Entering Diffie-Hellman Group 1 key exchange.
localhost.localdomain: Sent DH public key, waiting for reply.
localhost.localdomain: Received host key, type 'ssh-dss'.
localhost.localdomain: Host '1.1.1.1' is known and matches the host key.
localhost.localdomain: Computing shared secret key.
localhost.localdomain: Verifying server signature.
localhost.localdomain: Waiting for NEWKEYS message.
localhost.localdomain: Send NEWKEYS.
localhost.localdomain: Enabling encryption/MAC/compression.
localhost.localdomain: Sending request for user-authentication service.
localhost.localdomain: Service accepted: ssh-userauth.
localhost.localdomain: Trying empty user-authentication request.
localhost.localdomain: Authentication methods that can continue: publickey,keyboard-interactive.
localhost.localdomain: Next method to try is publickey.
localhost.localdomain: Publickey: testing agent key 'user#localhost.localdomain'
localhost.localdomain: Authentication methods that can continue: publickey,keyboard-interactive.
localhost.localdomain: Next method to try is publickey.
localhost.localdomain: Publickey: testing agent key 'user'
localhost.localdomain: Authentication methods that can continue: publickey,keyboard-interactive.
localhost.localdomain: Next method to try is publickey.
Permission denied at /home/user/workspace/perl-random/avamar_ssh.pl line 4.
I am guessing I am doing something wrong, so if someone could point in the right direction that would be awesome.
Thanks.
This part:
localhost.localdomain: Authentication methods that can continue: publickey,keyboard-interactive.
means that the server is allowing two methods for authenticating:
publickey — public-key authentication
You mention in a comment that this not an option for you.
keyboard-interactive — where you enter a password
It should hardly come as a surprise that this only works in interactive mode.
So, what you're trying to do is not possible.
The good news is, this sounds like the X-Y Problem. If you give us more details about your real problem, we may be able to suggest a better approach.

mkdir //.ssh: Permission denied at /usr/lib/perl5/site_perl/5.8.8/Net/SSH/Perl/Util/Hosts.pm line 92

I'm using "Net::SFTP" in perl cgi file to put files to a windows M/C from my dev box.
After adding below new directory manually (with 0777 permissions) everything works fine:
bash-4.1$ pwd
/.ssh
-bash-4.1$ cd ..
-bash-4.1$ ls -ltra | grep .ssh
drwxrwxrwx 2 root root 4096 Jan 23 23:57 .ssh
Problem (if I don't add above directory manually ) here is as per my understanding:
Apache is running cgi with user as "nobody" which do not have permissions to make directory after connection is established via sftp and I'm getting below error messages in logs:
xxx.xxx.net: Reading configuration data /.ssh/config
xxx.xxx.net: Reading configuration data /etc/ssh_config
xxx.xxx.net: Connecting to xxx.xxx.xxx.com, port 22.
xxx.xxx.net: Remote protocol version 2.0, remote software version 5.17 FlowSsh: Bitvise SSH Server (WinSSHD) 5.58: free only for personal non-commercial use^M
Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::Calc at /usr/lib/perl5/site_perl/5.8.8/Crypt/DH.pm line 6
xxx.xxx.net: Net::SSH::Perl Version 1.34, protocol version 2.0.
xxx.xxx.net: No compat match: 5.17 FlowSsh: Bitvise SSH Server (WinSSHD) 5.58: free only for personal non-commercial use^M.
xxx.xxx.net: Connection established.
xxx.xxx.net: Sent key-exchange init (KEXINIT), wait response.
xxx.xxx.net: Algorithms, c->s: 3des-cbc hmac-sha1 none
xxx.xxx.net: Algorithms, s->c: 3des-cbc hmac-sha1 none
xxx.xxx.net: Entering Diffie-Hellman Group 1 key exchange.
xxx.xxx.net: Sent DH public key, waiting for reply.
xxx.xxx.net: Received host key, type 'ssh-dss'.
xxx.xxx.net: Permanently added 'xxx.xxx.xxx.com' to the list of known hosts.
**mkdir //.ssh: Permission denied at /usr/lib/perl5/site_perl/5.8.8/Net/SSH/Perl/Util/Hosts.pm line 92**
I tried to solve this problem with different methods given over internet but nothing is working for me.
Can anybody suggest possible solution?
Any help will be greatly appreciated.
I recently ran into the same problem myself and you are correct that it is a permissions issue. When your nobody process tries to connect to the remote server, it wants to write the remote host key to a file. This is the step that is failing in your error message (Hosts.pm line 92).
My solution was to create a nobody-writable location for the NET::SFTP to write the known_hosts file and to specify that location before you construct your NET::SFTP connection.
$ENV{HOME} = '/nobody/writable/location/';
You can find more information on this problem at http://www.perlmonks.org/?node_id=599078

Difference with Net::SSH::Perl on perl 5.12 and 5.14

I have the following code (of course I replaced myremoteserver.com):
use Modern::Perl;
use Net::SSH::Perl;
use Data::Dumper;
my $ssh = Net::SSH::Perl->new('myremoteserver.com', debug => 1, port => 2999);
$ssh->login('root');
print Dumper $ssh->cmd('uptime');
On a keyless environment, I'm running it both on perl 5.12 and 5.14.
On perl 5.12 it seems to work:
$ perl5.12 /tmp/sshtest.pl
ko.local: Reading configuration data /Users/david/.ssh/config
ko.local: Reading configuration data /etc/ssh_config
ko.local: Connecting to myremoteserver.com, port 2999.
ko.local: Remote protocol version 2.0, remote software version OpenSSH_5.8p1 Debian-1ubuntu3
Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::Calc at /opt/local/lib/perl5/site_perl/5.12.3/Crypt/DH.pm line 6
ko.local: Net::SSH::Perl Version 1.34, protocol version 2.0.
.o.local: No compat match: OpenSSH_5.8p1 Debian-1ubuntu3
ko.local: Connection established.
ko.local: Sent key-exchange init (KEXINIT), wait response.
ko.local: Algorithms, c->s: 3des-cbc hmac-sha1 none
ko.local: Algorithms, s->c: 3des-cbc hmac-sha1 none
ko.local: Entering Diffie-Hellman Group 1 key exchange.
ko.local: Sent DH public key, waiting for reply.
ko.local: Received host key, type 'ssh-dss'.
ko.local: Host 'myremoteserver.com' is known and matches the host key.
ko.local: Computing shared secret key.
ko.local: Verifying server signature.
ko.local: Waiting for NEWKEYS message.
ko.local: Send NEWKEYS.
ko.local: Enabling encryption/MAC/compression.
ko.local: Sending request for user-authentication service.
ko.local: Service accepted: ssh-userauth.
ko.local: Trying empty user-authentication request.
ko.local: Authentication methods that can continue: publickey.
ko.local: Next method to try is publickey.
ko.local: Publickey: testing agent key '/Users/david/.ssh/github_rsa'
ko.local: Authentication methods that can continue: publickey.
ko.local: Next method to try is publickey.
Permission denied at /tmp/sshtest.pl line 9
But on perl 5.14:
$ perl5.14 /tmp/sshtest.pl
ko.local: Reading configuration data /Users/david/.ssh/config
ko.local: Reading configuration data /etc/ssh_config
ko.local: Connecting to myremoteserver.com, port 2999.
ko.local: Remote protocol version 2.0, remote software version OpenSSH_5.8p1 Debian-1ubuntu3
ko.local: Net::SSH::Perl Version 1.34, protocol version 2.0.
.o.local: No compat match: OpenSSH_5.8p1 Debian-1ubuntu3
ko.local: Connection established.
ko.local: Sent key-exchange init (KEXINIT), wait response.
ko.local: Algorithms, c->s: 3des-cbc hmac-sha1 none
ko.local: Algorithms, s->c: 3des-cbc hmac-sha1 none
ko.local: Entering Diffie-Hellman Group 1 key exchange.
ko.local: Sent DH public key, waiting for reply.
ko.local: Received host key, type 'ssh-dss'.
ko.local: Host 'myremoteserver.com' is known and matches the host key.
ko.local: Computing shared secret key.
ko.local: Verifying server signature.
Key verification failed for server host key at /opt/local/lib/perl5/site_perl/5.14.1/Net/SSH/Perl/SSH2.pm line 92
The only difference I see is Math::BigInt returns a warning on perl 5.12.
Some debugging info:
~ $ perl5.12 -MNet::SSH::Perl -e 'print $Net::SSH::Perl::VERSION, "\n";'
1.34
~ $ perl5.14 -MNet::SSH::Perl -e 'print $Net::SSH::Perl::VERSION, "\n";'
1.34
~ $ perl5.12 -MMath::BigInt -e 'print $Math::BigInt::VERSION, "\n";'
1.997
~ $ perl5.14 -MMath::BigInt -e 'print $Math::BigInt::VERSION, "\n";'
1.997
Any idea what the problem here is?
There was a change to the default value for a configuration option that controlled how https validation was performed (specifically, the PERL_LWP_SSL_VERIFY_HOSTNAMES environment variable), when LWP::Protocol::https was pulled out of the main LWP library - now hostname checking is on by default, where it was off previously. It is possible that your perl 5.14 library picked up these new changes, and 5.12 is using the old versions.
There is also more information in "Now you need LWP::Protocol::https".

Why is ssh prompting me for a password after I give it to Perl's Net::SSH::Perl?

I am using Net::SSH::Perl to execute a command on a remote server as follows:
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new($host);
$ssh->login($user, $pass);
my ($stdout, $stderr, $exit) = $ssh->cmd($cmd);
But when I execute the above script, a password prompt comes again. Meaning the password I supplied in $pass is not taken to establish the ssh connection. Why is this? Any idea how I can overcome this? I give below the debug info:
serv1: Reading configuration data /root/.ssh/config
serv1: Reading configuration data /etc/ssh_config
serv1: Allocated local port 1023.
serv1: Connecting to 15.154.59.63, port 22.
serv1: Remote protocol version 1.99, remote software version OpenSSH_4.2
serv1: Net::SSH::Perl Version 1.34, protocol version 1.5.
serv1: No compat match: OpenSSH_4.2.
serv1: Connection established.
serv1: Waiting for server public key.
serv1: Received server public key (768 bits) and host key (1024 bits).
serv1: Host '15.154.59.63' is known and matches the host key.
serv1: Encryption type: DES3
serv1: Sent encrypted session key.
serv1: Received encryption confirmation.
serv1: RSA authentication failed: Can't load public key.
serv1: Doing challenge response authentication.
Password:
The password prompt should not be coming right, given that I have already supplied the password in $pass variable?
UPDATE(Based on the comments received):
I tried the following:
my $ssh = Net::SSH::Perl->new($host, debug =>1, identity_files => []);
Now, I don't get the message "RSA authentication failed: " but still the password prompt appears. I give below the debug info:
serv1: Allocated local port 1023.
serv1: Connecting to 15.154.59.63, port 22.
serv1: Remote protocol version 1.99, remote software version OpenSSH_4.2
serv1: Net::SSH::Perl Version 1.34, protocol version 1.5.
serv1: No compat match: OpenSSH_4.2. kf-linux-dm3: Connection established.
serv1: Waiting for server public key.
serv1: Received server public key (768 bits) and host key (1024 bits).
serv1: Host '15.154.59.63' is known and matches the host key.
serv1: Encryption type: DES3
serv1: Sent encrypted session key.
serv1: Received encryption confirmation.
serv1: Doing challenge response authentication.
Password:
Could someone enlighten me?
This line in your errors:
serv1: RSA authentication failed: Can't load public key.
tells me that your program is trying to do automatic logins, which is not what you want to do when you need a password to log in.
Check the Perl/ssh documentation:
identity_files
A list of RSA/DSA identity files to be used in RSA/DSA authentication. The value of this argument should be a reference to an array of strings, each string identifying the location of an identity file. Each identity file will be tested against the server until the client finds one that authenticates successfully.
If you don't provide this, RSA authentication defaults to using $ENV{HOME}/.ssh/identity, and DSA authentication defaults to $ENV{HOME}/.ssh/id_dsa.
You might try setting identity_files to an empty array, to see if that forces it to use your supplied password; or you could go ahead and set up public key authentication like in the link above.
serv1: Doing challenge response authentication.
That's your key line. SSH actually has multiple types of password-like authentication. One of them is strait password authentication (controlled by the PasswordAuthentication option in /etc/sshd_config), I suspect that is what the $pass you sent is for. Another one is challenge-response authentication, where the server sends one or more challenges, and you are expected to reply with the correct responses. Ref and Spec.
So, technically, ssh isn't asking you for a password. Its asking you for a reply to an arbitrary challenge from the server, and that challenge just happens to be "Password:".
Possibly, it'll work if you use Net::SSH::Perl::KeyboardInt explicitly?
Of course, you really ought to set up RSA public key authentication.
You need to disable ChallengeResponse authentication:
#!/usr/bin/perl
use strict;
use Net::SSH::Perl;
my $user = 'user';
my $pw = 'pw';
my $host = 'some.server';
my $cmd = 'id';
my %params = (
'debug' => 0,
);
# get the ssh connection object
my $ssh = Net::SSH::Perl->new($host, %params);
# get the configuration object associated with the host connection
my $cfg = $ssh->config;
# disable challenge/response authentication
my $v = $cfg->set('auth_ch_res', 0);
# set the login parameters
$ssh->login($user, $pw);
# issue the command (which is when the authentication actually takes place)
my($stdout, $stderr, $exit) = $ssh->cmd($cmd);
# do what you want with the result
print $stdout;