Feed RSS
Feed RSS
Debian GNU Linux
Play Ogg
Eliminate DRM!
hosted by tuxfamily.org
Articles Hierarchy

    Howto ssh


Table of contents

  1. Introduction
  2. Installation
  3. Set up the client
    1. Create asymmetric key pairs
    2. Copy the keys
  4. Set up the server
  5. Use of SSH
    1. Execute remote commands
    2. Mount a remote folder - SSHFS
    3. Copy files remotely
  6. X11 fowarding
  7. Settings
    1. Client
    2. Server
  8. The Control Master
    1. Persistent connection
  9. Conclusions


1. Introduction

Before the Secure Shell protocol it was common to use plain text. communications as in telnet. Of course this represents a big security issue. Plain text can be easely sniffed and read due to the lack of encryption meaning that user names and password are in serius danger.
The Secure Shell (SSH) protocol solved the problem using an asymmetric key pair. SSH allows for secure communications, graphic remote sessions, remote command execution, and much more. SSH can handle the key exchange between client and server, authenticate users, and encrypt data.
On Linux the standard implementation is OpenSSH, present by default in the repositories of every distribution.

In this howto I collected what I found useful about the installation and basic configuration of both client and server. As usual I think at this how to as a hands-on guide, not a comprehensive guide at all. OpenSSH is a very big software and the official documentation should always be read before start working with SSH especially if you are working on a server.

NOTE: this howto is based on Debian. While in Debian derivates all commands should be the same, in other distributions things may change. If you find that in your distribution something is different let me know, so we can improve the howto togheter.


2. Installation

First we need to install required packages. OpenSSH should be installed by default in every distribution, but in case is not enter

# apt-get install ssh

This Debian metapackage depends on both client and server. Search in the repos of your distribution for the right packages.

