otp icon indicating copy to clipboard operation
otp copied to clipboard

SSH server key exchange fails with dropbear dbclient due to RFC4253 sec 7 "each side MAY guess"

Open KarlVogel opened this issue 1 year ago • 3 comments

Describe the bug Using the SSH client from dropbear might fail to connect to the SSH server implementation of OTP, with following error:

10:05:48.080 [notice] Erlang SSH :server version: 5.1.1 (OpenSSL 3.2.1 30 Jan 2024. FIPS available but not enabled).
Address: 127.0.0.1:2222
Peer client version: ~c"SSH-2.0-dropbear_2024.85"
Peer address: 127.0.0.1:57220
Disconnects with code = 2 [RFC4253 11.1]: Protocol error
State = {new_keys,server,init}
Module = ssh_connection_handler, Line = 1370.
Details:
  Message ssh_msg_kex_ecdh_init in wrong state ({new_keys,server,init})

The reason is that the dropbear client may send a guess KEXINIT and if the guess doesn't match it will send another KEXINIT which then fails the state machine. This is described in RFC4253 sec 7:

   However, if the guess was wrong, and a packet was optimistically sent
   by one or both parties, such packets MUST be ignored (even if the
   error in the guess would not affect the contents of the initial
   packet(s)), and the appropriate side MUST send the correct initial
   packet.

The initial guess send happens here: https://github.com/mkj/dropbear/blob/2674736bce847bc51a30a07c191562047659ac1f/src/common-kex.c#L112

and depending on whether the first guess matches or not, another KEX might be send: https://github.com/mkj/dropbear/blob/2674736bce847bc51a30a07c191562047659ac1f/src/common-kex.c#L1037

The OTP ssh code only seems to encode the first_kex_packet_follows in the ssh_msg_kexinit but doesn't appear to support it in the receiving part.

To Reproduce

Use dropbear dbclient to connect to OTP SSH daemon and cause the preferred_algorithms kex and public_key to not match the order of what dropbear uses.

dropbear should build easily:

$ git clone https://github.com/mkj/dropbear
$ cd dropbear
$ ./configure
$ make
$ ./dbclient -y -y user@host/port

change the order of the kex and public_key values when starting the daemon:

$ mkdir sysdir
$ ssh-keygen -t ed25519   -f sysdir/ssh_host_ed25519_key
$ erl
1> ssh:start().
2> ssh:daemon(2222, [{system_dir, "sysdir"}, {password, "pass"}, {preferred_algorithms, [ {kex, ['curve448-sha512', 'curve25519-sha256']}, {public_key,['ssh-dss', 'ssh-ed25519']} ]} ]).

If the first entry doesn't match the first guess dropbear uses, it will send another KEXDH_INIT causing the connection to terminate.

Expected behavior OTP SSH should support the key exchange guess as described in RFC4253 section 7.

Affected versions tested on OTP SSH 5.1.1 and 5.2

Additional context

The dropbear code has a define to disable this code:

/* A client should try and send an initial key exchange packet guessing
 * the algorithm that will match - saves a round trip connecting, has little
 * overhead if the guess was "wrong". */
#ifndef DROPBEAR_KEX_FIRST_FOLLOWS
#define DROPBEAR_KEX_FIRST_FOLLOWS 1
#endif

https://github.com/mkj/dropbear/blob/2674736bce847bc51a30a07c191562047659ac1f/src/sysoptions.h#L55

but this is ofcourse not a solution as one can't always control which client is used.

KarlVogel avatar Jul 18 '24 09:07 KarlVogel

Respective implemenation in openssh: https://github.com/openssh/openssh-portable/blob/7717b9e9155209916cc6b4b4b54f4e8fa578e889/kex.c#L1050

KarlVogel avatar Jul 18 '24 10:07 KarlVogel

thanks for detailed report. indeed does not seem to be supported. I will investigate it further.

u3s avatar Jul 22 '24 13:07 u3s

we plan to fix this interop issue. but this task might be scheduled for later due to other ssh work planned earlier.

u3s avatar Aug 27 '24 12:08 u3s