SSH in Linux

SSH Connection

Connection uses the following syntax

ssh + username + host

E.g.

ssh andrei@192.168.0.2

If it is your first connection - the warning will appear

The authenticity of host '192.168.56.101 (192.168.56.101)' can't be established. ECDSA key fingerprint is SHA256:db8az/qbrWOJWvNRv2d9UHaDBnnUHanJ9Svca9vFx7c. Are you sure you want to continue connecting (yes/no/[fingerprint])?

When you choose yes file ~/.ssh/known_hosts will get a new entry similar to this:

|1|abcdef+abcdefghijklmnopqrst=|abcdefghijklmnopqrstuvwxyz1= ssh-rsa abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzB1234567

Usually file known_hosts has the following format (entries are separated with spaces)

{server-id} ssh-rsa {public-key-string} {comment}

Thus

abcdef+abcdefghijklmnopqrst=|abcdefghijklmnopqrstuvwxyz1=

It is a server name hash.

Three elements are written here separated by spaces: the hash of the server name, the name of the asymmetric algorithm used, and the server's public key. Let's go through them one by one.

Generate Key Pair

The first step is generating a key pair. Usually this is done on the client machine. For example, on your laptop.

The main command ssh-keygen will create a 2048-bit RSA key pair. For greater reliability you can add the -b 4096 flag

Run

ssh-keygen -b 4096

To generate a key in /home/$(whoami)/.ssh

or

sudo ssh-keygen -b 4096

To generate a key in /home/root/.ssh

Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa):

You need to make up a key name.

I will name the key andrei-key101 and I will save it to the current directory.

Enter file in which to save the key (/root/.ssh/id_rsa): andrei-key101 Enter passphrase (empty for no passphrase): Enter same passphrase again:

You need to enter the password twice. If you need one. Usually you do not.

Your identification has been saved in andrei-key101 Your public key has been saved in andrei-key101.pub The key fingerprint is: SHA256:abcd/abcdefghijklmnopqrstuvwxyz1234567890ab root@urn-su The key's randomart image is: +---[RSA 4096]----+ |=o oo++ | |= oo o. = o | |+ | |Oo=o . . | |B+.o S . | |+o.o | |+.0. . | |o+= . E | |+=oo. . . | +----[SHA256]-----+

The keys are ready. I saved them to the current directory, so I will see them by running ls

ls

andrei-key101 andrei-key101.pub

It is important to remember that if you generate a key for another user you need to take care of the correct access rights to that key.

Which Key Goes Where?

.pub send the key to the remote machine

keep the private key on your client

Pass the key to the remote host

After the keys are created you need to pass .pub the key to the remote host.

This can be done in several ways; let's start with the utility ssh-copy-id

ssh-copy-id

I prefer to use it with the flag -i and to specify the path to the required key

sudo ssh-copy-id -i ~/.ssh/andrei-key.pub andrei@192.168.0.2

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/andrei/.ssh/andrei-key.pub" The authenticity of host '192.168.0.2 (192.168.0.2)' can't be established. ECDSA key fingerprint is SHA256:abcdefgh1234567890abcdefgh1234567890abc+def. Are you sure you want to continue connecting (yes/no/[fingerprint])?

Enter yes

Are you sure you want to continue connecting (yes/no/[fingerprint])? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys andrei@192.168.0.2's password:

Enter the password

Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'andrei@192.168.0.2'" and check to make sure that only the key(s) you wanted were added.

Now on host 192.168.0.2 in the file /home/andrei/.ssh/authorized_keys a new entry has appeared like this

ssh-rsa AAAAB3NzaC1y … lseP/jXcq … Uydr/2CwQ &hellip ++TpY19pHqD/AnhL … Az62T/Ipyx … 8U2T andrei@host.andrei.com

The … sign replaces long sequences of random characters to save space.

You can test the key with the command

ssh -i ~/.ssh/mykey user@host

In our case

ssh -i ~/.ssh/andrei-key andrei@192.168.0.2

If you did not set a password for the key, you will get to the remote host without any extra steps

Last login: Sun Jan 10 16:48:27 2021 from 192.168.0.1

Find the OpenSSH version in Linux

To find the OpenSSH version in your Linux distribution execute

ssh -V

OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017

Run a command from a script on a remote computer

If the ssh connection comes from a bash script , and you also need to run a number of commands after connecting, it is enough to list these commands separated by a semicolon

