Ok, this might need a little bit of explaination up front.
I am currently working on an automation project using node-red.
I want to upload and download files from an remote server using ssh. For this tasks I use this node-red package called node-red-contrib-sftpc
. I rewrote the library a little bit, so that I can hand over some credentials for the sftp connection, via the payload which is handed over to the node.
To establish an connection the sftp.connect
method of the ssh2-sftp-client is used:
await sftp.connect({
host: node.server.host,
port: node.server.port,
username: node.server.username,
password: node.server.password});
There you can find in the documentation that you can provide connect
with the parameters hostHash
and hostVerifier
. The documentation of the ssh2 model, on which the ssh2-sftp-client is based, states that:
hostHash - string - Any valid hash algorithm supported by node. The host's key is hashed using this algorithm and passed to the hostVerifier function as a hex string. Default: (none)
hostVerifier - function - Function with parameters (hashedKey[, callback]) where hashedKey is a string hex hash of the host's key for verification purposes. Return true to continue with the handshake or false to reject and disconnect, or call callback() with true or false if you need to perform asynchronous verification. Default: (auto-accept if hostVerifier is not set)
So here is my problem: How do I write the hostVerifier
function? I want to pass hashedKey
and also fingerprint
, so that I can return true
or false
, when the handshake worked out or not.
I want to check, if the given server key fingerprint is the "right" one and that I connect to the correct server.
So far as I understood the second parameter, will be a callback function, but I do not know how to use that, so that it will verify the handshake. This was my try, or at least how I tried to do it.
node.server.hostVerifier = function (hashedKey, (hashedKey, msg.fingerprint)=> {
if (hashedKey = msg.fingerprint) return true;
else return false
}){};
await sftp.connect({
host: node.server.host,
port: node.server.port,
username: node.server.username,
password: node.server.password,
hostHash: 'someHashAlgo',
hostVerifier: node.server.hostVerifier,});
I know that this is completely wrong, but I am about to get crazy, because I have no idea, how to proper check the ssh host key fingerprint.
So I found a solution myself and want to share it with you.
I defined an arrow function as the hostVerifier
function, which takes implicite the value of the fingerprint through the msg.fingerprint
variable. I only do this, if node.server.fingerprint
has an value. So if I do not have an fingerprint at hand, the connection will still established.
node.server.fingerprint = msg.fingerprint;
if(!!node.server.fingerprint){
node.server.hostHash = 'md5';
node.server.hostVerifier = (hashedKey) => {
return (hashedKey === msg.fingerprint) ;};
node.server.algorithms = {serverHostKey: ['ssh-rsa'],};
};
For that I also declare my node.server.alogrithms
. With that it was a little bit of try and error.
So I put everything together here:
await sftp.connect({
host: node.server.host,
port: node.server.port,
username: node.server.username,
password: node.server.password,
hostHash: node.server.hostHash,
hostVerifier: node.server.hostVerifier,
algorithms: node.server.algorithms,
});