OpenSSH

From Segfault
Jump to: navigation, search

Installation

To get the OpenSSH version:

CVSROOT=anoncvs@anoncvs.mindrot.org:/cvs cvs get openssh
mv openssh openssh_portable-cvs

Or, via Git:

git clone git://anongit.mindrot.org/openssh.git openssh-git

Install prerequisites & build:

apt-get install autoconf libpam0g-dev libwrap0-dev         # Debian
yum install autoconf tcp_wrappers-devel pam-devel          # Fedora
cd openssh_portable-cvs
autoheader && autoconf
./configure --prefix=/opt/openssh --with-pam --with-tcp-wrappers --with-Werror
make

sudo make install

Configuration

We could make some changes[1] to the server and to the client configuration.

Server

Protocol                        2
HostKey                         /etc/ssh/ssh_host_ed25519_key
HostKey                         /etc/ssh/ssh_host_rsa_key

PermitRootLogin                 without-password
PasswordAuthentication          no
ChallengeResponseAuthentication no

Ciphers                         chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs                            hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
KexAlgorithms                   curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

To support older clients[2][3], add the following:

       MACs                    [...],hmac-sha1
       KexAlgorithms           [...],diffie-hellman-group-exchange-sha1

To set certain configuration options for trusted clients, use the Match directive:

Match Address 10.10.0.0/24
      PasswordAuthentication yes

As we enabled diffie-hellman-group-exchange key exchange algorithms, we should also generate stronger moduli:

ssh-keygen -G moduli.candidates -b 4096                   # Takes about 6 min on a i7-3632QM, output was ~200 MB
ssh-keygen -f moduli.candidates -T moduli                 # Takes about 2 hrs on a i7-3632QM

sudo mv moduli.tested /etc/ssh/moduli && sudo chown root:root /etc/ssh/moduli
rm moduli

To re-generate the host keys (skipping ECDSA again[4]):

ssh-keygen -t ed25519     -N "" -f ssh_host_ed25519_key
ssh-keygen -t rsa -b 4096 -N "" -f ssh_host_rsa_key

Client

On the client side, similar changes may be needed:

Host *  
       Protocol                2
       Ciphers                 chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
       MACs                    hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
       KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

       TCPKeepAlive            yes
       ServerAliveInterval     20
       IdentitiesOnly[5]       yes
       HashKnownHosts          yes
       ForwardX11              no
#      VisualHostKey           yes
#      ProxyCommand            /usr/bin/nc -X connect -x 10.36.6.86:8080 %h %p
#      EscapeChar              none

Again, if the SSH client doesn't understand current algorithms[2][3], enable:

       MACs                    [...],hmac-sha1
       KexAlgorithms           [...],diffie-hellman-group-exchange-sha1

Usage

autossh

 autossh -M 0 -f -N ssh.example.com

We're using -M 0 to disable autossh's monitoring capabilities and the use TCPKeepAlive feature from OpenSSH to monitor the connection:

 $ cat ~/.ssh/config
 Host ssh.example.com
       PasswordAuthentication  no
       TCPKeepAlive    yes
       LogLevel        ERROR
       User            alice
       IdentityFile    ~/.ssh/ssh-key
       LocalForward    1234 localhost:80

With systemd having won the system service management init war, let's create a service file[6] so autossh is started during bootup:

$ cat /etc/systemd/system/autossh@example.service
[Unit]
Description=autossh: %I
Documentation=file:///usr/share/doc/autossh/README.service man:autossh(1)
After=network.target

[Service]
User=nagios
Environment="AUTOSSH_GATETIME=0"
EnvironmentFile=/etc/autossh/%i.conf
ExecStart=/usr/bin/autossh $OPTIONS

[Install]
WantedBy=multi-user.target

Create a configuration file:

$ cat /etc/autossh/example.conf 
OPTIONS=-M 0 -N ssh.example.com

Start and enable with:

systemctl start autossh@example && systemctl enable autossh@example

Agent Forwarding

This will forward the local authentication agent connection to the remote host, to be used for a later connection. This has the advantage that the SSH key for the remote host does not need to be copied to the intermediate system.

On the server side, AllowAgentForwarding has to be enabled (default for many installations).

Note: there are security concerns though.[7][8]

$ ssh-add -c ~/.ssh/remotehost-key                              # Use "-c" to have key usage confirmed[9]
Enter passphrase for ~/.ssh/remotehost-key:
 
$ ssh -A jump.example.com                                       # ForwardAgent=yes

jump$ ssh-add -l
4096 1e:60:9d:99:f6:20:c5:d3:23:f6:57:1c:e9:f4:15:9c ~/.ssh/remotehost-key (RSA)

jump$ ls -l ~/.ssh/remotehost-key
ls: cannot access ~/.ssh/remotehost-key: No such file or directory

jump$ ssh -v remotehost
[...]
debug1: Offering public key: ~/.ssh/remotehost-key
debug1: Server accepts key: pkalg ssh-rsa blen 535
remotehost$

Escapes

According to ssh(1), several escape characters are supported:

~.      Disconnect.
~^Z     Background ssh.
~#      List forwarded connections.
~&      Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.
~?      Display a list of escape characters.
~B      Send a BREAK to the remote system
~C      Open command line.  Currently this allows the addition of port forwardings using the
        -L, -R and -D options (see above).  It also allows the cancellation of existing remote
        port-forwardings using -KR[bind_address:]port.
        !command allows the user to execute a local command if the PermitLocalCommand
        option is enabled in ssh_config(5).  Basic help is available, using the -h option.
~R      Request rekeying of the connection

Listing and modifying existing forwarded connections seem to be very interesting. Let's see how this goes.

