iEFdev

Code, Computers & Random Junk

Setup OpenSSH

There was a couple of great articles the other day about SSH and how to configure it in a more secure way.

Before you do anything, you should read the 2 articles a couple of three times, since they both explain everything so good.


If you’re new to SSH… There are 2 sides. A client side and a server side.

  • ssh_config is the corrensponding file for the client. It handles everything you do when you connect to other servers.
  • sshd_config is the corrensponding file for the server. It’s when you or others login to your computer/server. In OS X, that is when you in System Preferences->Sharing activates the “Remote Login”

[Note] To get the correct owner/group of the files from start, you should perform all Terminal commands as: root, and not as a user with: sudo. Except when you create the keys in you home folder when you do it as the user.

OpenSSH

You should upgrade your OpenSSH to the latest (6.7) or at least have 6.5. To check your version, run:

$ ssh -V

# should display something like...
OpenSSH_6.7p1, OpenSSL 1.0.1k 8 Jan 2015

On OS X… If you have an older version (don’t remember wich one the bundled one is now), you can upgrade/install to the latest version with MacPorts, Homebrew or Fink (they also have support for the OS X Keychain) …or compile it yourself. How to do that will take another blog post…

Client

For the client, you’ll need to edit the file: /etc/ssh_config (OS X) or /etc/ssh/ssh_config (standard UNIX location)

First, change/add this:

PasswordAuthentication no
ChallengeResponseAuthentication no

PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-ed25519,ssh-rsa

Make sure you only have Protocol 2 (not Protocol 2,1)

Protocol 2

Add the Ciphers etc…

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
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

At the bottom you can add a section as a comment about the lines for Github, mentioned in one of the articles - just in case you’ll need it later.

# Github needs diffie-hellman-group-exchange-sha1 some of the time but not always.
#Host github.com
#   KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1

Server

First, you can (perhaps should) change the port number from standard Port 22 to something more unique. Since most poeple use 2222 or 2223 as substitution … go another way.

In the file /etc/services you can see all ports and numbers. Scroll down to where it says:

ssh         22/udp
ssh         22/tcp

Further down in the file you’ll see that the ports 778-779, 781-799, 802-809 are all defined as “Unassigned” ports. Pick one of those, or find another empty port.

So, in an example using 785 - change the lines into:

#ssh         22/udp
#ssh         22/tcp
ssh         785/udp
ssh         785/tcp

For OS X, one could set up another service instead, with a launch agent. Can make a post about that later on…


For the server, you’ll need to edit the file: /etc/sshd_config (OS X) or /etc/ssh/sshd_config (standard UNIX location)

First, the port number you changed above. Add it in here:

#Port 22
Port 785

Also make sure it only says Protocol 2. And add the keys.

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

Remove the other lines starting with “HostKey”.

Add the Ciphers etc…

# Ciphers
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
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

If you don’t have 6.7, there was other Ciphers recommended for 6.0 in Aaron Toponce’s article

Then find these values and change them accordingly

LoginGraceTime 1m

PermitRootLogin no

MaxAuthTries 3

RSAAuthentication yes

PubkeyAuthentication yes

IgnoreRhosts yes

PasswordAuthentication no

PermitEmptyPasswords no

ChallengeResponseAuthentication no

You might need to comment out PAM (depending on your OpenSSH installation)

#PAM no

Look for the line “Banner” and change/add:

Banner /etc/ssh/ssh_login.msg

The banner is simular to the motd (message of the day) file. But this one is shown when logging in from the outside. IF you have a motd file, you can use that one - just make a symlink

cd /etc/ssh && sudo ln -sf ../motd  ssh_login.msg

A simple Banner message could look something like:

1
2
3
4
5
6
7
8
9
# ====[ Security Message ]==================================== #
#
#     Restricted Area :: Authorized Users Only
#
#     All connections are monitored and recorded.
#
#     If you are NOT an authorized user - Disconnect NOW!
#
# ============================================================ #

At the bottom of the file you can (or should) add a fake username

# To prevent logins to any account - enter a non-existing user.
AllowUsers NonExistingUserName 

Moduli

