SSH Secure Shell

Managing Secure Connections with SSH

ssh - secure shell


SSH or Secure Shell is a network protocol that allows data to be passed between two networked servers using a secure channel. The main use for ssh is to obtain a secure remote shell on a networked server, however, it is also commonly used for copying files between servers (SCP). To use ssh to obtain a secure remote shell, the remote shell must be running "sshd" (secure shell daemon). Generally "ssh" uses port 22 for its communication, however, many system administrators will change to an alternative port as a means of adding extra security. Changing the port however doesn't offer much in security gains. If you need to secure your ssh communications you should consider using a firewall to only allow known traffic!



On Linux the general implementation of ssh is known as "OpenSSH". Most modern Linux distributions should have OpenSSH installed by default. The standard location for OpenSSH configuration files is "/etc/ssh". Here you will find the ssh_config file for the client side and the sshd_config file for the server side.

Example configuration files and keys found on a OpenSUSE installation:



linux-pd5y:/etc/ssh # ls -l
total 164
-rw------- 1 root root 125811 Feb 22  2012 moduli
-rw-r--r-- 1 root root   3056 Feb 22  2012 ssh_config
-rw------- 1 root root    668 Mar 14 10:16 ssh_host_dsa_key
-rw-r--r-- 1 root root    605 Mar 14 10:16 ssh_host_dsa_key.pub
-rw------- 1 root root    227 Mar 14 10:16 ssh_host_ecdsa_key
-rw-r--r-- 1 root root    177 Mar 14 10:16 ssh_host_ecdsa_key.pub
-rw------- 1 root root    980 Mar 14 10:16 ssh_host_key
-rw-r--r-- 1 root root    645 Mar 14 10:16 ssh_host_key.pub
-rw------- 1 root root   1679 Mar 14 10:16 ssh_host_rsa_key
-rw-r--r-- 1 root root    397 Mar 14 10:16 ssh_host_rsa_key.pub
-rw-r----- 1 root root   3825 Feb 22  2012 sshd_config

Generating a SSH key


SSH gives you the ability to create keys that can be exchanged with other servers which allow you access without having to type a password. The utility for creating these keys is called "ssh-keygen". To create a key quickly we can simply issue the command "ssh-keygen -t rsa". This will then step through several interactive prompts asking for confirmation or for additional information to be entered. Below is an example of a "Public Key" being generated:



john@john-desktop:~/.ssh$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/john/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/john/.ssh/id_rsa.
Your public key has been saved in /home/john/.ssh/id_rsa.pub.
The key fingerprint is:
d7:f5:6e:20:9b:fe:29:51:f3:d4:2f:bb:6c:c5:9a:31 john@john-desktop
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|              . .|
|           . .o.o|
|        S . o..=o|
|         .  .+Eo=|
|            o. Oo|
|           ...=o |
|            .+=. |
+-----------------+

In the above example we chose to use "rsa" (Rivest, Shamir, Adleman) algorithm to create our digital signature. We could have chosen "dsa". Next we were prompted to supply a directory where we would like the key to be saved. In the example we pressed "enter" to accept the default option of "/home/john/.ssh/id_rsa". We were then asked to enter a passphrase. We chose not to enter a passphrase. All that is required now is that we distribute our public key to our desired remote server.


Copying Public keys to remote servers


In the above example of the "ssh-keygen -t rsa" command we can see that a public key was created:

Your public key has been saved in /home/john/.ssh/id_rsa.pub

To use our public key, we have to first copy the contents of the file "id_rsa.pub" to a file called "authorized_keys" on the remote server. Whenever copying a new key to a remote servers authorized_keys file, always use the append option. If we blindly copy our files content we could overwrite the file and destroy any other keys that may be located there. The easiest way to transfer the key to the remote server is to issue a command similar to the one below:

cat $HOME/.ssh/id_rsa.pub | ssh 192.168.0.11 'cat >> .ssh/authorized_keys && echo "Contents Copied Successfully"'

The above command simply appends the key on our local server to the "authorized_keys" file on the remote server.

The "authorized_keys" file on the remote host should ideally have its permissions locked down to stop others from copying this file. To achieve this, you would need to make the following changes on the remote server:



john@linux-pd5y:~/.ssh> chmod 600 authorized_keys
john@linux-pd5y:~/.ssh> ls -l authorized_keys 
-rw------- 1 john users 399 Apr 25 09:34 authorized_keys

