Unable to issue command/read data on remote host from Elixir using sshex framework

MacOS 12.5.1 (M1 Max)
Elixir 1.14.3 (compiled with Erlang/OTP 25)

I am trying to read some status data from a network switch within my Elixir application over ssh. I am attempting to do this using the SSHEx framework.

I am able to connect fine (returns ok, and I can see an open session on the switch), but when I issues a command I am unable to read any response, and it times out waiting.

To confirm I have started :ssh under Extra Application.

Here is the code I am using initially, I’m aware it’s not ideal at the moment, but it should at least be getting me some output.

    defmodule FibreTestUi.Ssh do
      defp connect do
        SSHEx.connect(
          ip: '192.168.1.1',
          user: 'admin',
          password: '!Password',
          modify_algorithms: [
            {:append, [{:kex, [:"diffie-hellman-group-exchange-sha1"]}]},
            {:append, [{:public_key, [:"ssh-rsa", :"ssh-dss"]}]}
          ]
        )
      end
    
      def list_port_status do
        {:ok, conn} = connect()
        SSHEx.cmd!(conn, 'show ssh', exec_timeout: 15000)
      end
    end

All I get back is:

    ** (RuntimeError) {:error, "Timeout. Did not receive data for 15000ms."}
        (sshex 2.2.1) lib/sshex.ex:100: SSHEx.cmd!/3
        iex:2: (file)

If I ssh into the switch manually, I am able to execute the command fine.

    user@comp ~ % ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 admin@192.168.1.1
    
    
    FS#show ssh
    Connection Version Encryption       Hmac         Compress   State           Username
             0     2.0 aes128-ctr       hmac-sha1    none       Session started admin
    FS#

If I pick another random device (ransom raspberry pi), and connect with a basic ‘echo hello’ I get a response fine.

    defmodule FibreTestUi.Ssh do
      defp connect do
        SSHEx.connect(
          ip: '10.11.xx.xx',
          user: 'pi',
          password: 'password',
          modify_algorithms: [
            {:append, [{:kex, [:"diffie-hellman-group-exchange-sha1"]}]},
            {:append, [{:public_key, [:"ssh-rsa", :"ssh-dss"]}]}
          ]
        )
      end
    
      def list_port_status do
        {:ok, conn} = connect()
        SSHEx.cmd!(conn, 'echo hello', exec_timeout: 5000)
      end
    end

"hello\n"

I have also tried doing this directly using :ssh with the following code:

      def send_command do
        {:ok, ssh_pid} =
          :ssh.connect('192.168.1.1', 22,
            user: 'admin',
            save_accepted_host: false,
            silently_accept_hosts: true,
            password: '!Password',
            modify_algorithms: [
              prepend: [kex: [:"diffie-hellman-group1-sha1", :"diffie-hellman-group-exchange-sha1"]],
              prepend: [public_key: [:"ssh-rsa", :"ssh-dss"]]
            ]
          )
    
        {:ok, chn} = :ssh_connection.session_channel(ssh_pid, 5000)
    
        _success = :ssh_connection.exec(ssh_pid, chn, 'show ssh', 5000)
    
        # for _ <- 0..1 do
        receive do
          {:ssh_cm, ^ssh_pid, value} -> IO.inspect(value)
        after
          5000 ->
            IO.puts(:stderr, "No message in 5 seconds")
        end
    
        :ok = :ssh.close(ssh_pid)
      end

The response I get is this, for every command, no matter what command I send.

    iex(20)> FibreTestUi.Ssh.send_command    
    {:data, 0, 0,
     <<2, 83, 67, 80, 58, 32, 83, 67, 80, 32, 83, 101, 114, 118, 101, 114, 32, 83,
       101, 114, 118, 105, 99, 101, 32, 105, 115, 32, 100, 105, 115, 97, 98, 108,
       101, 33, 10>>}

So it seems to be something specific to this device, but I can’t really work out what that would be. Anyone got any thoughts?

1 Like

Enable please the debug logs and post here the output, I have a feeling that your server might be using a deprecated public key algorithm.

