Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bypass host key checking with Net::SCP

Tags:

perl

I'm using the Perl Net::SCP module to SCP tarballs to a remote server.

The remote server does not have a static IP, so every time the IP address changes the sending machine would need to accept the host key.

This breaks my script, as now I have to manually accept the host key each time the IP changes.

Is there a way I can have Net::SCP bypass host key checking?

I saw an option with Net::SCP::Expect, but I'm not sure if I would be required to use this module.

like image 858
Alex Giunta Avatar asked Apr 19 '26 15:04

Alex Giunta


1 Answers

Solution

Yes, you can do that with the module Net::SCP::Expect in the following way (unix system assumed):

#!/usr/bin/perl
use strict;
use warnings;
use Net::SCP::Expect;

my $scp = Net::SCP::Expect->new(
    host     => 'localhost', # or target IP address
    user     => 'username',
    password => 'mysecretpass',
    auto_yes => 1, # automatically pass a 'yes' string to any yes/no questions
    timeout  => 5,
    option   => 'UserKnownHostsFile=/dev/null StrictHostKeyChecking=no' # the trick
);

# now send the file
$scp->scp('file.tar', 'TargetDirectory/') || die "scp() failed: $!\n";

Explanation

SCP actually uses SSH, so whenever the remote identity/fingerprint changes, the connection is no longer permitted because of security reasons. As you can probably imagine, this is for your own security because you could also be the victim of a "man in the middle attack" or similar things. Your machine has most likely saved all known fingerprints in the following file:

~/.ssh/known_hosts

And this causes the problem for you. In the Perl script above you can see how the options UserKnownHostsFile=/dev/null and StrictHostKeyChecking=no are passed to the constructor. These are actually SSH options, which can be either specified on the command line or in your machine's SSH configuration file. Since SCP uses the same options, you can pass them to the module and therefore completely bypass the identity check in your case.

Why does it work?

By replacing(*) the known_hosts file with /dev/null, you basically give it an empty file that cannot be modified. This allows you to completely ignore the safety check and your file will get sent as expected.

(*): of course it doesn't get replaced in the filesystem, but the module will just use it as the temporary location/path

like image 160
reflective_mind Avatar answered Apr 22 '26 12:04

reflective_mind