To fix the file /etc/moduli (OS X) /etc/ssh/moduli (standard UNIX location). Run the example in the article:

awk '$5 > 2000' /etc/ssh/moduli > "${HOME}/moduli"
wc -l "${HOME}/moduli" # make sure there is something left
mv "${HOME}/moduli" /etc/ssh/moduli

If the file doesn’t exist, create a new one with:

ssh-keygen -G "${HOME}/moduli" -b 4096
ssh-keygen -T /etc/ssh/moduli -f "${HOME}/moduli"
rm "${HOME}/moduli"

Keys

Ok, time to create the default keys.

Creating the default server keys

First remove all old ones since we only need 2 (as defined in sshd_config).

cd /etc/ssh
rm ssh_host_*key*

Now, the command in the article threw a couple of errors at me - because OS X doesn’t have the ssh-askpass. There’s a good script for that (at the end of the post).

You can use the commands in the article:

ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null

Or look in the /usr/local/libexec/sshd-keygen-wrapper, or OS X default location /usr/libexec/sshd-keygen-wrapper and look at the commands in that script… So with our ones it will end up as:

ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N '' -C '' < /dev/null > /dev/null 2> /dev/null
ssh-keygen -q -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N '' -C '' < /dev/null > /dev/null 2> /dev/null

You should also update that file with your new values so it doesn’t create old &/or unnecessary keys. Here’s mine for an install in /usr/local/libexec/sshd-keygen-wrapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env sh
#
# No rsa1
#
# Only ed25519, rsa (4096)
#

# ed25519
[ ! -f /etc/ssh/ssh_host_ed25519_key ] && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N '' -C '' < /dev/null > /dev/null 2> /dev/null

# rsa 4096
[ ! -f /etc/ssh/ssh_host_rsa_key ] && ssh-keygen -q -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N '' -C '' < /dev/null > /dev/null 2> /dev/null

exec /usr/local/sbin/sshd $@

Make sure it has permission to execute

chmod +x /usr/local/libexec/sshd-keygen-wrapper

Creating client keys

If you don’t have an environment for ssh, create one:

mkdir ~/.ssh
touch ~/{authorized_keys,config,known_hosts}

Set the permisstions to 700