$ ssh -L 1234:localhost:80 malice
malice% ~#
   The following connections are open:
   #2 client-session (t4 r0 i0/0 o0/0 fd 8/9 cc -1)

Hm, this isn't too descriptive :-\ Let's open another port forward:

malice% ~C
ssh> -h
Commands:
     -L[bind_address:]port:host:hostport    Request local forward
     -R[bind_address:]port:host:hostport    Request remote forward
     -D[bind_address:]port                  Request dynamic forward
     -KR[bind_address:]port                 Cancel remote forward

ssh> -L1235:localhost:80
Forwarding port.
malice% ~C

And it worked:

$ wget http://localhost:1235 -qO-
Hello, world!

gnome-keyring

As gnome-keyring cannot handle ECDSA[10] or Ed25519[11] keys yet[12][13], we might have to use something else.[14][15]

keychain

Install keychain:

sudo apt-get install keychain

Disable gnome-keyring:

sudo mv /etc/xdg/autostart/gnome-keyring-ssh.{desktop,disabled}

Create startup items:

$ cat ~/.config/autostart/gnome-keyring-ssh.desktop
[Desktop Entry]
Type=Application
Name=SSH Key Agent (keychain)
Exec=keychain –quiet –agents ssh

$ cat ~/.config/autostart/gnome-keyring-gpg.desktop
[Desktop Entry]
Type=Application
Name=GPG Key Agent (keychain)
Exec=keychain –quiet –agents gpg 

Logout and login again, then tell your shell to pick-up the keychain environment variables:

echo 'eval $(keychain --eval --quiet)' >> ~/.bashrc

Adding and removing keys:

$ ssh-add .ssh/ed25519-key
Enter passphrase for .ssh/ed25519-key: 
Identity added: .ssh/ed25519-key (.ssh/ed25519-key)

$ ssh-add -l
256 11:43:de:1a:39:c8:96:71:d3:54:75:1c:3d:15:41:ac .ssh/ed25519-key (ED25519)

$ ssh-add -d .ssh/ed25519-key
Identity removed: .ssh/ed25519-key (.ssh/ed25519-key.pub)

ssh-agent

We could also use ssh-agent with some systemd trickery:[16]

TBD

known_hosts

List all known fingerprints (length in bits, MD5 fingerprint, hashed hostkey, type)

$ ssh-keygen -l -f ~/.ssh/known_hosts | tail -2
 256 37:8c:a0:67:78:53:4b:da:d7:38:fe:14:10:d1:90:aa |1|h6o4y26eF7Vtc/ypRvdrrvxshQ (ED25519)
2048 c5:50:3a:b4:fa:b5:2d:6f:2e:9e:ea:15:de:cf:25:21 |1|sG5je3ToIqDIIyPLG0sqKrU5tM (RSA)

Note: for some OpenSSH versions, one has to specify -E md5 to show the fingerprints as an MD5 sum, otherwise it may display SHA256 fingerprints.

Display the fingerprint of the hostkey of a known host. The -f known_hosts_file switch is optional here and ~/.ssh/known_hosts is assumed:

$ ssh-keygen -l -F login.example.org
# Host login.example.org found: line 12 type ED25519
256 37:8c:a0:67:78:53:4b:da:d7:38:fe:14:10:d1:90:aa |1|h6o4y26eF7Vtc/ypRvdrrvxshQ (ED25519)

Note: because HashKnownHosts is most likely set in ssh_config, all entries are hashed and thus will not reveal any hostnames. Only known hostnames can be queried.[17]

Remove a known hostkey:

$ ssh-keygen -R login.example.org                               # Repeat for the host's IP address as needed
# Host login.example.org found: line 12 type RSA
~/.ssh/known_hosts updated.
Original contents retained as ~/.ssh/known_hosts.old

Display the hostkey of a known host, not stored in known_hosts_file:

$ ssh-keyscan -t ed25519 login.example.org
# login.example.org SSH-2.0-OpenSSH_6.7p1
login.example.org ssh-ed25519 AAAAC3NzCa1lDZI1NT5EAAAAILMG6q9z8HuoBWehII1/aOBgom5piBip635juE50v+QP

Find all hosts from the file ssh_hosts which have new or different key from a sorted known_hosts file:

$ ssh-keyscan -t ed25519 ssh_hosts | sort -u - ~/.ssh/known_hosts | diff known_hosts.sorted -
# login.example.org SSH-2.0-OpenSSH_6.7p1
76a77
> login.example.org ssh-ed25519 AAAAC3NzCa1lDZI1NT5EAAAAILMG6q9z8HuoBWehII1/aOBgom5piBip635juE50v+QP

Port Forwarding

Forward a remote port to a local one. For example, only the remote site may be connected to an internal webserver:

local$ ssh -L 1234:box.intra:80 webserver
local$ wget http://localhost:1234 -qO -
Hello, I'm an intranet webserver!

Forward a local port to a remote site. For example, the remote site may not have access to the internet:

local$ ssh -R 1234:localhost:8080 box
box$ http_proxy=localhost:1234 wget http://example.org -O-
Hello, world!

xauth

SSH connections sometimes complain about:

 Warning: untrusted X11 forwarding setup failed: xauth key data not generated
 Warning: No xauth data; using fake authentication data for X11 forwarding.

Somehow xauth(1) is involved:

 $ strings `which ssh` | grep -i bin/xauth
 /usr/X11R6/bin/xauth

But our xauth(1) is located somewhere else:

 $ which xauth 
 /opt/X11/bin/xauth

The trick is tp specify the correct location in ssh_config(5):

 XAuthLocation           /opt/X11/bin/xauth

Links

References