Do you mean by adding ssh_msg_debug_fun to the connect function, like this?

    {:ok, ssh_pid} =
      :ssh.connect('192.168.1.1', 22,
        user: 'admin',
        save_accepted_host: false,
        silently_accept_hosts: true,
        password: '!Password',
        modify_algorithms: [
          prepend: [kex: [:"diffie-hellman-group1-sha1", :"diffie-hellman-group-exchange-sha1"]],
          prepend: [public_key: [:"ssh-rsa", :"ssh-dss"]]
        ],
        ssh_msg_debug_fun: fn _, _, msg, _ -> IO.inspect(msg) end
      )

If so, then it doesn’t seem to produce any additional output.

FibreTestUi.Ssh.send_command
{:data, 0, 0,
 <<2, 83, 67, 80, 58, 32, 83, 67, 80, 32, 83, 101, 114, 118, 101, 114, 32, 83,
   101, 114, 118, 105, 99, 101, 32, 105, 115, 32, 100, 105, 115, 97, 98, 108,
   101, 33, 10>>}
:ok
iex(2)>

There was another one, can’t remember it right now, try to set quiet_mode to false, maybe that will start to print something: Erlang -- ssh

    {:ok, ssh_pid} =
      :ssh.connect('192.168.1.1', 22,
        user: 'admin',
        save_accepted_host: false,
        silently_accept_hosts: true,
        password: '!Password',
        modify_algorithms: [
          prepend: [kex: [:"diffie-hellman-group1-sha1", :"diffie-hellman-group-exchange-sha1"]],
          prepend: [public_key: [:"ssh-rsa", :"ssh-dss"]]
        ],
        ssh_msg_debug_fun: fn _, _, msg, _ -> IO.inspect(msg) end,
        quiet_mode: false
      )

Same result, so frustrating. Really wish I could work out what this meant, as it might give me a clue as to what’s not working.

<<2, 83, 67, 80, 58, 32, 83, 67, 80, 32, 83, 101, 114, 118, 101, 114, 32, 83,
    101, 114, 118, 105, 99, 101, 32, 105, 115, 32, 100, 105, 115, 97, 98, 108,
    101, 33, 10>>

I did see a post on StackOverlflow that suggested using :ssh_connection.shell instead as some devices don’t like :ssh_connection.exec, but I can’t really work out how to use :ssh_connection.shell?

Thanks for you efforts so far!

Gareth

Can you confirm what version of ssh is used for communication? Because in erlang documentation of ssh it is stated that only version 2.0 is supported by the client Erlang -- SSH

Not sure exactly how to solve the problem, but the binary reads:

"SCP: SCP Server Service is disable!\n"
1 Like

Here’s the stats from the server, it states v2 (which is what the UI of the switch says it’s doing also):

comp@host fibre_test_ui % ssh -v 192.168.1.1

OpenSSH_8.6p1, LibreSSL 3.3.6

debug1: Local version string SSH-2.0-OpenSSH_8.6

debug1: Remote protocol version 2.0, remote software version SSH

debug1: compat_banner: no match: SSH

debug1: Authenticating to 192.168.1.1:22 as '####'

debug1: SSH2_MSG_KEXINIT sent

debug1: SSH2_MSG_KEXINIT received

debug1: kex: algorithm: (no match)

Unable to negotiate with 192.168.1.1 port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1

@benstepp thanks for the translation, how did you translate that into text? (Apologies, working with Binaries e.t.c is not a strength of mine)

Also somewhat stumped by that error message, off to google I go!

Not a strength of mine either, but every time I see a binary like this I just dump it into String.graphemes/1 to get some readable characters lol.

Ok, so I’ve enable SCP on the switch (not sure why this would be needed, maybe it’s how the commands are executed?)

So that block of data has gone away, but now I get absolutely nothing back :frowning:

FibreTestUi.Ssh.send_command
{:eof, 0}

Have you tried to execute this on a known working environment like a linux machine? I have a feeling that the problem is somewhere in the protocol.

I have used the same machine/code to connect to a Pi and that seems to work fine, are you proposing I try running the code on a different (nix) based machine?

Then most probably this is a issue related to protocol implementation on that switch.

I have worked with some old sftp servers, that would also have bugs like the one you have, back in the day the issue I found was that their implementation was not following 1:1 the specification of the protocol, never managed to make them work with the erlang client.

I would suggest to use Port and use OpenSSH, the only thing to be careful with ports is not to leak connections/processes.

Thanks all, I have decided to stop fighting this and just use the serial console port instead, seems the implementation on this switch is just a little “odd” and the serial port is, well a serial port, so a little easier to deal with . . .

Thanks

Gareth

1 Like