#!/bin/bash ssh andrei@192.168.0.2 "ls;cd /home/andrei/bash_scripts;ls;ip a;cal"

If you need to run a command that requires sudo, try the -t flag

#!/bin/bash ssh -t andrei@192.168.0.2 "sudo apt upgrade"

known_hosts

The list of known hosts is in the file known_hosts

Full path:

/home/$(whoami)/.ssh/known_hosts

Usually the file known_hosts has the following format (entries are separated by spaces) ( details )

{server-id} algorithm {public-key-string} {comment}

Algorithm examples: ssh-rsa, ssh-dss, ssh-ed25519, ecdsa-sha2-nistp256 …

Example line:

|1|abcdef+abcdefghijklmnopqrst=|abcdefghijklmnopqrstuvwxyz1= ssh-rsa abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzB1234567

Thus

abcdef+abcdefghijklmnopqrst=|abcdefghijklmnopqrstuvwxyz1=

This is a hash of the server name.

ssh-rsa

This is the encryption algorithm

abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzB1234567

This is the host's public key

Create an SSH tunnel

Tunnels are usually created to redirect traffic. An SSH tunnel is the same thing as SSH port forwarding.

Suppose you want to direct traffic from your localhost (127.0.0.1) to a remote host 192.168.0.2.

On the remote host you have a user named andrei and you know his password.

First you need to decide on the ports on the local host and on the remote one.

Suppose you chose 9119 for the local and 9200 for the remote hosts.

That is, you want everything going to localhost:9119 to be redirected to 192.168.0.2:9200

Run

ssh -L 9119:192.168.0.2:9200 andrei@192.168.0.2

The authenticity of host '192.168.0.2 (192.168.0.2)' can't be established.
ECDA …
…
andrei@192.168.0.2's password:
Last login: Sun Jan 31 13:23:00 2021

Check the ip by running

ip a

If you need a tunnel with graphical interface support, X Window System use flag -X

ssh -X -L 9119:192.168.0.2:9200 andrei@192.168.0.2

Demonstration

The tunnel is created, do not close the terminal. Open two new terminals or two new tabs in the old one.

You have two empty terminals, both on the local host. Let's call them 1 and 2.

From terminal 2 we will connect to the remote host 192.168.0.2 over ssh and listen on port 9200 using nmap

ssh andrei@192.168.0.2
nmap -l 9200

On terminal 1, using nmap, we will send a message to port 9119 of the local host. This is the port we configured for forwarding.

nmap localhost 9119

Let's enter any text

heihei.ru

Open terminal 2, the same text should appear there

heihei.ru

List of all open SSH tunnels

To get the list of tunnels opened specifically by ssh execute

sudo lsof -i -n | egrep '\<ssh\>'

ssh 14695 andrei 3u IPv4 230080 0t0 TCP 192.168.0.1:46356->192.168.0.2:ssh (ESTABLISHED) ssh 14695 andrei 4u IPv6 230103 0t0 TCP [::1]:9119 (LISTEN) ssh 14695 andrei 5u IPv4 230104 0t0 TCP 127.0.0.1:9119 (LISTEN)

For some reason the output of this command differs under practically identical conditions.

Below is an example of the second variant. If you know why this happens, write in the comments.

ssh 15151 andrei 3u IPv4 239364 0t0 TCP 192.168.0.1:46464->192.168.0.2:ssh (ESTABLISHED) ssh 15151 andrei 4u IPv6 239380 0t0 TCP [::1]:mxit (LISTEN) ssh 15151 andrei 5u IPv4 239381 0t0 TCP 127.0.0.1:mxit (LISTEN) ssh 15151 andrei 9u IPv6 239428 0t0 TCP [::1]:mxit->[::1]:54306 (ESTABLISHED)

Close all SSH tunnels

To close everything related to ssh you can run

sudo killall ssh sshd

This method is only good if you work alone, for example on some virtual machine.

Run SSH in the background

There are several ways to run an ssh connection in the background, that is, to free the current terminal.

-L, screen, tmux, nohup

nohup helped me run ssh in the background from a script, so let's start with it

nohup ssh user@host "cd scripts;python3 my_script.py $ARG1 $ARG2; exit" &

What it was needed for: Python the script first opened one ssh connection from subprocess there a command was run to start memory consumption monitoring and nothing else was needed from this connection, but it was necessary to make new connections with load from another script.

