Converting Dropbear Keys to Use Within OpenSSH

The existing instructions for installing the openSSH server to replace the default dropbear SSH server instruct you to create entirely new keys for openSSH to use.

That can cause issues because it means that the key fingerprint of the SSH servers will be different, since the new keys do not match the original keys generated by dropbear. Many SSH clients are configured to reject changes in server key fingerprint due to security concerns about man-in-the-middle attacks. To workaround this, you could change the fingerprints within each client's known_hosts file, but in some scenarios changing that information on each computer you access the router from becomes impractical.

As an alternative, you can make it so the openSSH server uses the same keys that the dropbear SSH server originally used. However, dropbear stores the SSH keys in a special format that openSSH does not know how to understand, so it isn't as simple as moving the existing dropbear keys into the location that openSSH expects. Luckily, there is an existing Entware package, dropbearconvert, which provides a utility for converting between dropbear and openssh formatted SSH keys, and by using that utility we can preserve the dropbear keys and provide them to the openSSH server instead of generating entirely new keys.

This script downloads the dropbearconvert package and temporarily installs the dropbearconvert utility using opkg (if needed; it will use an existing installed copy if one exists). Next the script uses the utility to convert the private dropbear keys into the openSSH versions, and finally it uninstalls the dropbearconvert package (if it was not using an existing installed copy from PATH). This script also regenerates the corresponding public keys, in openSSH format, and copies the existing authorized_keys information from the dropbear location into the existing openSSH configuration. This script requires you to explicitly opt in to any key overwriting, and also generates backup files automatically to help you recover should any issues arise.

A downloadable version of the script is available as a GitHub gist. This script is written by emabrey and distributed under the terms of the GPLv2. Also, this script relies upon the dropbearconvert utility authored by Matt Johnston, and you can find the license for that utility online.

#! /bin/sh
# SPDX-License-Identifier: GPL-2.0-only
# License available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# Script written by emabrey
 
#### Configuration ####
 
DROPBEAR_DIR="/etc/dropbear";   # Path for locating existing dropbear keys
OPENSSH_DIR="/etc/ssh";         # Path for placement of converted openSSH keys
FORCE_ENABLED=false;            # Key overwrite enabled (see -f or --force)
CONVERT_PROG="dropbearconvert"  # The name of the dropbearconvert package/program
BACKUP_UUID="bfe22494-8bea-43c3-908c-59e412b89cce" #The filename UUID to use when making backup files
#### Script ####
 
if [ "$#" -gt 1 ]; then
  echo "Too many arguments, please consult --help option helptext; aborting";
  exit 1;
fi
 
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
  echo "Usage: $0 [option...]                                 ";
  echo "                                                      ";
  echo "     -f, --force   Overwrite the existing openSSH keys";
  echo "     -h, --help    Display this help message          ";
  echo "                                                      ";
  exit 0;
elif [ "$1" = "-f" ] || [ "$1" = "--force" ]; then
  FORCE_ENABLED=true;
elif [ -n "$1" ]; then
  echo "Unrecognized option; aborting";
  exit 1;
fi
 
if ! [ -e "$DROPBEAR_DIR" ] || ! [ -d "$DROPBEAR_DIR" ]; then
  echo "Configured dropbear directory is not a valid directory; aborting";
  exit 1;
fi;
 
if ! [ -e "$OPENSSH_DIR" ] || ! [ -d "$OPENSSH_DIR" ]; then
  echo "Configured openSSH directory is not a valid directory; aborting";
  exit 1;
fi;
 
for program in "echo" "cp" "rm"; do
  if ! command -v $program >/dev/null 2>&1; then
    printf "%s\n" "Missing $program, which is required; aborting;"
    exit 1;
  fi;
done;
 
echo "The dropbear to openSSH key conversion is about to start...";
 
if [ "$FORCE_ENABLED" = "true" ]; then
  echo "WARNING: SSH key overwriting is enabled; press Ctrl-C if unintentional";
fi;
 
# Give user time to abort if they accidentally ran the program
# overwriting SSH keys accidentally could be a catastrophic issue
# so the script is trying to give you one last chance to change your mind
# if you've made a mistake
echo "5.." && sleep 1;
echo "4.." && sleep 1;
echo "3.." && sleep 1;
echo "2.." && sleep 1;
echo "1.." && sleep 1;
 
echo "---"
# Detect existing dropbear key converter, or temporarily install it
if ! command -v "$CONVERT_PROG" >/dev/null 2>&1; then
  # Check for entware installer
  if ! command -v "opkg" >/dev/null 2>&1; then
    echo "Unable to proceed; $CONVERT_PROG utility is not available";
    echo "Try manually installing the $CONVERT_PROG program to PATH first";
    exit 1;
  fi
 
  echo "Updating entware repository database" && opkg update >/dev/null 2>&1;
  echo "Temporarily installing $CONVERT_PROG utility..." && opkg install "$CONVERT_PROG" >/dev/null 2>&1; 
  hash -r;
  REMOVEDC=true;
 
  # Verify that the installation succeeded 
  if ! command -v "$CONVERT_PROG" >/dev/null 2>&1; then
    echo "The temporary installation failed; aborting"
    exit 1;
  fi
 
