sshd hardening

Server configuration and security settings (sources : ANSSI, 1, 2)

In the configuration file :

Use SSH protocol version 2 only (version 1 has flaws allowing MitM attacks) :
Protocol 2
Deny root login :
PermitRootLogin no
Disable password authentication (source) :
Disable port forwarding (unless this is explicitly required, by X2Go, for instance ) :
AllowTcpForwarding no
Disable X11 forwarding (which could allow : key logging, sending signals to applications, redirecting display) :
X11Forwarding no
ForwardX11Trusted no
Define ACL (or consider PAM) :
  • whitelist users : AllowUsers kevin stuart bob
  • whitelist users and the client IP address : AllowUsers admin@192.168.17/24
  • whitelist groups / IP addresses : AllowGroups developers wheel@192.168.17/24
  • blacklist users : DenyUsers root alice foo
  • blacklist groups : DenyGroups others
  • To explicitly blacklist all the existing local users (except kevin, stuart and bob), you can quickly generate the list with :
    cut -d: -f1 /etc/passwd | grep -Ev 'kevin|stuart|bob' | tr '\n' ' '
Check directories / key files permissions of the user side before opening a session :
StrictModes yes
Automatically logout idle users after n seconds of inactivity :
ClientAliveInterval n
ClientAliveCountMax 0
Ignore ~/.rhosts and ~/.shosts files (if they exist) :
IgnoreRhosts yes
Disable host-based authentication :
HostbasedAuthentication no
Disable empty passwords :
PermitEmptyPasswords no
Login restrictions :
MaxAuthTries 2
LoginGraceTime 30
Some extra directives for ssh_config and sshd_config :
Ciphers aes256-ctr, aes192-ctr, aes128-ctr
# Pour les versions 6.3+, OpenSSH supporte le ETM (encrypt-then-mac),
# plus sûr que les anciennes implémentations (mac-then-encrypt)

# S'il s'agit d'une ancienne version, utilisez uniquement "hmac-sha1"
MACs hmac-sha2-512, hmac-sha2-256, hmac-sha1
By default sshd listens on all available interfaces and IP addresses on the system. You can limit this with :
Port 443
Or :
Disable compression (source) :
Compression no

Filter sshd port (defaults to TCP 22) (See NetFilter) :

iptables -I INPUT -s -m state --state NEW -p tcp --dport 22 -j ACCEPT

Rate-limit incoming connections :