To leave the first connection without interrupting the memory consumption monitoring, nohup had to be added before ssh, and & had to be put at the very end

SSH_MSG_USERAUTH_BANNER

A client that connects to the ssh server can be shown a banner SSH_MSG_USERAUTH_BANNER

Specification rfc4252

Run

sudo vi /etc/issue.net

And edit the file by adding your own banner

\S Kernel \r on an \m ######################################################### # ANDREYOLEGOVICH.RU and URN.SU # #########################################################

Open sshd_config and specify the path to the banner

sudo vi /etc/ssh/sshd_config
/banner

# no default banner path #Banner none

This banner will be shown BEFORE authorization, that is, while the password is being entered

To create a banner that will be shown after a successful login execute

sudo vi /etc/motd

######################################################### # YOU ARE HERE: urn.su/linux/ssh.php # #########################################################

After editing the files, restart sshd

sudo systemctl restart sshd.service

Converting certificates

Let's look at a simple example: you retrieved from the database a certificate MIIC4jCCAc … A7A6Rpt8V9Q== , but it is not formatted and does not pass validation

The certificate is, of course, longer; I put an ellipsis to save space and your time.

Run

echo 'MIIC4jC … 7A6Rpt8V9Q==' | base64 -d | openssl x509 -inform der

Or, if you need to work with files, save the original certificate to the file raw_cert

echo MIIC4jC … 7A6Rpt8V9Q== > raw_cert
cat raw_cert | base64 -d | openssl x509 -inform der > cert
cat cert

-----BEGIN CERTIFICATE-----
MIIC4jC … 7A6Rpt8V9Q==
-----END CERTIFICATE-----

The same result could have been achieved by carefully adding -----BEGIN CERTIFICATE----- at the beginning and -----END CERTIFICATE----- at the end of the file, but it is not always that simple.

Existing OpenSSH versions

