Set up key authentication
It’s recommended to handle authentication of SSH connections via keys, instead of a password. Most of the steps only need to be executed on the server machine.
Prerequisites
Client & Server:
Create a new directory
C:\Users\%USERNAME%\.ssh(Windows) or~/.ssh(Linux/macOS, where it should already exist).Within it, create these empty files (no suffix):
configServer only:
authorized_keys
Server & Client: Create key pair
Start the Key Generator via the command line (Windows) or shell (Linux/macOS)
$ ssh-keygen -t ed25519
Hint
To customize the key pair even further you may also run
$ ssh-keygen -t ed25519 -C "$USER@$(scutil --get LocalHostName) - `date +%Y%m%d`"
$ ssh-keygen -t ed25519 -C "$USER@$HOSTNAME - `date +%Y%m%d`"
Run in git bash (comes with Git for Windows):
$ ssh-keygen -t ed25519 -C "$USERNAME@$COMPUTERNAME - `date +%Y%m%d`"
Set the path and filename of the keys (default: ~/.ssh/id_ed25519). In case, you don’t need separate keys pairs for different connections, you don’t need to specify a custom path or filename.
Warning
I experienced errors from the server upon connection, stating the clients private key contains an invalid format:
Load key "/Users/arnewohletz/.ssh/imac_ed25519.pub": invalid format
This issue was resolved by not defining a custom named key pair (like
imac_ed25519in the example above), but using the default name (here:id_ed25519).Enter a passphrase to encrypt the private key, if needed (more secure, but might conflict with applications using the key).
Check if the
.sshdirectory contains both the private and the public key file (*.pub).
Server: Set permissions
To prevent the authentication keys from being manipulated, only the respective user must be able to interact with them.
Hint
The commands are used on Linux/macOS only. See here, how to permissions on Windows: https://www.howtogeek.com/301768/how-to-take-ownership-of-files-and-folders-in-windows/
On Windows, it is highly recommended to use the included PowerShell scripts to check or set the proper access rights. Open a PowerShell instance as administrator, navigate to the OpenSSH directory and run:
PS C:\> powershell.exe -ExecutionPolicy Bypass -File .\FixHostFilePermissions.ps1
Linux/macOS only: Make sure, your home directory is only writable by the respective user:
$ ls -l /home $ ls -l /Users
should output
drwxr-xr-xfor the user’s directory.If not, execute:
$ chmod 755 ~/
It is important that
$HOME/.ssh(%USERPROFILE%\.sshon Windows) and theauthorized_keysfile have the correct permissions and owner:$USERPROFILE$\.sshmust be owned by the user$USERPROFILE$\.sshmust only be writable, readable and executable by the ownerauthorized_keysmust be owned by the userauthorized_keysmust only be writable and readable by the owner
$ chown $USER ~/.ssh $ chown $USER ~/.ssh/authorized_keys $ chown $USER ~/.ssh/config
$ chmod 700 ~/.ssh $ chmod 600 ~/.ssh/authorized_keys $ chmod 600 ~/.ssh/config
Client: Set permissions
Same as for the server, each connecting client needs to set the correct permissions for the key pair. OpenSSH is very sensitive here and does not hint you to wrong permissions, when trying to establish a connection, so always make sure, those are set correctly.
Hint
The commands are used on Linux/macOS only. See here, how to permissions on Windows: https://www.howtogeek.com/301768/how-to-take-ownership-of-files-and-folders-in-windows/
On Windows, it is highly recommended to use the included PowerShell scripts to check or set the proper access rights. Open a PowerShell instance as administrator, navigate to the OpenSSH directory and run:
PS C:\> powershell.exe -ExecutionPolicy Bypass -File .\FixUserFilePermissions.ps1
OpenSSH does not allow the key pair files to be editable by anyone except the owner. The private key must also be protected (here: id_ed25519):
$ chmod 700 ~/.ssh/id_ed25519 $ chmod 700 ~/.ssh/id_ed25519.pub
Server: Set-up key authentication
Add your private key to the authentication agent (it will handle the authorizations via keys):
$ ssh-addHint
In case you received the message
Could not open a connection to your authentication agent.
start the ssh-agent via
eval `ssh-agent -s`
To autostart the ssh-agent add this content to your
~/.bashrcor~/.zshrcfile:# auto-start ssh-agent if [ ! -S ~/.ssh/ssh_auth_dock ]; then eval `ssh-agent` >/dev/null ln -sf "$SSH_AUTH_DOCK" ~/.ssh/ssh_auth_sock fi export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock ssh-add -l >/dev/null || ssh-add
In case you are using a private key using a different name and/or path, you must pass it:
$ ssh-add /path/to/custom_private_key_file
Hint
On Windows, in case you see this message:
Error connecting to agent: No such file or directory
you must manually start the SSH Agent Service first via
powershell.exe Set-Service -Name ssh-agent -StartupType Manual powershell.exe Start-Service ssh-agent
from an administrator shell.
On the client, open the public key file (e.g. id_ed25519.pub) and copy the entire content into the
authorized_keysfile on the server (should be a single line starting with ssh-rsa and ending with <username>@<hostname>). Save and close both files.Important
The public key of each client, that wants to authorize itself, needs to be added into a separate line within the server’s
authorized_keysfile. Each time, this file is edited, the SSH server must be restarted.This can also be done from the client via:
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub <HOST_USERNAME>@<HOST>
Open the OpenSSH config file in a text editor:
Windows:
C:\ProgramData\ssh\sshd_configLinux:
/etc/ssh/sshd_configmacOS:
/private/etc/ssh/sshd_config
Change the following content:
PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys
Important
Don’t disable the password authentication (
PasswordAuthentication) until the key authentication has been proven to work.Windows only: Make sure, the following content is commented out (starts with #):
# Match Group administrators # AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
Save and close the file.
Restart the SSH Server.
Windows:
Type Windows+R, type
services.mscand confirm to open the service manager.Right-click the service and select Restart.
Ensure that the
OpenSSH SSH Serverservice’s startup type is set to Automatic (right click service and choosePropertiesto edit).
Linux:
$ service ssh restart
macOS:
If using Homebrew installation:
$ brew services start ssh
If using preinstalled SSH:
$ sudo launchctl stop com.openssh.sshd $ sudo launchctl start com.openssh.sshd
Client: Set-up key authentication
Open the
configfile inside the.sshdirectory.Insert the following content (adapt path to private key file a.k.a. Identity file, if necessary):
On Windows (adapt USERNAME):
Host * IdentityFile C:\Users\<USERNAME>\.ssh/id_ed25519
On Linux/macOS:
Host * IdentityFile ~/.ssh/id_ed25519
This enables the client to use its private key file as an identity to authenticate towards the server.
Test key authentication
Connect to the server (using the server username):
$ ssh <HOST_USERNAME>@<HOST>
The connection should be established without asking for the password, stating that the public key was used for authentication.
If the connection is not successful, check the log output, by running the connection in verbose mode:
$ ssh <HOST_USERNAME>@<HOST> -v
Configure connections
This is a convenience feature. Right now, connecting to a host system is done, for example, like this:
$ ssh -i ~/.ssh/all_my_keys/imac.ed25519.pub someuser@some.host.system
To shorten this you may create a config file to store all these parameters.
On the client machine, create the config file in your
.sshdirectory (if not already present):$ touch ~/.ssh/config
Open the file and add your config, for example, like this:
Host imac HostName imac.fritz.box User arnewohletz IdentityFile ~/.ssh/id_ed25519 Host someotherhost HostName some.other.host User some.user IdentityFile ~/.ssh/id_ed25519You may specify settings for any number of host systems. Check out all possible settings via:
$ man ssh_config
Save and close the file.
You may connect to a specified host system by only stating its name:
$ ssh imac
Hint
To list all configured hosts, specify this command under an alias in your
~/.bashrc or ~/.zshrc file:
alias ssh-hosts="cat ~/.ssh/config | grep -E '^\s*Host\s' | awk '{print $2}'"
When running ssh-hosts in a new shell, it will print all configured hosts.
On Windows create a Batch script in a folder defined in your PATH variable,
for example ssh-hosts.bat and insert the following content:
@echo off
type %USERPROFILE%\.ssh\config | findstr /R "^Host "