else
  echo "Pre-existing $CONVERT_PROG installation detected"
  REMOVEDC=false
fi;
 
echo "---"
KEYCOUNT=0 # Counts up for each conversion
 
for keytype in "rsa" "ed25519"; do
  DROPBEAR_KEY="${DROPBEAR_DIR}/dropbear_${keytype}_host_key" # dropbear input
  OPENSSH_KEY="${OPENSSH_DIR}/ssh_host_${keytype}_key"        # openSSH output
 
  KEY_PRIVATE="$OPENSSH_KEY"
  KEY_PUBLIC="${OPENSSH_KEY}.pub"
 
  echo "Attempting to convert dropbear $keytype keys to openSSH format...";
 
  # If there are existing keys, check if force is enabled and backup and remove
  # the existing files if that option is enabled
  for existing_keyfile in "$KEY_PRIVATE" "$KEY_PUBLIC"; do
    if [ -e "$existing_keyfile" ] && [ -f "$existing_keyfile" ]; then
	  if [ "$FORCE_ENABLED"  = "true" ]; then
	    echo "  - openSSH $keytype keys have been detected; making backup and overwriting"
        # Make a backup and remove original private key
        cp "$existing_keyfile" "${existing_keyfile}.${BACKUP_UUID}.bak";
        rm "$existing_keyfile";
	  fi;
    fi;
  done;
 
  if [ -e "$KEY_PRIVATE" ] || [ -e "$KEY_PUBLIC" ]; then
	echo "  - Existing openSSH $keytype keys have been detected; key type skipped"
	echo "  - To forcibly overwrite the keys, run using the -f (--force) option"
  elif [ -e "$DROPBEAR_KEY" ] && [ -f "$DROPBEAR_KEY" ]; then
    # generate converted private key
    echo "Converting dropbear $keytype private key into private openSSH key..."
    "$CONVERT_PROG" dropbear openssh "$DROPBEAR_KEY" "$KEY_PRIVATE" >/dev/null 2>&1;
    KEYCOUNT=$((KEYCOUNT+1))
 
    # Now try to generate converted public key
    if command -v "ssh-keygen" >/dev/null 2>&1; then
      echo "Converting openssh $keytype private key into public openSSH key..."
      ssh-keygen -y -f  "$KEY_PRIVATE" -y > "$KEY_PUBLIC";
    else
      echo "Skipping public key conversion because ssh-keygen is not available";
    fi;
  else
    echo "Unable to find dropbear $keytype key; skipping conversion"
  fi;
done;
 
echo "---"
# If we temporarily installed the converter, remove it
if command -v "$CONVERT_PROG" >/dev/null 2>&1 && [ "$REMOVEDC" ]; then
  echo "Removing $CONVERT_PROG utility..." && opkg remove "$CONVERT_PROG" >/dev/null 2>&1;
  hash -r
  # Make sure the removal was completed
  if command -v "$CONVERT_PROG" >/dev/null 2>&1; then
    echo "Removal of the $CONVERT_PROG utility may have experienced an error"
    echo "A manual execution of \`opkg remove $CONVERT_PROG\` may be required"
  fi;
else
  echo "Pre-existing $CONVERT_PROG installation detected; skipping uninstall"
fi
 
echo "---"
if [ -e "$DROPBEAR_DIR/authorized_keys" ] && command -v "sort" >/dev/null 2>&1; then
  echo "Copying dropbear authorized keys to openSSH authorized keys file...";
 
  AUTH_KEY_FILE="${OPENSSH_DIR}/authorized_keys"
 
  if ! [ -d "$AUTH_KEY_FILE" ]; then
    if ! [ -e "$AUTH_KEY_FILE" ]; then
      touch "$AUTH_KEY_FILE";
    else
      # Make a backup of the original authorized keys file just in case
      # Uses a UUID to eliminate chance of collision in POSIX compliant way
      cp "$AUTH_KEY_FILE" "${OPENSSH_DIR}/authorized_keys.${BACKUP_UUID}.bak"
    fi;
 
    sort -u "$DROPBEAR_DIR/authorized_keys" "$AUTH_KEY_FILE" -o "$AUTH_KEY_FILE";
  fi
fi;
 
echo "---"
echo "There were $KEYCOUNT private keys converted during this script execution";
echo "The dropbear to openSSH key conversion is now complete!"

Advice on Running Script

This script requires permissions that allow it to access both the system-level directories for the dropbear and openSSH servers, and in most setups that means you need to run this script as the root user.