OpenSSH 8.2 FEATURE: Add FIDO/U2F Support OpenSSH 8.1, released in October 2019 ssh, sshd, ssh-agent: add protection for private keys at rest in RAM against speculation and memory side-channel attacks like Spectre, Meltdown and Rambleed. OpenSSH 8.0, released in April 2019 SECURITY: CVE-2019-6111 related to scp tool and protocol allowing to overwrite arbitrary files in the scp client target directory OpenSSH 7.9, released in October 2018 allow key revocation lists (KRLs) to revoke keys specified by SHA256 hash OpenSSH 7.8, released in August 2018 Incompatible changes: ssh-keygen write OpenSSH format private keys by default instead of using OpenSSL's PEM format. OpenSSH 7.7, released in February 2018 FEATURE: Add "expiry-time" option in sshd for authorized_keys files to allow for expiring keys. OpenSSH 7.6, released in October 2017 FEATURE: Add RemoteCommand option FEATURE: Add SyslogFacility option to ssh matching the equivalent option in sshd FEATURE: ssh client reverse dynamic forwarding -R OpenSSH 7.5, released in March 2017 BUGFIX: This is a mainly a bugfix release. OpenSSH 7.4, released Template:Release date and age sshd(8): Add a sshd_config DisableForwarding option OpenSSH 7.3, released August 01, 2016 FEATURE: Adds ProxyJump option (-J) FEATURE: Add an Include directive for ssh_config(5) files OpenSSH 7.1: August 20, 2015 This is a bugfix release. OpenSSH 7.0: August 11, 2015 The focus of this release is primarily to deprecate weak, legacy and unsafe cryptography. OpenSSH 6.9: July 1, 2015 BUGFIX: This is primarily a bugfix release. OpenSSH 6.8: March 18, 2015 Added new hostkeys@openssh.com extension to facilitate public key discovery and rotation for trusted hosts (for transition from DSA to Ed25519 public host keys) AuthenticationMethods=publickey,publickey to require that users authenticate using two different public keys OpenSSH 6.7: October 6, 2014 The default set of ciphers and MACs has been altered to remove unsafe algorithms. In particular, CBC ciphers and arcfour* are disabled by default. Compile-time option to not depend on OpenSSL Add support for Unix domain socket forwarding OpenSSH 6.6: March 16, 2014 This is primarily a bugfix release. OpenSSH 6.5: January 30, 2014 Added new ssh-ed25519 and ssh-ed25519-cert-v01@openssh.com public key types (available since 2005 but more popular since some suspicious that NSA had chosen values that gave them an advantage in factoring public-keys) Added new chacha20-poly1305@openssh.com transport cipher Added curve25519-sha256@libssh.org key exchange FEATURE: ssh, added Match keyword for ssh_config that allows conditional configuration to be applied FEATURE: client-side hostname canonicalisation: CanonicalDomains, CanonicalizeFallbackLocal, CanonicalizeHostname, CanonicalizeMaxDots and CanonicalizePermittedCNAMEs. Add a new private key format that uses a bcrypt KDF OpenSSH 6.4: November 8, 2013 This release fixes a security bug with AES-GCM OpenSSH 6.3: September 13, 2013 This release is predominantly a bugfix release OpenSSH 6.2: March 22, 2013 Add a GCM-mode for the AES cipher, similar to RFC 5647 Added support for encrypt-then-mac MAC modes Added support for multiple required authentication methods Added support for Key Revocation Lists (KRL) OpenSSH 6.1: August 29, 2012 This is primarily a bugfix release. Enables pre-auth sandboxing by default Finds ECDSA keys in ssh-keyscan and SSHFP DNS records by default now OpenSSH 6.0: April 22, 2012 This is primarily a bugfix release. OpenSSH 5.9: September 6, 2011 Introduce sandboxing of the pre-auth privilege separated child OpenSSH 5.8: February 4, 2011 OpenSSH 5.7: January 24, 2011 Added support for elliptic curve cryptography for key exchange as well as host/user keys, per RFC 5656 OpenSSH 5.6: August 23, 2010 Added a ControlPersistoption to ssh_config OpenSSH 5.5: April 16, 2010 OpenSSH 5.4: March 8, 2010 Disabled SSH protocol 1 default support. Clients and servers must now explicitly enable it. Added PKCS11 authentication support for ssh(1) (-I pkcs11) Added Certificate based authentication Added "Netcat mode" for ssh(1) (-W host:port). Similar to "-L tunnel", but forwards instead stdin and stdout. This allows, for example, using ssh(1) itself as a ssh(1) ProxyCommand to route connections via intermediate servers, without the need for nc(1) on the server machine. Added the ability to revoke public keys in sshd(8) and ssh(1). While it was already possible to remove the keys from authorised lists, revoked keys will now trigger a warning if used. OpenSSH 5.3: October 1, 2009 OpenSSH 5.2: February 23, 2009 OpenSSH 5.1: July 21, 2008 Added a MaxSessions option to sshd_config OpenSSH 5.0: April 3, 2008 OpenSSH 4.9: March 30, 2008 Added chroot support for sshd(8) Create an internal SFTP server for easier use of the chroot functionality OpenSSH 4.7: September 4, 2007 - Ubuntu 8.04 OpenSSH 4.6: March 9, 2007 OpenSSH 4.5: November 7, 2006 OpenSSH 4.4: September 27, 2006 OpenSSH 4.3: February 1, 2006 Added OSI layer 2/3 tun-based VPN (-w option on ssh(1)) OpenSSH 4.2: September 1, 2005 OpenSSH 4.1: May 26, 2005 OpenSSH 4.0: March 9, 2005 OpenSSH 3.9: August 18, 2004 Implement session multiplexing. ControlMaster option Added a MaxAuthTries option to sshd, allowing control over the maximum number of authentication attempts permitted per connection Added IdentitiesOnly option to ssh which specifies that it should use keys specified in ssh_config, rather than any keys in ssh-agent Re-introduce support for PAM password authentication OpenSSH 3.8: February 24, 2004 OpenSSH 3.7.1: September 16, 2003 OpenSSH 3.7: September 16, 2003 rhosts authentication has been removed in ssh(1) and sshd(8). OpenSSH 3.6.1: April 1, 2003 OpenSSH 3.6: March 31, 2003 OpenSSH 3.5: October 14, 2002 OpenSSH 3.4: June 26, 2002 OpenSSH 3.0: Improved Kerberos support in protocol v1 (KerbIV and KerbV) OpenSSH 2.9.9: OpenSSH 2.5.1p1: February 19, 2001 SkeyAuthentication absoleted, use ChallengeResponseAuthentication instead. OpenSSH 1.2.2p1: March 5, 2000

Article author: Andrei Olegovich