Now providing the remote server allows public key authentication, we should be able to "ssh" to the remote server. On the remote server we would need "PubkeyAuthentication" to be enabled in the "sshd_config" file.



How to test your ssh public key


To test that our key is working correctly, we can issue the command: ssh 192.168.0.11 from our local server:



john@john-desktop:~/ubuntu$ ssh 192.168.0.11
Last login: Thu Apr 25 09:39:34 2013 from 192.168.0.14
Have a lot of fun...

Success, we should now have a command prompt on the remote server.



SCP - Secure Copy (Copying files securely)


SCP copies data between two networked servers using "ssh", thus meaning that it uses the same authentication and security methods. SCP is a replacement for the older "rcp" command. Below is an example of "scp" being used to transfer a file to a remote server:



john@john-desktop:~/ubuntu$ scp new_ubuntu_file.txt john@192.168.0.11:/home/john/suse/
new_ubuntu_file.txt                           100%   31KB  30.8KB/s   00:00

Because we have already exchanged our public key with the server "192.168.0.11", our "scp" command copied our file "new_ubuntu_file.txt" across without requesting for a password. The syntax of the above example is:

scp local_file userid@remote_server:remote_path

The command "scp" instructs the system to copy the file "new_ubuntu_file.txt" to the directory "/home/john/suse" on the remote server whose IP address is "192.168.0.11" with the specified user "john". We can confirm that this file has been transferred successfully by issuing the command "ssh 192.168.0.11 ls -l /home/john/suse/" from our local server:



john@john-desktop:~/ubuntu$ ssh 192.168.0.11 ls -l /home/john/suse/
total 108
-rw-r--r-- 1 john  1000  2866 Apr 25 08:59 file1.txt
-rw-r--r-- 1 john  1000  5732 Apr 25 08:59 file2.txt
-rw-r--r-- 1 john  1000  8598 Apr 25 08:59 file3.txt
-rw-r--r-- 1 john  1000 14330 Apr 25 09:00 file4.txt
-rw-rw-r-- 1 john users   333 Apr 25 09:42 landoflinux.com
-rw-r--r-- 1 john users 31526 Apr 25 21:41 new_ubuntu_file.txt
-rw-rw-r-- 1 john  1000 31526 Apr 25 09:18 ubuntu_file.txt

ssh -vvv - debugging the authentication process


If you would like to see the authentication process in action we can add an extra parameter to the "ssh" command. By adding "-v" to the ssh command we get "verbose" output of the authentication process. If we add an extra "v" so that we now have "-vv" we get "very very verbose" output. And if we were to add another "v" to the command we get, you guessed "very very very verbose" output. Below is an example of the "-vvv" option being used. (If you are having problems authenticating, it is always a good idea to use these flags to help with debugging):



