【问题标题】:Perl Net::SSH2 pubkey authentication issuePerl Net::SSH2 公钥认证问题
【发布时间】:2016-09-26 23:10:52
【问题描述】:

我正在尝试使用 Net::SSH2 连接到远程 SSH 服务器。命令行 ssh 工作正常。不过,我似乎无法找出正确的基于 auth_host 的参数

这是我的代码:

use Net::SSH2;

my $ssh = Net::SSH2->new();
$ssh->debug(1);
$ssh->trace(-1);
$ssh->connect('remotehost.remotedomain.tld') or die;
$ssh->auth_hostbased('username',
    'ssh-rsa  AAAAB3Nz[..]C0JoaFF9 root@myhost',
    '-----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: AES-128-CBC,FA97214E87562096A7E480C82DAE5EB4

    XIMKnj9k[..]kpRo5V
    -----END RSA PRIVATE KEY-----',
    'myhost.mydomain.tld',
    'username',
    'keypassword') or die;

sn-p 在 @ $ssh->auth_hostbased 中死去,只有一个 'Net::SSH2::DESTROY object 0xe17de0'。设置跟踪似乎无关紧要。用 $ssh->die_with_error 替换 die 会引发“die_with_error 不是有效的 Net::SSH2 宏”。下载当前 0.53 版本的 Net:SSH2 不起作用,因为脚本不再编译:'Net::SSH2 object version 0.44 does not match bootstrap parameter 0.53'

感谢任何有关正确参数格式或替代模块的帮助。

【问题讨论】:

  • 您将密码短语作为最后一个参数传递,对吗?你从命令行连接时使用了什么认证方式?
  • 这在 bash 中有效:'ssh -i /root/.ssh/privkey username@remotehost.remotedomain.tld ls -l' 然后我输入密码来解锁 privkey
  • 使用auth_publickey 方法。顺便说一句,最新的 Net::SSH2 版本是 0.60。
  • 不高兴。没有错误消息可以使用,这有点令人沮丧。 strace 揭示了这一点: read(5, "-----BEGIN RSA PRIVATE KEY-----\n"..., 4096) = 1766 ||关闭(5) = 0 || munmap(0x7f10a0dd8000, 4096) = 0 ||写(2,“死于 ./nrp.pl 第 21 行。\n”,26死于 ./nrp.pl 第 21 行。)= 26 || write(2, "Net::SSH2::DESTROY object 0xf73d"..., 35Net::SSH2::DESTROY object 0xf73dc0 ) = 35 鉴于没有网络写入,我猜想 Net:SSH2 不喜欢这个键
  • 在调用die之前打印Net::SSH2错误:print STDERR join(' ', $ssh->error);

标签: perl ssh public-key


【解决方案1】:

为什么不使用 Net::OpenSSH ? 这是一个简单的 ssh 包装脚本,我前段时间写的:

#!/usr/bin/perl

#Simple SSH Remote Executor  using Net::OpenSSH Library

use warnings;
use strict;
use Net::OpenSSH;
# see http://search.cpan.org/~salva/Net-OpenSSH-0.62/lib/Net/OpenSSH.pm#DEBUGGING
$Net::OpenSSH::debug = undef;
use Getopt::Long;


my $timeout = 10;
my ($username,$identity,$hostname,$command) = undef;
my $uid=getpwuid($<);
my $ctl_dir=qq{/tmp/.libnet-puppet-$uid};
my $ctl_mode=0700;

if ( ! -d $ctl_dir ) { mkdir( $ctl_dir,$ctl_mode ) };

open my $stderr_fh, '>>', '/dev/null' or die $!;


sub print_help{
    print qq{\nusage: $0 [options] -h Hostname

        -u username

        -i identity

        -c command

        long options are supported !

  };
        exit (1);
}



GetOptions ("hostname=s" => \$hostname, # string
                "username=s" => \$username, # string
                "identity=s" => \$identity, # string
                "command=s" => \$command) # string
or print_help;

if ( not defined $username or not defined $identity or not defined $hostname or not defined $command ) { print_help };

my $port = q{22};
my $user = $username;
my $ssh;

my $cmd = qq{$command};

my $options = {
    host => $hostname,
           user => $user,
           port => $port,
           default_stderr_fh => $stderr_fh,
       ctl_dir => $ctl_dir,
       master_opts => [
                   -o => "UserKnownHostsFile=/dev/null",
                   -o => "StrictHostKeyChecking=no",
                   -o => qq{IdentityFile=$identity},
               ],
    timeout => $timeout };

#ALARM Timer timeout handling
$SIG{ALRM} = sub {
  printf( "%s\n", qq{invalid-timeout-connecting-to-node-$hostname});
  exit(1);
};

#init alarm timer ;-)
alarm( $timeout );

$ssh = Net::OpenSSH->new( %{$options} )
           or $ssh->error and die "Couldn't establish SSH connection: ". $ssh->error;

my (@out, $err) = $ssh->capture2({ timeout => 10 }, $cmd);

die("Error: %s\n", $err) if defined $err;

if ( (scalar(@out)) eq 0 ) {
  printf( "%s\n", qq{invalid-empty-string-received-by-node-$hostname});
  exit(1);
}

foreach my $line ( @out ) {
    $line =~ s/^\s{1,}//;
       printf ("%s",$line);
}

使用 cpanm (cpanm Net::OpenSSH) 或作为 debian 包“libnet-openssh-perl”安装它。
有关可用的主选项,请参阅“man ssh_config”。
不过,我认为该脚本会很有帮助。
Rgds。弗朗茨

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    相关资源
    最近更新 更多