iptables -I INPUT -p tcp --dport $sshPort -i $interface -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport $sshPort -i $interface -m state --state NEW -m recent --update --seconds 60 --hitcount 5 -j DROP
Or consider fail2ban to block brute force attacks (if you don't mind it eating your CPU...).

Use TCP Wrappers :

It's a host-based networking ACL system, used to filter network access to Internet.
Edit /etc/hosts.allow to allow SSH only from and :
sshd :

Last but not least :

  • analyze logs (logwatch, logcheck)
  • keep software up-to-date (apt upgrade, ...)

SSH keys types

Key type Length [bits] Comment
min. default max.
DSA exactly 1024 Deprecated since OpenSSH 7.0, should not be used anymore (source, details)
ECDSA ssh-keygen -b determines the key length by selecting from one of three elliptic curve sizes: 256, 384 or 521 bits. All other values will fail.
  • Is ECDSA obsolete/deprecated?
  • key strength depends on the actual randomness of the number generator
  • The 521 bits elliptic curve size is not a typo, it's _really_ 521 (not 512 as I thought , details)
Ed25519 keys have a fixed length and ssh-keygen -b flag will be ignored
  • probably the strongest mathematically (and also the fastest), but not yet widely supported
  • stronger encryption (password-protection) of the private key by default than other key types
RSA 1024 2048
  • Generally, 2048 bits is considered sufficient.
  • The best bet if you can't use Ed25519.

  • If you need more security than RSA-2048 offers, the way to go would be to switch to elliptic curve cryptography — not to continue using RSA. (source)
  • If supported, ECDSA should be used instead of RSA.
  • Virtual machines and machines having a short uptime have not enough entropy to benefit from cryptographically-acceptable randomness and generate strong keys.

How can I assign several names / aliases to an SSH host ?

There are situations —like working with Ansible— where naming hosts is paramount so that everything is organized, readable and explicit. This implies the whole team settles on a naming convention.

Alas, for the vision of one man lends not its wings to another man., the team members sometimes can't agree on such a convention, ending with :

However, nobody has to resign to having to use such poor names.

File Single naming convention Multiple naming conventions
Ansible inventory file
Common to all team members, usually shared via Git.
apache	ansible_host=platformA_apache
mysql	ansible_host=platformA_mysql
apache	ansible_host=xyzABC_123-j_054
mysql	ansible_host=xyzABC_123-j_012
Not shared with the team
Host platformA_*
	User kevin
	ProxyCommand ssh bastion -W %h:%p
	IdentityFile ~/.ssh/myPrivateKey
	AddKeysToAgent yes
	StrictHostKeyChecking no

Host platformA_apache

Host platformA_mysql
Host platformA_* xyzABC_123-j_*
	User kevin
	ProxyCommand ssh bastion -W %h:%p
	IdentityFile ~/.ssh/myPrivateKey
	AddKeysToAgent yes
	StrictHostKeyChecking no

Host platformA_apache xyzABC_123-j_054

Host platformA_mysql xyzABC_123-j_012


The known_hosts file exists in 2 flavors : Both contain public host keys for all known hosts.

known_hosts format (source) :

  • Entries are space-separated.
  • Lines starting with # and empty lines are considered as comments and ignored
Fields :
  1. markers : one of @cert-authority or @revoked
  2. hostnames :
    • comma-separated list of patterns, including wildcards ? or *, negation !, or stuff like : [hostname]:nonStandardPortNumber
    • lines starting with a | : 1 hashed host name only, no wildcards
  3. keyType : taken directly from the host key
  4. base64-encoded key : taken directly from the host key
  5. comment : for humans only, field ignored

How to open an SSH connection through an HTTP Proxy with authentication ?

SSH is not able to use a proxy in order to access external computers.

To do so, you'll need an extra application to tunnel TCP connections through an HTTP Proxy supporting the CONNECT method : here comes corkscrew.

  1. setup :
    apt install corkscrew
  2. configure corkscrew :
    echo 'proxyUser:proxyPassword' > ~/.corkscrew
    Looks like corkscrew prefers when passwords (including special characters) are not urlencoded.
  3. for privacy of your credentials :
    chmod 600 ~/.corkscrew
  4. configure SSH client by adding to ~/.ssh/config :
    Host sshServer
    	User stuart
    	IdentityFile ~/.ssh/myPrivateKey
    	ProxyCommand corkscrew proxy.myCompany.tld proxyPort %h %p ~/.corkscrew
  5. connect to sshServer :
    ssh sshServer

Alternate solution :

  • not tested (yet!)
  • works when otherProxy.mycompany.tld asks no authentication
Host sshServer
	User stuart
	IdentityFile ~/.ssh/myPrivateKey
	ProxyCommand connect-proxy -H http://otherProxy.mycompany.tld:proxyPort %h %p
	ServerAliveInterval 120	
See : source, man page

How to avoid recording the host key into the known hosts list (~/.ssh/known_hosts) ?

Situation :

When connecting to a new host, SSH adds its host key to its local known hosts list : ~/.ssh/known_hosts. The next time a connection is being open towards this host, SSH will compare its known key with the key advertised by the host it's currently connecting to :

Details :

The behavior described above is normal and expected : a host key is not supposed to change.
However, when experimenting with containers or virtual machines, it's pretty usual to build + use + destroy + re-build "hosts", and in such circumstances, SSH will send repeated warnings about hosts that have changed —which we are aware of and is not a security issue in this context.

Solution :

Add this to ~/.ssh/config :
Host 172.17.*
	StrictHostKeyChecking no
	UserKnownHostsFile /dev/null
	LogLevel QUIET

How can an SSH connection succeed / fail intermittently with no error message despite verbose mode ?

Situation :

Details :

Looks like you've done nothing wrong. The problem must be :

Solution :

There are chances you actually shot your own foot with hardened security rules like this .

How to mount / umount a SFTP directory ?

  • SFTP != FTPS
  • SFTP is what you do while using scp (and also WinSCP or FileZilla — in their respective SFTP modes (i.e. SSH-based file transfer), since they support other protocols as well).

For a quick / one-time use, consider using the SFTP client built in many file managers (Caja has one) by opening :

mount, umount and CLI access :

Setup :

on sshServer :
provided sshd is up and running, there's nothing more to do
on sshClient :
apt install sshfs

mount :

  • As a non-root user
  • Should you need to map UID/GID between sshServer and sshClient, have a look at -o idmap=TYPE
interactively or with SSH keys
sshfs stuart@sshServer:/path/to/remote/directory /mount/point
password-based authentication (this solution is _a little_ dirty )
echo password | sshfs -o password_stdin stuart@sshServer:/path/to/remote/directory /mount/point

umount :

As a non-root user :
fusermount -u /mount/point

Save keystrokes with an extra /etc/fstab entry :

stuart@sshServer:/path/to/remote/directory /mount/point	fuse.sshfs	noauto,user,default_permissions,uid=1000,gid=1000,noatime	0	0
  • You'll be able to mount the remote filesystem as usual :
    mount /mount/point
  • But umount requires sudo privileges :
    umount /mount/point
    umount: /mount/point: Permission denied
    This is because sshfs uses FUSE instead of the regular mount command (+ elevated privileges). As a result, you'll have to use the FUSE "umount command" (source) :
    fusermount -u /mount/point
When experimenting mount options, you may end up receiving errors such as :
read: Connection reset by peer
In such situation, add the debug and sshfs_debug options to increase verbosity (source).

Alternate solution : use this _VERY BASIC_ script :

#!/usr/bin/env bash

sshServer='mySshServer'	# full details in ~/.ssh/config

case "$1" in
		mount | grep -q "$mountPoint" && { echo 'Already mounted'; exit 1; } || sshfs -o idmap=user "$sshServer":"$sshRemoteDir" "$mountPoint"
		mount | grep -q "$mountPoint" || { echo 'Not mounted'; exit 1; } && fusermount -u "$mountPoint"
		echo 'wut?'
		exit 1

Improve network throughput :

Your may experience poor transfer speed with sshfs, and search engines will surely take you to pages suggesting to use the arcfour cipher type. However, arcfour is now considered unsafe and is disabled by default since OpenSSH 6.7 (2014-10-06) and not supported anymore since OpenSSH 7.6 (2017-10-03).
command-line line 0: Bad SSH2 cipher spec 'arcfour'.
	==> has been disabled by default in recent versions of SSH.
man -P 'less -p encryption' ssh_config

man -P 'less -p ciphers' ssh_config

How to automate password-based SSH logins ?

Situation :

Details :

For reasons unrelated to the current article, I also have inter-operability constraints between GNU/Linux and Windows, and when saying KeePass, I mean : which both can handle .kbdx files.

Solution :

The idea is to :

  1. chain SSH logins from a single command-line (source) :
    ssh -At hopLogin@hop ssh -A targetLogin@target
  2. store hosts + credentials in KeePass, avoiding repeating stuff thanks to field references
  3. let KeePass build and auto-type the full SSH connection command, based on a template like :

    ssh -At {REF:U@I:C03D4B434F400B4C843F682A994B0A02}@{REF:A@I:C03D4B434F400B4C843F682A994B0A02}{ENTER}{DELAY 100}{REF:P@I:C03D4B434F400B4C843F682A994B0A02}{ENTER}ssh -At {USERNAME}@{URL}{ENTER}{DELAY 100}{PASSWORD}

    {whatever} placeholders will be replaced by the value of the named variable or key or action :
    • USERNAME : username of the current entry
    • REF:U@I:C03D4B434F400B4C843F682A994B0A02 : reference to the value of another entry (details)
    • ENTER :
    • ...

Let KeePass auto-type the SSH connection command :

  1. open the KeePass vault and select the entry you'd like to auto-type
  2. give the focus to the window that will receive the simulated keystrokes
  3. give the focus back to KeePass and hit Ctrl-v to fire Perform Auto-Type
  4. if this fails complaining The 'xdotool' utility/package is required for auto-type.
  5. see the magic happen
  • During setup / tests, you may send simulated keystrokes to a text editor to see the generated SSH connection command and debug the auto-type template. Keep in mind your passwords will be echo'ed to screen.
  • Don't forget to connect manually to each SSH server (gateways + targets), since you'll be prompted to accept the SSH host keys.
don't mix sshpass and "auto-type" !
You may have landed here after having automated (or tried to) password-based SSH logins with sshpass. Your process may have lines such as :
sshpass -p 'password' ssh kevin@sshServer
If you plan to use any kind of "auto-type" feature, do NOT use it to generate SSH connection commands including sshpass, otherwise you will : Actually, you don't even need sshpass anymore since the "auto-type" feature will "type" the password for you (for interactive logins only, I'm afraid ). As for KeePass, you'll end with auto-type sequences like :