When running the script, it will only generate converted openSSH keys if there are not already existing openSSH keys in the relevant default key-file locations. If you have just installed the openSSH server (or if you recently ran the sshd service for the first time), it is likely that those key-files are the auto-generated keys, and are safe to overwrite. To allow the script to overwrite existing keys, simply pass in the -f or --force option when running the script. If overwriting is enabled, the script will generate backup files ending in the *.bak extension containing each overwritten key.

Please note that even if the key-file overwriting is not enabled, the script always overwrites the existing authorized_keys file in a safe manner by combining the unique keys from the existing dropbear and openSSH authorized_keys files. However, to ensure that no data is lost, this safe operation still generates a backup file for the authorized_keys file as well. This backup file, and the key backup files (if enabled), will be created within the same directory the output openSSH keys are being written to.

The script is compatible with an existing installation of the dropboxconvert program on the PATH, and will use your existing installation without modifying it when present. However, if the script automatically does a temporary install of the dropboxconvert package, it will make an attempt to automatically uninstall it at the end of the script run. If it fails to remove the temporary installation of the program, it will print a message saying that a manual removal command is likely needed. To manually remove the dropboxconvert program from your device, simply execute opkg remove dropboxconvert from a root shell.

Below is a basic sshd configuration file. You can use this as your configuration file by first replacing the default one located at etc/ssh/sshd_config and secondly restarting the sshd service service restart sshd (but finish reading this article before doing so).

This configuration file loads both the openSSH and dropbear authorized_keys files (which enables you to continue to add keys for openSSH via the LuCI interface), disables insecure SHA-1 based KEX (Key EXchange) as well as providing a workaround for an existing bug in OpenSSH for Windows v9.5p1. This configuration also makes the sshd daemon listen on 0.0.0.0:22 and [::1]:22], and uses the openSSH keys located in /etc/ssh/ssh_host_rsa_key and /etc/ssh/ssh_host_ed25519_key (which you should have generated with the script above so that they match the keys from your dropbear server).

Finally, the last part of this configuration enables SSH compression, enables TCP keepalive to ensure the connection does not drop, enables DNS lookups for ssh server hostnames, and ensures that your SSH traffic uses a custom DSCP class (af41, where 4 is the highest priority and 1 is the highest availability - read more on DSCP here).

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.
 
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
 
Include /etc/ssh/sshd_config.d/*.conf
 
Port 22
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
 
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
AuthorizedKeysFile .ssh/authorized_keys /etc/dropbear/authorized_keys
KexAlgorithms -diffie-hellman-group1-sha1,-diffie-hellman-group-exchange-sha1,-sntrup761x25519-sha512@openssh.com
PermitRootLogin prohibit-password
MaxAuthTries 3
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
 
Compression yes
IPQoS af41
TCPKeepAlive yes
UseDNS yes
 
# override default of no subsystems
Subsystem	sftp	/usr/lib/sftp-server

Safely Setting up openSSH for Public Key Authentication

This configuration will ONLY allow root login via public keys, so ensure that your ssh fingerprint is loaded within /etc/ssh/authorized_keys or /etc/dropbear/authorized_keys before disabling dropbear. Failure to verify that you have a public key added to the openSSH server WILL leave you locked out of SSH and unable to access your SSH server on port 22. If you are somehow locked out, quickly re-enable the dropbear service using LuCI and log back into the dropbear SSH server on port 2222 to fix the incorrectly configured openSSH server (ssh <router_ip> -p 2222). It is STRONGLY advised that you start a SSH session on the dropbear server (on port 2222) before switching to openSSH and disabling the dropbear service (service dropbear disable && service dropbear stop). So long as you have the session already open, stopping the dropbear service will not end your SSH session; this allows you to stop the dropbear service, restart the openSSH service with the new configuration, and verify that you are able to login to the new openSSH server all without losing access to your OpenWRT device over SSH. Once you have verified you have public key access to openSSH on port 22, you can safely end your leftover dropbear SSH session and the transfer is complete.

So the safe order of events is:

  1. Install the openSSH server (opkg install openssh-server)
  2. Run the conversion shell script to generate the openSSH keys from the dropbear keys (convert_key.sh)
  3. Move dropbear to port 2222 and restart it (uci set dropbear.@dropbear[0].Port=2222 && uci commit dropbear && service dropbear restart)
  4. Start an SSH session from another device using the dropbear server on port 2222 (ssh <server_ip> -p 2222)
  5. Using that SSH session, copy the provided sshd settings into the file at etc/ssh/sshd_config, replacing its contents
  6. Restart the openSSH server to start using the new configuration file's settings (service sshd restart)
  7. Verify that you can access the openSSH server using only public key authentication (ssh <server_ip> -p 22)
  8. Once you have verified the ability to access the openSSH server, disable the dropbear server on port 2222 (service dropbear disable && service dropbear stop)
  9. Double and/or triple check that the openSSH server is definitely accessible using public key authentication, and once you are sure, close the dropbear SSH session you started in step 4.
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2025/12/29 00:15
  • by emabrey