chmod -R 700 ~/.ssh/*

For authorized_keys - set 600, or you can even try with 400. This is where you store keys you accept from others to login with.

chmod 400 ~/.ssh/authorized_keys

The RSA key:

ssh-keygen -t rsa -b 4096 -o -a 100 -f ~/.ssh/id_rsa -C "a comment here"

# For the comment you could use something like
# $(whoami)@$(hostname)-$(date "+%F")
# It will render as: username@hostname-2015-01-01

The ed25519 key:

ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/id_ed25519 -C "$(whoami)@$(hostname)-$(date "+%F")"

Using -o will create an “openssh-key” and -a 100 will slow down cracking attempts by iterating the hash function NNN times.

Then of course you’ll need to upload the keys to your server, like you would do normally.

Set permission to your private key(s)

chmod 600 ~/.ssh/id_keyname

When all is done - to add a little more restriction to this, we can set the immutable flag. On OS X you use chflags for that, on Linux, chattr

# OS X/*BSD
sudo chflags uchg ~/.ssh/authorized_keys
sudo chflags uchg ~/.ssh

# to revert use: chflags nouchg

# Linux
chattr +i ~/.ssh/authorized_keys
sudo chattr +i ~/.ssh

# to revert use: chattr -i

To add your key for usage:

ssh-add ~/.ssh/id_keyname

On OS X you use -M to add it to the keychain.

ssh-add -M ~/.ssh/id_keyname

Config file

In the file ~/.ssh/config you can set up like “shortcuts” or “presets” to use. So, for your site it could look something like:

# My site
Host mysite
    User webhostusername
    Hostname yoursite.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_keyname
    Port 22

And then just connect with

ssh mysite

…instead of

ssh -p 22 -i ~/.ssh/id_keyname webhostusername@yoursite.com

Set permission to 600 on this file:

chmod 600 ~/.ssh/config

Now you should have a quite good and secure setup. Remember to:

  • Always protect your key(s) and password(s).
  • Don’t leave your computer on unattended.
  • Use a scrensaver &/or sleep mode with a password lock
  • … etc. etc.


Keys and login problem

Just going to round off with some experience I had with the server on the webhost I use. I created an ed25519 key, and it didn’t work. They only allowed RSA, and DSA (which we don’t use).

Ok, so I created a RSA key instead. Uploaded it and added it to .ssh/authorized_keys on the server. Logged in, with no problem. But, later on setting up my FTP client. It didn’t work. WTF?

After talking to the support and also testing the webhosts online tool, it appears the key needs to be specifically RSA - meaning the start/end block need to include RSA.

Our keys here are generating:

-----BEGIN OPENSSH PRIVATE KEY-----
<the key>
-----END OPENSSH PRIVATE KEY-----

According to my webhost, they use an older OpenSSH - the current one the package repository for the server OS. They are usually really fast with upgrades, so now when the problem is mentioned/brought to them - I guess they’ll fix a newer version soon.


Anyway, after a few attempts with different RSA versions I ended up doing it with openssl genrsa ... instead, and make a public key from there.

$ openssl genrsa -aes256 -out id_foobar 4096
Generating RSA private key, 4096 bit long modulus
.....................................................++
..................++
e is 12345 (0x10001)
Enter pass phrase for id_foobar:
Verifying - Enter pass phrase for id_foobar:

$ ssh-keygen -f id_foobar -y > id_foobar.pub
Enter passphrase: 

That gave me an RSA key with AES-256-CBC

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,12345FOO67890BAR

It was simular to the one generated with the online tool they have, but instead of DES3 it uses AES-256-CBC.

A note on that… If you later on use ssh-keygen to change the password, it’ll set AES-256 back to AES-128 since ssh-keygen doesn’t use AES-256. If that is ok with you, go on …otherwise, generate a new pair with openssl genrsa -aes256 ... to keep using AES-256.

I still wonder why the first one (OPENSSH/RSA) worked in the shell, but not later with my FTP client.

Xtras

As mentioned earlier. OS X doesn’t have ssh-askpass. Not that one really needs it, we have the OS X Keychain, but there is a great script.

Save this in /usr/libexec/ssh-askpass or /usr/local/libexec/ssh-askpass, if that is where your openssh files are.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env bash
#
# /usr/local/libexec/ssh-askpass
#
# Script: ssh-askpass
# Author: Mark Carver
# Created: 2011-09-14
# Licensed under GPL 3.0

# A ssh-askpass command for Mac OS X
# Based from author: Joseph Mocker, Sun Microsystems
# http://blogs.oracle.com/mock/entry/and_now_chicken_of_the

# To use this script:
#   Install this script running INSTALL as root
#
# If you plan on manually installing this script, please note that you will have
# to set the following variable for SSH to recognize where the script is located:
#   export SSH_ASKPASS="/path/to/ssh-askpass"

TITLE="${SSH_ASKPASS_TITLE:-SSH}";
TEXT="$(whoami)'s password:";
IFS=$(printf "\n");

CODE=("on GetCurrentApp()");
CODE=(${CODE[*]} "tell application \"System Events\" to get short name of first process whose frontmost is true");
CODE=(${CODE[*]} "end GetCurrentApp");
CODE=(${CODE[*]} "tell application GetCurrentApp()");
CODE=(${CODE[*]} "activate");
CODE=(${CODE[*]} "display dialog \"${@:-$TEXT}\" default answer \"\" with title \"${TITLE}\" with icon caution with hidden answer");
CODE=(${CODE[*]} "text returned of result");
CODE=(${CODE[*]} "end tell");

SCRIPT="/usr/bin/osascript"
for LINE in ${CODE[*]}; do
    SCRIPT="${SCRIPT} -e $(printf "%q" "${LINE}")";
done;

eval "${SCRIPT}";

Make sure it has permission to execute

chmod +x /usr/local/libexec/ssh-askpass

You can also find the script on Github:


More reading..? Look at the Arch Linux Wiki page. There are always some good reading at the Arch Wiki, even if you don’t use Arch, or Linux at all.

Comments