The 'xdotool' utility/package is required for auto-type.

apt install xdotool


Setup :

apt install openssh-client

Starting ssh-agent :

  • Was it automatically started at login :
    ps aux | grep [s]sh-agent
    bob      982  0.0  0.0  11088   328 ?        Ss   Oct08   0:00 /usr/bin/ssh-agent startxfce4
  • env | grep SSH_
    check the agent is running :
    	echo $SSH_AUTH_SOCK
    	/!\ not '$SSH_AGENT_SOCK' as said in the doc

Manage private keys :

  • add a private key :
    ssh-add ~/.ssh/myPrivateKey
  • list known keys :
    ssh-add -l
    2048 SHA256:cMdVUp8pTJGbLYS6Ngrl5odnFYGhoBXGY1p8pTJGbLTk+drlkgE /home/kevin/.ssh/myPrivateKey (RSA)
  • delete all keys :
    ssh-add -D
Looks like under some conditions, ssh-agent forgets keys after a reboot (don't know whether this is context-specific or the default behavior. Details). Anyway, to permanently add keys to the agent, no need for
ssh-add myKey
in ~/.bashrc. Instead, use AddKeysToAgent.
run the agent manually (should not be necessary) :
	eval `ssh-agent`

kill the agent :
	ssh-agent -k

How to revoke a host key from SSH's ~/.ssh/known_hosts file ?

ssh-keygen -R
# Host found: line 124
/home/kevin/.ssh/known_hosts updated.
Original contents retained as /home/kevin/.ssh/known_hosts.old

How to hide the connection banner ?

Situation :

Displaying a connection banner is fine when manually opening a connection to a server, but it's getting ugly / awkward when :

Solution :

From light to heavy weaponry :
Use SSH client's quiet mode :
ssh -q host command
Decrease verbosity :
ssh -o LogLevel=QUIET host command
Explicitly filter the unwanted banner :
ssh -q host command 2>&1 | sed -r '/banner/d'
This banner shouldn't be there, actually :
  • When you run ssh user@computer command, command is run non-interactively (source)
  • and there's no point in printing a connection banner to non-interactive shells (source)
  • so this should NOT receive a banner ()

How to hop through a SSH host ?

Situation :

Considering : it is possible to open an SSH session from workstation directly to sshTarget. To do so :

Solution :

  1. On workstation, add to ~/.ssh/config :
    Host sshTarget
    	User stuart
    	ProxyCommand ssh %r@sshHop -W %h:%p
  2. then, from workstation : ssh sshTarget
The Host directive accepts wildcards to fit various scenarios :
Host *

Host *

SSH client configuration

Configuration files :

system-wide settings
personal user configuration
local cache of host (i.e. server) keys
list of public keys that will be accepted for key-based logins
Usage of ~/.ssh/authorized_keys2 for SSH protocol 2 is deprecated since 2001 (sources : 1, 2).

Configuration directives :

Flag Default Usage
BindInterface Use the address of the specified interface on the local machine as the source address of the connection
This feature was introduced by OpenSSH 7.7. As of June 2019, it must be installed —on Debian Stretch— via the testing repository (details, sources : 1, 2).
ControlMaster Share multiple sessions over a single network connection. Values :
  • no : default
  • yes : enable multiplexed connections by re-using a master connection. Connect normally (i.e. open a new connection) if using the master connection fails.
  • ask : as above + requires confirmation via ssh-askpass
  • auto : use master connection, create it if missing
  • autoask : as above + ask confirmation like the ask option
ControlPersist Used with ControlMaster to specify how the master connection should remain open in the background :
  • no (default) : do not leave the master connection open in the background (waiting for future client connections) and close it as soon as the initial client connection is closed
  • yes or 0 : leave the master connection open in the background forever (or until closed explicitly)
  • ns : the master connection stays open in the background up to n seconds of inactivity
HashKnownHosts no hash host names and addresses when they are added to ~/.ssh/known_hosts so that they do not visually reveal identifying information if the file's contents are disclosed.
Include someFile
  • include the specified configuration file(s)
  • multiple pathnames may be specified and each pathname may contain wildcards (such as ~)
  • files without absolute paths are assumed to be in :
    • ~/.ssh if included in a user configuration file
    • /etc/ssh if included from the system configuration file
    For this reason, Included configuration files related to SSHFS mounts declared in /etc/fstab should have an absolute path.
  • Include may appear inside a Match or Host block to perform conditional inclusion
LogLevel LEVEL (explicit)
ProxyCommand Specifies the command to use to connect to the server, typically when there is an intermediate hop between the SSH client and server (examples : 1, 2, 3)
man -P 'less -p "^ +ProxyCommand$"' 5 ssh_config
man -P 'less -p ^TOKENS' 5 ssh_config
ProxyJump Specify one or more jump proxies :
  • syntax :
  • ProxyJump is intended as an equivalent (replacement?) for ProxyCommand, with a simpler syntax (details and examples).
  • Multiple proxies may be separated by comma characters and will be visited sequentially.
  • SSH will connect to the target host by first making a ssh connection to the specified jump host and then establishing a TCP forwarding to the ultimate target from there.
  • ProxyJump competes with ProxyCommand : whichever is specified 1st wins.
  • configuration for the destination host (either supplied via the command-line or the configuration file) is not generally applied to jump hosts. ~/.ssh/config should be used if specific configuration is required for jump hosts.
  • ProxyJump came with OpenSSH 7.3 (2016-08-01). It is absolutely stunning that so many hosts are not up-to-date and still lack this feature today .
OpenSSH/Cookbook/Proxies and Jump Hosts
ServerAliveInterval n send keepalive messages every n seconds when the connection is idle (details). Defaults to 0 (i.e. disabled).
  • yes :
    • never automatically add host keys to ~/.ssh/known_hosts
    • refuse to connect to hosts whose host key has changed
    • provide maximum protection against man-in-the-middle (MITM) attacks, though it can be annoying when /etc/ssh/ssh_known_hosts is poorly maintained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts.
  • accept-new :
    • automatically add new host keys to ~/.ssh/known_hosts
    • refuse to connect to hosts whose host key has changed
  • no or off :
    • automatically add new host keys to ~/.ssh/known_hosts
    • allow connections to hosts whose host key has changed (some restrictions, though)
  • ask (default) :
    • prompt the user before adding new host keys to ~/.ssh/known_hosts
    • refuse to connect to hosts whose host key has changed

Example :

A mashup of useful options :

Host HAL		this can be an alias, an IP address, a negated expression or a pattern (trick about patterns lists)

	HostName realHostname		if you specified an alias above
	Port 443				Port to connect to on the remote host. Defaults to 22
	User DrEinsteinVonBrainstorm
	IdentityFile ~/.ssh/myPrivateKey

	ProxyCommand ssh -e none hop exec nc -w 5 %h %p		Go through hop host. If hop is an HTTP proxy, read this.

	AddKeysToAgent yes			details
	ForwardAgent yes
Patterns lists are comma-separated (,), but when they apply to the Host directive, they are whitespace-separated.

My basic default configuration :

Host *				this is a valid statement (details : 1, 2)
	ServerAliveInterval 120	Keep SSH sessions alive
	LogLevel QUIET		hide the connection banner
If SSH ignores your ~/.ssh/config file, be more explicit with -F.

SSH : how to authentify using a public/private key pair ?

Generate keys :

On Linux :

  • generates a private (keyName) + public ( key pair at the OpenSSH format. If not specified, keyName defaults to ~/.ssh/id_rsa
  • the type of key to generate can be specified with -t type (defaults to rsa for SSH protocol version 2).

generate a 2048-bit RSA key pair (~/.ssh/id_rsa + ~/.ssh/
ssh-keygen -t rsa
generate a 256-bit ECDSA key pair (~/.ssh/id_ecdsa + ~/.ssh/
ssh-keygen -t ecdsa -b 256
generate a fixed-length Ed25519 key pair (~/.ssh/id_ed25519 + ~/.ssh/
ssh-keygen -t ed25519
ssh-keygen -t ed25519 -a 100

On Windows, for PuTTY :

You'll need PuTTYgen and this procedure to generate a private (keyName.ppk) + public ( key pair at the PuTTY format.

The public key is a text file such as :

Comment: "this-is-my-key"
It contains a header line + a comment + the public key itself + a footer. You can convert it into the OpenSSH format :
  • with the dedicated utility
  • or manually, by editing it so that it looks like on a single line :
    ssh-rsa public key comment (usually the owner ID)

Copy the public key to a SSH server (source)

  1. ssh-copy-id -i ~/.ssh/ stuart@sshServer
    This should automatically populate the ~/.ssh/authorized_keys file on the SSH server (read about some required chmod's)
  2. Configure PuTTY accordingly.

Installing the key on an SSH server for the impatients :

As these commands use the ~ wildcard, run them as the user owning the ~ directory.

  1. On the SSH server side : mkdir ~/.ssh; touch ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys
  2. On the SSH client side : cat ~/.ssh/ | ssh kevin@myServer "cat - >> ~/.ssh/authorized_keys"

Log in using the key :

  1. ssh kevin@myServer -i ~/.ssh/id_rsa
  2. which can be aliased :
    echo "alias ssh='ssh -i ~/.ssh/id_rsa'" >> ~/.bashrc && source ~/.bashrc
  3. then :
    ssh kevin@myServer

sshd configuration

sshd supports SSH1 and SSH2 protocols, but SSH1 is not secure, so it mustn't be used !

Existing connections can survive sshd restart (source) :

Configuration files :

File Purpose
/etc/ssh/sshd_config This is the main configuration file (Configuration directives). sshd can't start if this file is unavailable.
/etc/motd welcome message to be displayed after a successful login, either "normal" login or via SSH (or grep Banner /etc/ssh/sshd_config )
~/.ssh/authorized_keys list of public keys. This can also hold some configuration directives.
/etc/nologin If this file exists, sshd refuses to let anyone except root log in.
ACL that should be enforced by tcp-wrappers are defined here.

Server configuration directives (source) :

Directive Default value Usage
AcceptEnv myEnvironmentVariable Declare environment variables that can be set by the SSH client (aka whitelist . A single AcceptEnv directive can declare several variables, separated by a space character.
AllowTcpForwarding yes Specifies whether TCP forwarding is permitted.
Disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.
When SSH forwarding is still needed, it is possible to enable it to specified users only (source) :
AllowTcpForwarding no
Match User stuart
AllowTcpForwarding yes
AllowUsers SPACE-separated list of user names or user / user@host patterns. Only the matching ones are allowed to log in.
Banner points to a banner file that can be found anywhere. The content of this banner is displayed during an SSH login, between the login name and password input.
ChallengeResponseAuthentication yes whether challenge-response authentication —the keyboard-interactive authentication scheme defined in RFC-4256— is enabled. This keyboard-interactive authentication scheme could, in theory, ask a user any number of multi-faceted questions. In practice it often asks only for the user's password.
ClientAliveCountMax n Allow at most n unanswered requests sent by ClientAliveInterval before disconnecting the client.
The ClientAliveInterval timer is reset after sending every request.
ClientAliveInterval n Start a timer for n seconds before requesting client response over the encrypted channel (this has nothing to do with KeepAlive, which is a TCP setting).
0 disables this function.
Compression value yes Specifies whether compression is enabled after the user has authenticated successfully. value must be :
  • yes
  • delayed (a legacy synonym for yes)
  • no
  • Login is disallowed for user names that match one of the patterns.
  • By default, login is allowed for all users.
  • The allow/deny users directives are processed in the following order:
    1. DenyUsers
    2. AllowUsers
GatewayPorts no Specifies whether remote hosts are allowed to connect to ports forwarded for the client (details)
HostbasedAuthentication no Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed
IgnoreRhosts yes whether to ignore per-user .rhosts and .shosts files (SSH can emulate the obsolete rsh with these) during HostbasedAuthentication. The system-wide /etc/hosts.equiv and /etc/shosts.equiv are still used regardless of this setting.
ListenAddress Specifies the local addresses sshd should listen on
LoginGraceTime duration 120 seconds
  • The server disconnects after duration if the user has not successfully logged in.
  • 0 = no time limit
  • duration format
MaxAuthTries 6 Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged.
PasswordAuthentication yes Whether password authentication is allowed
PermitEmptyPasswords no When PasswordAuthentication is allowed, it specifies whether the server allows login to accounts with empty password strings.
PermitRootLogin value
  • yes : root can log in using ssh
  • prohibit-password or without-password : password and keyboard-interactive authentication are disabled for root
  • forced-commands-only : root login with public key authentication will be allowed, but only if the command option has been specified (which may be useful for taking remote backups even if root login is normally not allowed). All other authentication methods are disabled for root.
  • no : root is not allowed to log in
PubkeyAuthentication yes Whether public key authentication is allowed
StrictModes yes Specifies whether sshd should check file modes and ownership of the user's files and home directory before accepting login. This is normally desirable because novices sometimes accidentally leave their directory or files world-writable.
Subsystem empty Configures an external subsystem (e.g. file transfer daemon)
UseDNS Specifies whether sshd should look up the remote host name and check that the resolved host name for the remote IP address maps back to the very same IP address. Set this to no to disable server lookups.
UsePAM no Enables the PAM interface. Details :
UsePrivilegeSeparation This option is deprecated since OpenSSH 7.5 (source)
X11DisplayOffset n Specifies the first display number available for sshd's X11 forwarding. This prevents sshd from interfering with real X11 servers. Defaults to 10.
X11Forwarding no whether X11 forwarding is permitted
disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own forwarders

Advanced Features

  • log on a remote host as a specified user :
    ssh bob@sshServer
  • receive display of remote application :
    1. log in remote host :
      ssh -X stuart@sshServer
    2. start remote application
  • execute a remote application on its own (remote) display :
    1. log in remote host :
      ssh kevin@sshServer
    2. mangle its DISPLAY environment variable to use the local display :
      export DISPLAY=:0.0
    3. then start remote application
  • copy a file ("push" mode) :
    scp path/to/file sshServer:/remote/destination/directory
  • copy a file ("pull" mode) :
    scp sshServer:/path/to/file local/destination/directory
  • copy files with scp as a specific user on the remote system :
    scp /path/to/file bob@sshServer:/remote/destination/directory
  • Preserve file rights and timestamp while using scp : use the -p flag :
    scp -p

Extra configuration directives in ~/.ssh/authorized_keys :

accept the key only for clients coming from the 192.168.15/24 network :
from="192.168.15.*" ssh-ecdsa AAAAE2Vj
accept the key only for clients coming from but not
from="!*, *" ssh-ecdsa AAAAE2Vj
disable the agent forwarding for the specified key
no-agent-forwarding ssh-ecdsa AAAAE2Vj

SSH tunneling

Tunnel types (source) :

  • local tunnels : forward a local port to a remote host
  • remote tunnels : forward a remote port to a local host. This is similar to a local tunnel, with reversed directions.

Local tunnels

SSH tunnel - local

ssh kevin@SSH -L

  • the local IP is implicit, there's not need to specify it.
  • the remote IP is relative to the SSH host (=as seen by the SSH host)

Remote tunnels

SSH tunnel - remote

ssh kevin@SSH -R SSH:s_port:REMOTE:r_port


  • Don't forget that the tunnel entry is
  • When setting tunnels, you are prompted for the password of the user stuart on the host SSH. If successful, a shell opens on SSH with stuart's credentials. As long as this shell is active, the tunnel is up. So, to close the tunnel, just "exit".
  • To make sure the tunnel is up :
    netstat -a | grep ssh
    In netstat output, connections listed as TIME_WAIT are waiting for the protocol session end (=timeout).
  • With both tunnel types, sshd only accepts connections from the loopback address, so that only local programs can use the tunnel (better security). To workaround this, edit /etc/ssh/sshd_config and set GatewayPorts to yes. (details)