Skip to content

SSH

SSH is a secure protocol and the most common way of remotely administering Linux servers and other equipment. SSH uses symmetrical encryption, which means a single key encrypts outbound messages to and inbound messages from the other participant.

The SSH session is established in two stages:

  1. Negotiate session key
  2. Authenticate the user

The symmetrical key used for the session, called the session key, is negotiated through the asymmetrical Diffie-Hellman key exchange protocol. This algorithm combines private data with public data from the other participant to produce the identical, session key, and the encryption used for the rest of the connection is called binary packet protocol.

The simplest and least secure method of authentication is password-based. Although the password is sent through the encryption, it is still considered vulnerable to brute-force attacks.

SSH key pairs, which are asymmetric, are recommended. These are what is generated by ssh-keygen, and stored in $HOME/.ssh with names that reflect the encryption algorithm, i.e. "id_rsa" and "id_rsa.pub", etc. The public key, used to encrypt data for the private key, can be freely shared. In fact, this is the purpose of ssh-copy-id, to share the public key. However the private key, which is used for decryption, must be kept secret.

The client sends an ID for the key pair it wants to authenticate with to the server. The server then checks the authorized_keys file of the requested account for the ID. A random number is generated by the server, encrypted with the public key, and sent to the client. The client then decrypts the random number and combines it with the shared session key and calculates the MD5 hash. This hash is then sent back to the server, which checks the calculation.

Note that the SSH server is named openssh-server in Ubuntu repos and the service is named ssh, as opposed to sshd on Red Hat systems.

Tasks

Port forwarding

Port forwarding is accomplished in one of two ways, local or remote with respect to the server not the client.

  • Local (-L): connections to the client are forwarded through the SSH tunnel to the SSH server. This technique is used to provide functionality similar to a VPN, where remote access is made possible to content on a private network, such as file shares or web applications that are not exposed publicly.
  • Remote (-R)...
  • Dynamic

Here, a private web application served locally on ssh-server will be served on the client at the same port. The first "localhost" can actually be omitted, since the connection will be exposed on localhost host by default and is almost universally.

The confusing part is the second "localhost", because that is actually in reference to the ssh server itself.

ssh -L localhost:80:localhost:80 ssh-server
It is actually possible to forward a request to another host on ssh-server's network, creating a jump box. Here a connection on the client's localhost:81 is forwarded to ssh-server, which then sends it to 192.168.1.1:80.
ssh -L 81:192.168.1.1:80 ssh-server

X forwarding

ssh -Y user@host
Have remote system use local computer {me.luna.edu}'s X display
export DISPLAY=me.luna.edu:0

fail2ban

<!-- On the first ban, f2b creates a new chain named f2b-name where "name" is the name of the jail, as defined in the config.

/etc/fail2ban/action.d/iptables.conf
actionstart = <iptables> -N f2b-<name>

This chain becomes the target of banned IPs, which are somehow added (although I don't know how). -->

Fail2ban is an intrusion prevention framework written in Python and that runs as a service. It can be installed from most distributions' repos.

The jail is a key concept in f2b that couples filters and actions definitions.

Fail2ban is configured through .ini-format configs found in /etc/fail2ban. It is recommended not to edit the default configs ending in .config but rather to create a custom config called jail.local which will be automatically loaded by the service.

Example jail
[sshd]
enabled=true
port=ssh
filter=sshd
logpath=/var/log/auth.log
maxretry=0
findtime=300
bantime=3600

Failed logins can be checked by running lastb, and connections are also logged to SystemD.

journalctl -ru sshd

# Display banned IPs
fail2ban-client banned

# Manually ban an IP
fail2ban-client set sshd banip $IPADDRESS

# Manually unban an IP
fail2ban-client unban $IPADDRESS

Configuration

Server and client configuration both use the same set of keywords that can be defined inline on invocation or in config files.

Client configuration

Host home
    HostName 192.168.1.1
    User root
    Port 50022
    SetEnv BAT_THEME=OneHalfLight # (1)
    LocalForward 8080 localhost:8080 # (2)
  1. SetEnv allows environment variables to be set in a remote session. However, these same environment variables must be explicitly specified in AcceptEnv key of the server configuration. This entry will set a specific syntax highlighting theme for use on the bat CLI utility.
    AcceptEnv BAT_THEME
    
  2. The use of LocalForward here is equivalent to the use of the -L option at the command-line:
    ssh -L 8080:localhost:8080 $SERVER
    

SSH to a transient server

To prevent recording a transient server to the client's known hosts file, for example when SSHing to many hosts from a single client, say while managing a corporate environment.

UserKnownHostsFile /dev/null # (1)
StrictHostKeyChecking no # (2)

  1. UserKnownHostsFile
  2. StrictHostKeyChecking

Canonical hostname

In corporate environments with verbose domain names, canonical hostnames can be configured to automatically append repetitive domain names ("canonicalize") to destination hosts.

In this example, any connection made to a hostname beginning with "server" will append "example.com".

Host server*
    CanonicalDomains example.com # (1)
    CanonicalizeHostname always # (2)

  1. CanonicalDomains
  2. CanonicalizeHostname

Server configuration

/etc/ssh/sshd_config is the configuration for the SSH server daemon.

Disable cleartext passwords

PasswordAuthentication no

Disable root login

PermitRootLogin no

Commands

endlessh

Log verbosity
# Silent
endlessh

# Normal
endlessh -v

# Debug
endlessh -vv
Log verbosity
LogLevel 0 # silent
LogLevel 1 # normal
LogLevel 2 # debug

ssh-add

ssh-add adds private key identities to the OpenSSH authentication agent, ssh-agent. Notably, ssh-add requires the SSH_AUTH_SOCK environment variable set by ssh-agent.

When run without arguments, it adds the private keys found in ~/.ssh, i.e.

  • id_rsa
  • id_dsa
  • id_ecdsa
  • id_ecdsa_sk
  • id_ed25519
  • id_ed25519_sk
eval $(ssh-agent); ssh-add <(cat "$(keyFile.secureFilePath)")

ssh-agent

ssh-agent is a helper program that keeps track of identity keys and passphrases, allowing them to be used without further interaction, similar to SSO. Running it produces output that is meant to be used with the eval command in order to set the environment variables SSH_AGENT_PID and SSH_AUTH_SOCK, which are needed by ssh-add.

eval $(ssh-agent); ssh-add <(cat "$(keyFile.secureFilePath)")

If only a single process is running, the -k option will kill it (although it is possible to fork multiple ssh-agent processes).

ssh-agent -k # (1)

  1. Equivalent to
    kill $SSH_AGENT_PID
    

ssh-copy-id

This command copies the SSH public key to a specified account's ~/.ssh/authorized_keys file.

In Windows, this command is not available, so a workaround is to simply pipe the public key over SSH itself.

type $env:USERPROFILE\.ssh\id_rsa.pub | ssh {IP-ADDRESS-OR-FQDN} "cat >> .ssh/authorized_keys"

ssh-keygen

Generate host keys
sudo ssh-keygen -A