Using ssh fingerprint in ssh2-sftp-client

1.7k views Asked by At

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.

1

There are 1 answers

0
Peter On BEST ANSWER

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,
                });