To install only the client (if you only need to connect to remote machines but you don't accept incoming connections) it is enough to install

# apt-get install openssh-client


3. Set up the client

We start from the setup of the client. Installing SSH should create a new directory ~/.ssh in the user home folder. If for some reason it's not there use the following to create it

$ mkdir ~/.ssh && chmod 700 ~/.ssh

Now try a first connection to a remote server using the following syntax

$ ssh <user>@<server>

You will be asked for the password. of the user you are connecting with. Enter it. If it's correct a message will be prompted.

The authenticity of host 'your_server.org' can't be established.
DSA key fingerprint is 61:d3:1a:6c:5c:fa:26:2d:b0:cf:4a:03:9a:74:a5:cc.
Are you sure you want to continue connecting (yes/no)?

Reply "yes" and a shell should come up

Warning: Permanently added 'your_server.org' (RSA) to the list of known hosts.

If you current user on the local machine and on the remote one are the same you can also use the syntax

$ ssh <server>

You can test this by connecting to your user on your local machineIn this case the actual username will be passed to the remote server.

If the connection works as expected your SSH is perfectly up and running.


Create asymmetric key pairs

Using only a password is not a secure way to use SSH since the password can be stolen or brute forced. Using asymmetric key pairs is considered a far more secure solution. To know more about asymmetric key cryptography see for example here[https://en.wikipedia.org/wiki/Public-key_cryptography].
Keys must first be generated with the keygen tool provided by SSH

$ ssh-keygen

Press Enter to save the keys to file. Now you'll be asked for the passphrase twice. Enter what you prefer. Choosing a strong one is always a good idea. If you want to change it later use the -p option of the keygen

$ ssh-keygen -p

ssh-keygen since SSH 5.7 use the recommended and default protocol to generate the key is the ECDSA. Also the RSA 1 (2048 bit), RSA 2 (4096 bit) and DSA (1024 bit) algorithms are available. To change the algorithm use the -t option

$ ssh-keygen -t rsa2        # or -t dsa

The RSA 1 protocol is old and unsecure with respect to the RSA 2 while the newer ECDSA should be faster than the RSA 2 with a similar security. The only issue with ECDSA is that might be incompatible with older versions of SSH.

ssh-keygen generates a pair of keys, one public and one private. The private one is stored inside the /home/user/.ssh/id_rsa file (or another one if we didn't use the default one) and the public one is in a file with the .pub suffix (by default id_rsa.pub). The private key must be kept safe on the local machine and should never be moved or copied elsewhere for security reasons. The public key is the one that the server we want to connect to must know in order to be able to recognize us and has to be copied remotely.

More options in the man page

$ man ssh-keygen


Copy the keys - SCP (Secure Copy)

Traditional way
The public key must be copied on the remote server. Tools like scp are perfect for this purpose

$ scp /home/user/.ssh/id_rsa.pub <user>@<server>:~/

Some useful options of scp

-r recursive copy
-P [num] port to use. Sometimes the service is not on the default port (the 22) and you need to change the number

The public key you have copied in your home folder on the remote server must be inserted in the .ssh/authorized_keys file. Log in and copy the key in the file

$ ssh <user>@<server>
$ cat id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ rm id_rsa.pub
$ logout

The public key file is no longer needed and can be deleted. You can also use this one-liner to generate and copy the keys

$ ssh-keygen -t rsa2 && cat id_rsa.pub | ssh <user>@<server> $(sh -c "cat ->> ~/.ssh/authorized_keys && \
chmod 600 ~/.ssh/authorized_keys")


Faster way
Another way to copy the public key remotely is to use the ssh-copy-id command. Simply enter

$ ssh-copy-id <user>@<server>

The public key must be in a file called id_rsa.pub.


Delete public key and check permissions
The public key is no longer needed both on the client and the server and should be deleted.

$ rm id_rsa.pub


Check that SSH is active client side with

$ ps -e | grep ssh
2908 ?        00:00:00 ssh-agent

If it is not active start it using as root

# sh /usr/bin/ssh-agent

If SSH refuses the connection after the setup of the key pair is complete, it might be that permissions are wrong. Check that the authorized_key file on the server is readable and writable only by you and that the .ssh/ folder has no writing permissions for group and others.

For good safety permessions should look like

# On the client
drwx------   2 nero nero 4,0K apr  3  2013 .ssh/
-rw------- 1 nero nero 1,7K mar 30  2013 id_rsa
# On the server
drwx------   2 remote remote 4,0K apr  3  2013 .ssh/
-rw------- 1 remote remote  396 18 jun  2012 authorized_keys


4. Set up the server

Configuring the sshd_config file
Now the keys are in place but you need to tell the server to use them. On the server open the file /etc/ssh/sshd_config and modify the file to have

PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

This option works only with SSH2. To use it with SSH1 is slightly different

RSAAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

However SSH1 is old and unsafe and should NEVER be used.

Note: Keys are entered in authorized_keys one per line. Copying the key be sure that it not contains non-printable characters or line breaks.

Note 2: Deleting a public key from the authorized_keys file on the server will make impossible for that user to access again.

Now the key log in is enabled and we can log in even without the password if we want (see how to disable password access).

Check that the SSH daemon is active

$ ps -e | grep sshd
3016 ?        00:00:00 sshd

If it is not active start it using as root

# /etc/init.d/sshd start


5. Use of SSH

To connect from the client to the server use the following syntax

$ ssh -l <user> <server>


$ ssh <user>@<server>

The two commands are equivalent and will connect the client to the desired server as the desired user. The server will ask for the password if needed (see also here for connection without password). Enter the right password and you're in!


Execute remote commands

Through SSH you can execute remote commands on the remote server with the rights of the user logged in. A shell ready to be used is prompted until you log out from the remote host. If you only want to issue one command, it is faster to log in and execute on the same instruction. SSH accept also commands as parameters of the connection using this syntax

$ ssh <user>@<server> $(command -options whatever)

To issue several commands in the same SSH call use a semicolon (;) to separate them. They are evaluated in the same order they are written. Be sure that commands are quoted or the semicolon will terminate the SSH call.

$ ssh <user>@<server> $(command1; command2; command3)

To log out when finished use the logout command

<user>@<server>:~$ logout


Mount a remote folder - SSHFS

Thanks to SSHFS and the Fuse project, SSH is able to mount a remote folder on the local filesystem like any other partition. In this way you can work on this files securely. The connection is not incredibly fast since all communications to and from the remote filesystem are silently sent through SSH and crypted. So don't use it for heavy load operations. For more informations on the Fuse project see the official documentation at Fuse project.

Fuse is usually installed on every distribution by default. To install both Fuse and SSHFSuse (on Debian and derivates)

# apt-get install sshfs fuse

Insert the fuse module in the kernel with

# modprobe fuse

Now we must add to the fuse group every user we want to be able to mount remote folders

# usermod -a -G fuse <user>

If Fuse was installed on your machine check that your user is in the fuse group.

When Fuse is configured the user can mount a remote folder using the syntax

$ sshfs idmap=<user> <user>@<server>:/remote_dir ~/local_dir

Now the remote folder remote_dir is mounted locally as local_dir and is browsable like any other folder in the filesystem.

To unmount

$ fusermount -u ~/local_dir

It is possible to automatically mount a SSHFS partition on boot modifying the /etc/fstab file. Following the usual syntax of this file, the line to add is

sshfs#<user>@<server>:/path/to/remote_dir /path/to/local_dir/    fuse   defaults, idmap=user   0 0


Copy files remotely

To copy some file to the remote server you can use the scp command, a secure version of the usual command cp. The syntax is the same

$ scp <source> <destination>

and can be used to transfer a file to the remote server using

$ scp <file> <user>@<server>:<remote_path>

For example

$ scp archive.tar user@my_server.org:/home/user/path/archive.tar

Also transfer from the remote folder is possible using the same syntax

$ scp user@my_server.org:/home/user/path/archive.tar local_archive.tar


6. X11 fowarding

By enabling the X11 fowarding, applications that need a GUI interface can be executed remotely while the X server output gets visualized on the local machine through SSH. The -X option and the -Y option enable the X11 fowarding at the connection

$ ssh -X <user>@<server>
# or
$ ssh -Y <user>@<server>

On the server side the X11 fowarding is possible only if you allow for it. To make it available modify the /etc/ssh/sshd_config file so that there are this two lines

AllowTcpForwarding yes
X11Fowarding yes

The X11 tunnel is a potential security weakness for both client and server. If you run a server make this available only if really needed for some reason or keep it disabled explicitly with

X11Fowarding no

On the client side you can set up to always use the fowarding modifying the /etc/ssh/ssh_config file in this way

ForwardX11 yes

If you run a client use it only when necessary and with trusted server. It is possible for the client to choose to use or not the X11 tunnel selectively for each remote host. In the /etc/ssh/ssh_config file add this line

Host *.foo.com
ForwardX11 yes

Host *
ForwardX11 no

The X11 fowarding is disabled for all host except for the domains belonging to foo.com.

There is a subtle difference between the -X option and the -Y option used by a client connecting. The former enables the "simple" X11 fowarding, the latter a "full access" X11 forwarding. What does it mean? When the "simple" forwarding is enabled the sever will send back to the client the GUI result of any command issued to the server unless certain security rules are violated. In this case the client will receive an error. When the "full access" forwarding is used, the client has total access to the original X11 server and the X11 SECURITY extension restrictions are not imposed. For more informations about this look into the X11 SECURITY restrictions.
To ask for a safer connection

$ ssh -X <user>@<server>

or for a full access one

$ ssh -Y <user>@<server>

There is a keyword we might want to modify on the client side (/etc/ssh/ssh_config configuration file). The key

ForwardX11Trusted no

specifies wheter we want a full access connection by default.
Therefore when the configuration is like

ForwardX11 no
ForwardX11Trusted no

we have

ssh <user>@<server> != ssh -X <user>@<server> != ssh -Y <user>@<server>

so that no forwarding is enabled by default. When

ForwardX11 yes
ForwardX11Trusted no

we have

ssh <user>@<server> == ssh -X <user>@<server> != ssh -Y <user>@<server>

so that forwarding is enabled but we need to explicitly ask for full access. When

ForwardX11 yes
ForwardX11Trusted yes

we have

ssh <user>@<server> == ssh -X <user>@<server> == ssh -Y <user>@<server>

so that we always have full access. At last

ForwardX11 no
ForwardX11Trusted yes

we have

ssh <user>@<server> != ssh -X <user>@<server> == ssh -Y <user>@<server>

we need to ask for the tunneling but it will always be full access.

There is a quick way to know if the X11 tunnel is enabled. Connect to the server and check if the DISPLAY environment variable is set.

<user>@<server>:~$ echo $DISPLAY

If everything is working correctly graphical applications will be displayed on the local desktop. Speed and responsiveness of the graphical session depend mainly on the network speed. Usually any network is able to run more common applications without flaws. But if you pretend to be able to watch a BlueRay disc through SSH you may be in trouble.

Data compressions can be activated when the graphic session is too slow. Compression is triggered by the -C option

$ ssh -X -C <user>@<server>

Server side the compression can be enabled for by default adding the following line to the sshd_config file

Compression yes


7. Settings

OpenSSH is a very big and complex program with a lot of options both client side and server side. It's clearly impossible and pointless to try to describe them all. Here there are only options and tricks I think are the most important or interesting for the majority of people.


Client side

Settings for the client are located in the /etc/ssh/ssh_config file. The root permissions are needed to change the file.


1. Check IP

The SSH client checks the IP address of the server is connecting to by comparing it with the IP stored in the .ssh/known_hosts file. If the address has changed, SSH displays a warning message

Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.

If the source of connection is trusted go further entering "yes" and the new IP will be registered in the known_host in place of the old.

This feature is useful for security but can be tedious if you need to connect frequently to a server with dynamic IP. To disable it (but do it only if is important for you) open the configuration file ssh_config and modify it to have this line

CheckHostIP no

The right thing to do is to disable the check only for domanis that give problems

Host *.dynamic_server.net
CheckHostIP no


2. Keep the connection alive – client side

If there is no traffic on the SSH tunnel for some time the connection is closed. The time interval before the connection is shut down can be modified changing these two lines

ServerAliveInterval 100
ServerAliveCountMax 3

The first line is the time interval in second the client waits before sending a request to the server to keep the connection alive. If the server doesn't respond, the client will continue to send messages with the same time interval. If the time is 0 the client will not send messages. After a number of messages given by the second line, the client will disconnect. If the second line is 0 the client disconnect the first time it has no response. In this example the client disconnects after 3 messages and 300 seconds if the server has disappeared.


 3. Hashing the known_hosts file

In the known_hosts file the addresses and names of the various servers are stored in plain text. If you are concerned with security you can hash the whole file using the -H option of the utility ssh-keygen

$ ssh-keygen -H -f ~/.ssh/known_hosts
$ rm ~/.ssh/known_hosts.old

SSH will be still able to read the hashed file.


Server side

Configurations for the server side are located in the /etc/ssh/sshd_config.


1. Disable password access

Use both password and key to access a remote server is the safest way. But in some cases, like non interactive logins, it is better to avoid using passwords and rely only on the key. For example when we want to automate a job on the remote using cron and a script. To disable password access on the server you must modify the /etc/ssh/sshd_config file.

Before doing any change, backup the server configuration file for security

# cd /etc/ssh
# cp sshd_config sshd_config.bak
# nano sshd_config

and modify it to have the following lines

PasswordAuthentication no
UsePAM no

If a new user want to create his keys he must follow the step 3. When asked for the password press Enter and the couple of keys will be generated without password.

To make new configurations effective restart the SSH daemon

# /etc/init.d/ssh restart


2. Not permit root login

To enhance security on the server is better to explicitly say which users can connect via SSH and which can't. The most dangerous user is of course root. Permit the root user to login means that if someone steals the password or the key, he has full access to the server system. It is always a good idea to disable the root user in this way

PermitRootLogin no

The root user cannot connect but it's possible to connect with another user and then obtain root permissions using su or sudo.


3. How to restrict the access to the SSH server

For the other users use the instructions AllowUsers and DenyUsers to explicity allow or disallow a user to connect. The syntax is

AllowUsers user1 user2
DenyUsers user3 user4

Another possibility is to use the instructions AllowGroups and DenyGroups. These work the same way as the previous two, but as the name suggest, they work on groups. One simple way to keep things organized is to create a group on the server allowed to connect through SSH and add all the users you want to allow to that group.

# groupadd -r sshallow
# usermod -a -G sshallow user

Than you change the usual configuration file

AllowGroups sshallow


4. Timeout setting

To change the time limit available to the user to authenticate himself modify this line (in seconds)

LoginGraceTime 100

After 100 seconds the connection is closed by the server.


5. Keep the connection alive – server side

After some time the connection is not used, the server close it and the user must reconnect. To change the time limit

ClientAliveInterval 100
ClientAliveCountMax 3

Like for the client the first line is the number of seconds between connection attempts, the second is the number of attempts before closing the connection.


6. Disable empty passwords

To use empty passwords to login is dangerous for security. It is always best to disallow empty passwords with this line

PermitEmptyPasswords no

However there are tools like scp that may need this option set on "yes". Check your own needs and if you can set it on "no".


7. Change service port

The default port for SSH is the 22. Needless to say that all the bots on the net try to attack this port. If you have a firewall the very big part of those attacks are harmless but anyway they fill up quickly the log files. To avoid the annoyance, change the service port to one bigger than 1024 with the following line

Port 1234

Remember that suitable ports are between 1025 and 65535. But you may experience problems going over 5000.
If you want to change the port only for this time, launch the SSH daemon on the server with the option -p <port>

# sshd -p <port>


8. Check user's files permissions

A user should not keep files in his home directory with permissions like 777 for security reasons. To avoid the problem make sure to have the following line in the configuration file

StrictMode yes


9. Restrict the sources of connection

SSH by default accepts connections from all over the world and checks for keys and/or password matching to allow logging in. If you know that connections for a certain user should come only from a certain IP or range of IPs you can deny connections for that user coming from other IPs. To do that use the field from="" in the authorized_keys file. In this field write a list of domains or IP addresses accepted for that key. This field will be checked by the daemon in addition to key and password.


In this field you can also explicitly deny connections from a source using the character "!".


The from="" field has other options that I omit. Read the sshd man page for more.


10. Add a banner

When a user connects to the server the shell prompt is displayed. However it is possible to display a banner or a message anytime a user connects before the shell prompt adding it to a file and using the following line in the configuration file

Banner /path/to/banner/file


11. Change the number of bits of the key

The bit number of the key is adjustable in the configuration file using this keyword

ServerKeyBits 1024

When creating the key tell to ssh-keygen the number of bits to be used with the -b option

$ ssh-keygen -t dsa -b 2048


12. Change server listening addresses

SSH by default listens for connections on any IP address (it is set on belonging to the server. When your server has more than one IP address associated you may want the server to listen only on one of them. To bind the server socket to one IP address use the following keyword



13. Change the host key file

Private keys on the server are kept in the ssh_host_key file for protocol SSH-1 and in the ssh_host_rsa_key, ssh_host_dsa_key, and ssh_ecdsa_host_key files for the protocol SSH-2 (the file is choose on the base of the type of key). To override the default file use the HostKey key in the configuration file

HostKey /etc/ssh/my_host_key      // SSH-1
HostKey /etc/ssh/my_host_dsa_key // SSH-2


14. Check if the configuration file sshd_config is ok

To check for the sanity of the sshd_config file there is the -t option whose purpose is to read all the keys and see if they are valid. Then the daemon exit and the exit code should be 0. To check use:

# sshd -t
# echo $?


8. The Control Master

The Control Master allows to open more than one session at a time on the same connection. With the first session a socket is created. New connections to the same host will use the same master connection without renegotiating. The socket is specified with the ControlPath keyword. Control Master enable autocompletion for the shell and speed up file transfer.

To activate it add the following lines in the ssh_config file on the client

ControlPath ~/.ssh/socket/master-%r@%h:%p
ControlMaster auto

In auto mode the CM will use the existing socket if present. If not it will create a new one.

The CM has many options you can use with the syntax ControlMaster <flag>. The list in the table.

no do not be CM but use an existing socket if present
yes always be the CM
ask if a socket exist, ask to the user to use it
askauto a combination of auto and ask

With the option -M connecting to SSH you are giving to that session the Control Master status.

The first line is the path of the socket to create with it's name. Every socket is identified univocally with is name.

%r login user
%h remote host name
%p port number
%l local host name


Persistent connection

This option is useful when we log in frequently for short sessions. Using the persistent connection, when you log in the connection remains open in background as a CM. Every other connection made as the same user will use the CM running in background instead of open a new session.

$ ssh -MNf user@remote_host.org


9. Conclusions

In this howto only a very small part of OpenSSH is presented. The whole program is too wide to be reviewed in a howto. Informations presented here come from (mainly) the official documentation distributed on line and with the man pages of OpenSSH. I suggest to read carefully the man pages especially if you are planningto set up a server of your own.

$ man ssh
$ man sshd
$ man ssh_config
$ man sshd_config
$ man ssh-keygen


Update 10-15-2010: Additions and corrections.
Update 18-09-2011:
English translation.
Update 30-12-2013: Review and additions to X11 forwarding part.

Check the SSH daemon is active on the server

$ ps -e | grep sshd
3016 ?        00:00:00 sshd

or that the client is active client side

$ ps -e | grep ssh
2908 ?        00:00:00 ssh-agent

If are not active start them using as root one of the following

# sh /usr/bin/ssh-agent     // for the client
# /etc/init.d/sshd start // for the server
No Comments have been Posted.

Post Comment
Please Login to Post a Comment.

Rating is available to Members only.

Please login to vote.

No Ratings have been Posted.