john@john-desktop:~/ubuntu$ ssh -vvv 192.168.0.11
OpenSSH_5.9p1 Debian-5ubuntu1.1, OpenSSL 1.0.1 14 Mar 2012
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to 192.168.0.11 [192.168.0.11] port 22.
debug1: Connection established.
debug3: Incorrect RSA1 identifier
debug3: Could not load "/home/john/.ssh/id_rsa" as a RSA1 public key
debug1: identity file /home/john/.ssh/id_rsa type 1
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: identity file /home/john/.ssh/id_rsa-cert type -1
debug1: identity file /home/john/.ssh/id_dsa type -1
debug1: identity file /home/john/.ssh/id_dsa-cert type -1
debug1: identity file /home/john/.ssh/id_ecdsa type -1
debug1: identity file /home/john/.ssh/id_ecdsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.8
debug1: match: OpenSSH_5.8 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1
debug2: fd 3 setting O_NONBLOCK
debug3: load_hostkeys: loading entries for host "192.168.0.11" from file "/home/john/.ssh/known_hosts"
debug3: load_hostkeys: found key type ECDSA in file /home/john/.ssh/known_hosts:1
debug3: load_hostkeys: loaded 1 keys
debug3: order_hostkeyalgs: prefer hostkeyalgs: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug2: kex_parse_kexinit: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: first_kex_follows 0 
debug2: kex_parse_kexinit: reserved 0 
debug2: kex_parse_kexinit: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: first_kex_follows 0 
debug2: kex_parse_kexinit: reserved 0 
debug2: mac_setup: found hmac-md5
debug1: kex: server->client aes128-ctr hmac-md5 none
debug2: mac_setup: found hmac-md5
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ECDSA 13:d5:46:05:78:4e:3f:43:c7:42:c1:ab:5c:6b:92:ad
debug3: load_hostkeys: loading entries for host "192.168.0.11" from file "/home/john/.ssh/known_hosts"
debug3: load_hostkeys: found key type ECDSA in file /home/john/.ssh/known_hosts:1
debug3: load_hostkeys: loaded 1 keys
debug1: Host '192.168.0.11' is known and matches the ECDSA host key.
debug1: Found key in /home/john/.ssh/known_hosts:1
debug1: ssh_ecdsa_verify: signature correct
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug2: key: /home/john/.ssh/id_rsa (0x20f11038)
debug2: key: /home/john/.ssh/id_dsa ((nil))
debug2: key: /home/john/.ssh/id_ecdsa ((nil))
debug1: Authentications that can continue: publickey,keyboard-interactive
debug3: start over, passed a different list publickey,keyboard-interactive
debug3: preferred gssapi-keyex,gssapi-with-mic,publickey,keyboard-interactive,password
debug3: authmethod_lookup publickey
debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/john/.ssh/id_rsa
debug3: send_pubkey_test
debug2: we sent a publickey packet, wait for reply
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug2: input_userauth_pk_ok: fp d7:f5:6e:20:9b:fe:29:51:f3:d4:2f:bb:6c:c5:9a:31
debug3: sign_and_send_pubkey: RSA d7:f5:6e:20:9b:fe:29:51:f3:d4:2f:bb:6c:c5:9a:31
debug1: Authentication succeeded (publickey).
Authenticated to 192.168.0.11 ([192.168.0.11]:22).
debug1: channel 0: new [client-session]
debug3: ssh_session2_open: channel_new: 0
debug2: channel 0: send open
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug2: fd 3 setting TCP_NODELAY
debug2: channel 0: request pty-req confirm 1
debug1: Sending environment.
debug3: Ignored env SSH_AGENT_PID
debug3: Ignored env GPG_AGENT_INFO
debug3: Ignored env TERM
debug3: Ignored env SHELL
debug3: Ignored env XDG_SESSION_COOKIE
debug3: Ignored env WINDOWID
debug3: Ignored env GNOME_KEYRING_CONTROL
debug3: Ignored env GTK_MODULES
debug3: Ignored env USER
debug3: Ignored env LS_COLORS
debug3: Ignored env XDG_SESSION_PATH
debug3: Ignored env XDG_SEAT_PATH
debug3: Ignored env SSH_AUTH_SOCK
debug3: Ignored env SESSION_MANAGER
debug3: Ignored env DEFAULTS_PATH
debug3: Ignored env XDG_CONFIG_DIRS
debug3: Ignored env PATH
debug3: Ignored env DESKTOP_SESSION
debug3: Ignored env PWD
debug3: Ignored env GNOME_KEYRING_PID
debug1: Sending env LANG = en_GB.UTF-8
debug2: channel 0: request env confirm 0
debug3: Ignored env MANDATORY_PATH
debug3: Ignored env UBUNTU_MENUPROXY
debug3: Ignored env COMPIZ_CONFIG_PROFILE
debug3: Ignored env GDMSESSION
debug3: Ignored env SHLVL
debug3: Ignored env HOME
debug3: Ignored env LANGUAGE
debug3: Ignored env GNOME_DESKTOP_SESSION_ID
debug3: Ignored env LOGNAME
debug3: Ignored env XDG_DATA_DIRS
debug3: Ignored env DBUS_SESSION_BUS_ADDRESS
debug3: Ignored env LESSOPEN
debug3: Ignored env DISPLAY
debug3: Ignored env XDG_CURRENT_DESKTOP
debug3: Ignored env LESSCLOSE
debug3: Ignored env COLORTERM
debug3: Ignored env XAUTHORITY
debug3: Ignored env OLDPWD
debug3: Ignored env _
debug2: channel 0: request shell confirm 1
debug2: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug2: channel_input_status_confirm: type 99 id 0
debug2: PTY allocation request accepted on channel 0
debug2: channel 0: rcvd adjust 2097152
debug2: channel_input_status_confirm: type 99 id 0
debug2: shell request accepted on channel 0
Last login: Thu Apr 25 21:55:03 2013 from 192.168.0.14
Have a lot of fun...