Raspberry Pi - SSH Hardening

Introduction: Raspberry Pi - SSH Hardening

The purpose of this Instructable is to harden SSH access to your remote client/server. This is accomplished by:

  • Dropping weak and/or tainted key algorithms (re: Anything with "DSA" in the name) in favor of 4096-bit RSA keys or Ed25519.
  • Prevent CVE-2016-0777 exploitation.
  • Enforcing forward secrecy on the key exchange.
  • Disable the use of weak and broken ciphers.
  • Sane settings related to message authentication codes.

Side note: I'm using Debian Jessie

Step 1: Make Sure You Have Strong SSH Keys

If you are using weak crypto keys for your SSH key authentication, then delete them! No DSA, or ECDSA! Only RSA 4096 or Ed25519 keys should be used!

To generate strong keys make sure you have sufficient entropy generated on your computer (stream a HD YouTube/Netflix video if you have to).

Now in your terminal shell (on your computer) run one of the following commands:

For RSA 4096 bit keys:

ssh-keygen -b 4096

For Ed25519 keys:

ssh-keygen -t ed25519 -o -a 100

When prompted for a passphrase, choose something that will be hard to guess if you have the security of your private key in mind. A longer, more random password will generally be stronger and harder to crack should it fall into the wrong hands.

On a mac, open a finder window and then go to "go" and "go to folder..." and enter:


to be taken to your new key pair.

Step 2: Copy SSH Key to Raspberry Pi

Now in your .ssh folder on your computer your going to want to open your public key file (.pub) and copy the contents to move to your remote machine.

Now in terminal lets go to your authorized host file.

sudo nano ~/.ssh/authorized_keys

Now paste your public key in the file and save and close the file.

Step 3: Harden Ssh_config

First we need to open the ssh_config file.

sudo nano /etc/ssh/ssh_config

Now we're going to replace everything in the file with the hardened version (The hardened version disables weak crypto algorithms, hashes, and authentication) .

# This is the ssh client system-wide configuration file. See # ssh_config(5) for more information.  This file provides defaults for
# users, and the values can be changed in per-user configuration files
# or on the command line. 
# Configuration data is parsed as follows:
#  1. command line options
#  2. user-specific file
#  3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end. 
# Site-specific key exchange algorithms. This is here so that if you're 
# having trouble logging into a server, you can modify and uncomment the
# lines below and be on the way to getting work done.

# Host github.com *.github.com
#     KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1

# Site-wide defaults for some commonly used options.  For a comprehensive
# list of available options, their meanings and defaults, please see the
# ssh_config(5) man page.

Host *
#   ForwardAgent no
#   ForwardX11 no
#   ForwardX11Trusted yes
#   RhostsRSAAuthentication no
#   RSAAuthentication yes
#   HostbasedAuthentication no
#   GSSAPIAuthentication no
#   GSSAPIDelegateCredentials no
#   GSSAPIKeyExchange no
#   GSSAPITrustDNS no
#   BatchMode no
#   CheckHostIP yes
#   AddressFamily any
#   ConnectTimeout 0
#   StrictHostKeyChecking ask
#   IdentityFile ~/.ssh/identity
#   IdentityFile ~/.ssh/id_rsa
#   IdentityFile ~/.ssh/id_dsa
#   Port 22
#   Protocol 2,1
#   Cipher 3des
#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
#   EscapeChar ~
#   Tunnel no
#   TunnelDevice any:any
#   PermitLocalCommand no
#   VisualHostKey no
#   ProxyCommand ssh -q -W %h:%p gateway.example.com
#   RekeyLimit 1G 1h
    UseRoaming no
    SendEnv LANG LC_*
    HashKnownHosts yes
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials no
    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    PubkeyAuthentication yes
    HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-ed25519,ssh-rsa
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr    
    MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com

Step 4: Disable Root Login

Disable Root Login Via SSH.

sudo nano /etc/ssh/sshd_config

Now just copy the code below and replace what is in your sshd_config file with it.

# Package generated configuration file # See the sshd_config(5) manpage for details
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
Protocol 2
# HostKeys for protocol version 2
Hostkey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes # Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024 # Logging
SyslogFacility AUTH
LogLevel INFO # Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys # Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes # To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no # Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no # Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes # Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes # GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no #MaxStartups 10:30:60
#Banner /etc/issue.net # Allow client to pass locale environment variables
AcceptEnv LANG LC_*Subsystem sftp /usr/lib/openssh/sftp-server

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM yes

Step 5: Happy Dance

I'd like to credit:


Raspberry Pi Contest 2016

Participated in the
Raspberry Pi Contest 2016

Be the First to Share


    • Potato Speed Challenge

      Potato Speed Challenge
    • Bikes Challenge

      Bikes Challenge
    • Remix Contest

      Remix Contest

    3 Discussions


    1 year ago

    For the sshd_config file, I think you want to fix this line...

    #PasswordAuthentication yes # Kerberos options

    ...for two reasons. First, it looks like "# Kerberos options" should be on a second line.
    Second, PasswordAuthentication defaults to 'yes' and you probably want it to be 'no' so that only the key file method can be used to log in. So then...

    PasswordAuthentication no
    # Kerberos options



    Step 1 is nice and clear but then you have become very unclear. May I suggest that you:
    a: say how you got the new public key to the RPI
    2: note when you are actually on the RPI and not on the Mac
    III: consider that some folks might have changed the ssh port from 22

    In summary, great idea, you know what you mean. Best to write it for your audience and not you.
    I suggest it is worth noting why the RPi server has the public key as, for the uninitiated, it may seem to be the wrong way round.
    Thanks, C


    4 years ago

    Correction for step one, the locally generated key pair shows up in the same directory as known_hosts, but is not appended into the file (which is generally keys collected from remote hosts). Filename is (for ED25519) id_ed25519 and id_ed25519.pub for the private/public pair, similar for rsa: id_rsa id_rsa.pub