Secure Shell (SSH) is a protocol for creating an encrypted communications channel between two networked hosts.
It quickly spread to replace insecure protocols such as telnet, rsh, and rlogin.
- OpenSSH is the most widely deployed implementation of the SSH protocol
- OpenSSH is developed by the OpenBSD Project, a team known for writing secure software
OpenBSD and OpenSSH Portable version
- The OpenBSD version is where the main development happens, but it only supports OpenBSD
- The OpenSSH Portability Team takes the OpenBSD version and adds the glue necessary to make OpenSSH work on other operating systems, creating Portable OpenSSH
The most popular Microsoft Windows SSH client.
SSH protocol versions
- Always use SSH-2, since SSH-1 is known to ver vulnerable to attacks
- If you own a SSH server, don’t support SSH-1 at all
- There are no known security problems with the protocol
How OpenSSH encryption works
- Every SSH server has a key pair
- Whenever a client connects, the server and the client use this key pair to negotiate a temporary key pair shared only between those two hosts
- The client and the server both use this temporary key to derive a symmetric key that they will use to exchange data during this session, as well as related keys to provide connection integrity
- If the session runs for a long time or exchanges a lot of data, the computers will intermittently negotiate a new temporary key pair and a new symmetric key
Verifying server keys
- Each SSH server has a unique public key
- The first time a client connects to a server, the SSH clients prints the server fingerprint
- Users are expected to manually check the fingerprint
- The client then caches the server key
View the fingerprint of a server public key from the server
ssh-keygen -lf /etc/ssh/ssh_host_*_key.pub
- Distribute fingerprints to your users in a secure, encrypted way
Rules of thumb
Don’t manually prefer certain algorithms over other algorithms. Let the OpenSSH developer choose (they know what they’re doing)
- Give accounts the least level of privileges that will let users and programs accomplish their required tasks
Change the TCP/IP port OpenSSH runs on (security through obscurity)
Don’t change the OpenSSH banner, since some clients make use of this information to connect correctly
By only allowing authorized IP addresses on your network to access your SSH server, you block the vast majority of attackers. Use firewalls instead of server settings when possible
The most effective way to protect your server is to disable passwords and only allow logins via keys
- Never use passphrases over SSH. Use SSH keys instead
/etc/ssh/sshd_config(see all options in
$HOME/.ssh/config(see all options in
- The server’s private key:
- The server’s public key:
Basic server configuration
The TCP port the OpenSSH server should run in.
The TCP/IP version the server should use.
inet: for IPv4
inet6: for IPv6
any: for both IPv4 and IPv6
ListenAddress <ip address[:port]>
Many hosts have multiple IP addresses. By default,
sshd listens for incoming
requests on all of them. If you want limit the IP addresses that
attaches to, use this option.
- This option may be set multiple times
The SSH protocol to support. This can be
- Always use
The path to the file containing the banner message.
- Keep in mind that whether this is shown or not depends on the client
Whether to print
/etc/motd after a client successfully connects.
Whether to print information about the last time the user logged in to the client, after it connects successfully.
- It is recommended to leave this turned on, to alert users about potential intrusions
How much time a user has to connect to the server. If the user fails to connect, then the connection is terminated.
The maximum amount of times a user can try to authenticate before closing the connection.
- After half of the user attempts failed, the system logs any further failures
Verify the forward and reverse DNS names for a client’s IP address, to reject potentially malicious connection attempts where the client spoofs the DNS name.
- DNS checks can increase system load (only relevant if you have hundreds of SSH users)
- Client controls the reverse DNS name for his IP address
- Client changes the DNS name to make it appear it comes from your company
- Client connects to your SSH server using the spoofed DNS name
If this option is set:
- Server queries its DNS for the host the client is trying to connect as:W
- If the IP address it has on the DNS doesn’t match the real IP address, reject the connection
The path to store the PID file.
- Useful if you want to lock SSH users to a certain file tree (a
chroot), and want to prohibit them from escaping that jail
- The chroot directory must be owned by
rootand not be writable by the restricted user
This option can take
%h (host) and
%u (username) macros.
OpenSSH makes use of
This can be:
These may violate privacy:
User access control
You can use the following options, which take a comma-delimited list of identifiers, to tweak user access permissions:
These options may also accept an IP or host name after a
@ sign to further
control where the allowed users should be permitted to log in.
- Make use of groups whenever possible
If a user is inside
DenyUsersbut his group is inside
AllowGroups, the user will be denied
If a user is inside
AllowUsersbut his group is inside
DenyGroups, the user will be allowed to connect
The presence of
AllowGroupsmeans that no one else can connect
Sometimes you need to dynamically set OpenSSH server options based on a certain pattern. You can use match statements for this:
Match <criteria> <value>
Anything that comes after the match statement applies if the conditions are true, until the next match statement or, the end-of-file mark.
- Match statements should appear at the bottom of the
- You can pass multiple match conditions one after the other one
match User johndoe,janedoe <rule 1> <rule 2> <rule 3> match Group mygroup <rule 1> <rule 2> <rule 3> match Group mygroup Address 192.168.0.* <rule 1> <rule 2> <rule 3>
OpenSSH server snippets
sshd with a custom configuration file
/usr/sbin/sshd -f path/to/sshd_config -p <port>
- You need to execute
sshdusing an absolute path, since the tools needs to be able to easily re-spawn itself when accepting a connection
- Remember to kill the SSH server when you’re done with it
sshd in debugging mode
This will make
sshd print a lot of verbose debugging information of
everything is happening on the server.
- You can pass
-dmultiple times to increase verbosity
- An OpenSSH server in debugging mode will not fork, so it can only accept one client connection at a time
- Ctrl-C causes a SSH server running in debug mode to die instantly
Basic client configuration
The port to use by default.
The username to connect as.
Set a host for which the following settings apply, until a new
is encountered, or the end-of-file marked is reached.
Host *.example.com Port 2222 Host 192.168.0.* foobar.com Port 24
- Put any defaults at the end of the file
Force a connection over IPv4 (
inet) or IPv6 (
Whether to require users to manually verify hosts and add them to
Setting it to
no means that
ssh will blindly trust any server.
- Don’t ever set this to
Whether to hash the entries of the
known_hosts host file, so no-one can read
them in plain-text.
- It is recommended to set this to
yesfor security purposes
- Older entries will remain un-hashed. Execute
ssh-keygen -Hto hash existing entries
Whether to allow port forwarding or not.
This option controls whether a client can bind a forwarded port to any server address other than the localhost.
If set to “yes” all forwarded ports are bound to the network-facing IP address.
If set to “clientspecified,” the software will accept any configuration given by the SSH client.
Restrict which TCP ports and addresses can receive forwarding.
PermitOpen localhost:80 localhost:221
Keeping SSH connections open
(Client|Server)AliveInterval: How many seconds the connection needs to be idle before the hosts sends a keepalive request
(Client|Server)AliveCountMax: How many unsuccessful keepalive requests to send before terminating the connection
ClientAliveInterval 90 ClientAliveCountMax 5
ServerAliveInterval 90 ServerAliveCountMax 4
OpenSSH client snippets
ssh in debugging mode
ssh -v <host>
- You can pass
-dmultiple times to increase verbosity
Pass a custom configuration file
ssh -F path/to/config <host>
Manually pass a configuration option
ssh -o <key>=<value> <host>
ssh -o Port=2222 <host>
Connect with a custom SSH key
ssh -i path/to/key <host>
Add a key to the ssh agent
Copying files using
- This program reads
Copy files from two OpenSSH servers
scp source-hostname:<file> destination-hostname:<file>
Recursively copy files from two OpenSSH servers
scp -rf source-hostname:<file> destination-hostname:<file>
Copy files from the local file-system to an OpenSSH server
scp <file> destination-hostname:<file>
- All remote paths are relative to the default login location
- If we omit the destination file path, then it will be copied to the default login location
Copy files from an OpenSSH server to the local file-system
scp source-hostname:<file> file>
Managing files with
sftp stands for SSH File Transfer Protocol, and its basically a
reimplementation of the FTP protocol using SSH.
- It allows for much more flexibility than
- This program reads
Open an FTP-like prompt
helpto print all the available commands
get <filename>to get a file to your local file-system
put <filename>to put a file from your local file-system
lsto list the remote directories
cdto change to another directory in the server
lcdto change to another directory in the client
rename <file1> <file2>to rename files in the server
exitto quit the interactive session
For cases where some users need to copy files, but don’t need interactive sessions.
Match Group <group> ChrootDirectory %h ForceCommand internal-sftp AllowTcpForwarding no
Generate server keys
- While any user can generate keys, only the superuser can copy them to the expected location
On newer systems
On older systems
- Server keys have no passphrase (because the SSH service needs to start when
the system boots, almost always non-interactively), so we set
-Nto an empty string
- Remember to retrieve the fingerprints after creating keys
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_dsa_key -N ''
Generate client keys
The following command will allow you pick all the options interactively:
- Store keys in the default location, since OpenSSH and other related programs look for key-pairs there
- Always pick the recommended algorithm at that time
- Generate one SSH key-pair per machine (never re-use them)
Disable server passwords authentication
ChallengeResponseAuthentication no PasswordAuthentication no PubkeyAuthentication yes
ssh to host
foo, and need to copy a file from
will need your private SSH keys in
foo in order to access
bar, which is a
You can enable agent forwarding to route private keys between hosts.
- Only do this if you trust the server!
Basic X11 forwarding (more secure)
Trusted X11 forwarding (less secure)
- Only if basic X11 forwarding is not enough
- Only enable this per-host:
ForwardX11 no Host foo ForwardX11 yes ForwardX11Trusted yes
It is recommended to use
ssh CLI options to enable X11 forwarding when you
need it, instead of always enabling it for all connections to certain hosts:
Basic X11 forwarding
ssh -X <host>
Trusted X11 forwarding
ssh -Y <host>
You can check if X11 forwarding was successfull by checking the value of the
DISPLAY environment variable, which will be undefined if X11 forwarding
- Do not run X11 programs if
Directly run an X11 program
-f option tells
ssh to go to the background after executing the
ssh -f <host> <x11-program>
To create a background process that does the forwarding, do:
ssh -f -N <forwarding options> <host>
-foption will put the
sshprocess in the background
-Noption will make the client run nothing on the server (not even a shell)
Local port forwarding
Bind a port of a server to a port of your local machine.
ssh -L localIP:localport:remoteIP:remoteport hostname
Or add an entry to
LocalForward client-IP:client-port server-IP:server-port
- This can be useful to make use of any unencrypted protocol over an encrypted connection
Remote port forwarding
Bind a port of your local machine to a port of a server.
ssh -R remoteIP:remoteport:localIP:localport hostname
Or add an entry to
RemoteForward client-IP:client-port server-IP:server-port
- Useful to access a service from behind a firewall
Dynamic port forwarding
Setups a generic gateway that can carry any TCP/IP traffic between two machines.
ssh -D localaddress:localport hostname
Or add an entry to
- This creates a SOCKS proxy on the specified address and port
- You can connect any application to the proxy, which will pipe any TCP/IP traffic
Contains entries in the following standard form:
You can pass additional keywords and instructions at the beginning of these lines for more finer control. Separate multiple keywords by commas.
Whenever someone logs in using the key, run the specified command.
Whenever someone logs in using the key, set the specified environment variable.
PermitUserEnvironmentto be enabled
Only allow logins from a certain SSH pattern. For example:
from="192.168.0.1/25" ssh-rsa ... hostname
- Remember that reverse DNS on hosts can be forged. If you really want to restrict the hosts that can log in, stick with IP addresses
Disables agent forwarding.
Disables port forwarding.
Disables X11 forwarding.
OpenSSH servers keep a list of “trusted” public keys in a file called
$HOME/.ssh/authorized_keys. This file contains a public key per line.
Appending entries to
Its recommended to:
- Copy the public key using
- Concatenate it to
cat id_rsa.pub >> $HOME/.ssh/authorized_keys
This is to avoid any silly copy-pasting issues.
Host key cache
The OpenSSH client records approved keys in
The structure of each line is the following:
- Marker (optional) (
- Hostnames (including IP addresses) (separated by comma)
- Type of key
- The public key
- Comment (optional) (anything you desire)
An entry that starts with this comment indicates that the host key is for a certification authority.