14 KiB
SSH
- TL;DR
- Server installation on Windows
- Key Management
- Client configuration
- Server configuration
- SSHFS
- Troubleshooting
- Further readings
TL;DR
# Create new keys.
ssh-keygen -t 'rsa' -b '4096'
ssh-keygen -t 'dsa'
ssh-keygen -t 'ecdsa' -b '521'
ssh-keygen -t 'ed25519' -f "${HOME}/.ssh/keys/id_ed25519" -C 'test@winzoz'
ssh-keygen -f "${HOME}/.ssh/id_rsa" -N '' -C 'batch-generated key with no password'
# Remove elements from the known hosts list.
ssh-keygen -R 'pi4.lan'
ssh-keygen -R '192.168.1.237' -f '.ssh/known_hosts'
ssh-keygen -R 'pi.lan' -f "${HOME}/.ssh/known_hosts"
# Change the password of a key.
ssh-keygen -f "${HOME}/.ssh/id_rsa" -p
# Show keys' fingerprint.
ssh-keygen -l -f "${HOME}/.ssh/id_ed25519"
# Show certificates' content.
ssh-keygen -L -f 'path/to/ssh.cert'
# Load keys from '${HOME}/.ssh' and add them to the agent.
eval $(ssh-agent) && ssh-add
# List keys added to the agent, by fingerprint.
ssh-add -l
# List keys added to the agent, by public key.
ssh-add -L
# Authorize keys for passwordless access.
ssh-copy-id 'host.fqdn'
ssh-copy-id -i "${HOME}/.ssh/id_rsa.pub" 'user@host.fqdn'
# Preload trusted keys.
ssh-keyscan 'host.fqdn' >> "${HOME}/.ssh/known_hosts"
# Connect to a directly unreachable host by tunnelling sessions.
ssh -t 'bastion-host' ssh 'unreachable-host'
# Mount remote folders.
sshfs 'nas.lan:/mnt/data' 'Data' \
-o 'auto_cache,reconnect,defer_permissions,noappledouble,volname=Data'
# Validate keys.
ssh-keygen -yef 'path/to/key'
openssl rsa -check -in 'path/to/key' -noout
Server installation on Windows
Needs Administrator privileges.
Tested on Window 11 22H2.
Via PowerShell:
-
Install the server component:
Add-WindowsCapability -Online -Name OpenSSH.Server -
Start and enable the service:
Start-Service sshd Set-Service -Name sshd -StartupType 'Automatic' -
Verify the firewall rule has been created automatically during the installation:
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) { Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..." New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 } else { Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists." }
Via GUI:
-
Open Settings > Apps, then select Optional features
-
Scan the list to see if the OpenSSH server is not already installed
-
At the top of the page, select View features in the Add an optional feature field
-
Find OpenSSH Server and select Install
-
Once the setup completes, return to Apps > Optional features and confirm OpenSSH is now listed
-
Open the Services desktop app:
- Select Start
- Type
services.mscin the search box - Select the Services app or just press ENTER
-
In the details panel, double-click OpenSSH SSH Server to enter its properties
-
On the General tab, from the Startup type drop-down menu, select Automatic to enable the service
-
In the same tab, select Start to start the service
Key Management
Create a new key:
ssh-keygen -t 'rsa' -b '4096'
ssh-keygen -t 'dsa'
ssh-keygen -t 'ecdsa' -b '521'
ssh-keygen -t 'ed25519' -f '.ssh/id_ed25519' -C 'test@winzoz'
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\test/.ssh/id_ed25519.
Your public key has been saved in C:\Users\test/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:lFrpPyqTy0d30TfnN0QRY678LnyCzmvMDbl1Qj2/U/w test@winzoz
The key's randomart image is:
+--[ED25519 256]--+
| +o.o++|
| ==*O|
| . .X*|
| o . +=|
| S S +..==|
| . .+..*E|
| + ...o|
| .+ .o = |
| =+ .o .|
+----[SHA256]-----+
Remove a host from the list of known hosts:
ssh-keygen -R 'pi4.lan'
ssh-keygen -R '192.168.1.237' -f '.ssh/known_hosts'
ssh-keygen -R 'raspberrypi.lan' -f '.ssh/known_hosts'
Host pi4.lan found: line 5
/home/user/.ssh/known_hosts updated.
Original contents retained as /home/user/.ssh/known_hosts.old
Change password of a key file
ssh-keygen -f "${HOME}/.ssh/id_rsa" -p
Client configuration
When connecting to a host, the SSH client will use settings:
- from the command line,
- from the user's
~/.ssh/configfile, - from the
/etc/ssh/ssh_configfile
Unless noted otherwise, for each parameter, only the first obtained value will be used
(first-come-first-served).
Values should hence appear from the most specific to the most generic, both by file and by position in those
files.
The configuration files contain sections separated by Host specifications
Those sections are only applied to hosts that match one of the patterns given in each specification.
The file contains keyword-argument pairs, one per line.
Lines starting with # and empty lines are interpreted as comments.
Arguments may optionally be enclosed in double quotes (") in order to represent arguments containing spaces.
Configuration options may be separated by whitespace, or optional whitespace and exactly one =. The latter format is
useful to avoid the need to quote whitespace when specifying configuration options using the ssh, scp, and sftp -o
option.
Keywords are case-insensitive and arguments are case-sensitive.
Host targaryen
HostName targaryen.example.com
User john
Port 2322
IdentityFile ~/.ssh/targaryen.key
LogLevel INFO
Compression yes
Host *ell
user oberyn
sendenv BE_SASSY
StrictHostKeyChecking no
Host * !martell
LogLevel INFO
StrictHostKeyChecking accept-new
UserKnownHostsFile /dev/null
Host *
User root
Compression yes
SendEnv -LC_* -LANG*
SetEnv MYENV=itsvalue
Append domains to a hostname before attempting to check if they exist
CanonicalizeHostname yes
CanonicalDomains xxx.auckland.ac.nz yyy.auckland.ac.nz
Host *.xxx.auckland.ac.nz
User user_xxx
Host *.yyy.auckland.ac.nz
User user_yyy
Optimize connection handling
# Keep a connection open for 30s and reuse it when possible.
# Save the above pipe in a safe directory, and use a hash of different data to
# identify it.
# source: https://www.cyberciti.biz/faq/linux-unix-reuse-openssh-connection/
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist 30s
Integrate with GnuPG
# In BASH and alike.
export SSH_AUTH_SOCK=$(gpgconf --list-dirs 'agent-ssh-socket')
# In FISH.
set -x 'SSH_AUTH_SOCK' (gpgconf --list-dirs 'agent-ssh-socket')
# In ~/.ssh/config.
# Value is from `gpgconf --list-dirs 'agent-ssh-socket'`.
IdentityAgent ~/.gnupg/S.gpg-agent.ssh
Server configuration
The daemon's default configuration file is /etc/ssh/sshd_config.
Reload the server upon config file change. No need to restart it.
The configuration file contains keyword-argument pairs, one per line.
Unless noted otherwise, for each keyword, the first obtained value is used (first-come-first-served).
Lines starting with # and empty lines are interpreted as comments.
Arguments may optionally be enclosed in double quotes (") in order to represent arguments containing spaces.
Keywords are case-insensitive and arguments are case-sensitive.
Some Linux distributions (e.g., Debian, OpenSUSE) started including .conf files in /etc/ssh/sshd_config.d/ and
/usr/etc/ssh/sshd_config.d/ as first thing in the base configuration file:
# To modify the system-wide sshd configuration, create a "*.conf" file under
# "/etc/ssh/sshd_config.d/" which will be automatically included below.
# Don't edit this configuration file itself if possible to avoid update
# problems.
Include /etc/ssh/sshd_config.d/*.conf
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Include /usr/etc/ssh/sshd_config.d/*.conf
This avoids issues from updates overwriting the default file and allows user configurations to override defaults in a cleaner way.
Change port
Port 2222
Disable password authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
Permit root login
PermitRootLogin yes
Conditional blocks
Only a subset of keywords may be used in a Match block. Check the
SSHD_CONFIG(5)man page.
Match Address 192.168.111.0/24
PasswordAuthentication no
PermitRootLogin no
SSHFS
Notable options:
auto_cacheenables caching based on modification times;reconnectreconnects to the server;defer_permissionsworks around the issue where certain shares may mount properly, but cause permissions denied errors when accessed (caused by how Mac OS X's Finder translates and interprets permissions;noappledoubleprevents Mac OS X to write.DS_Storefiles on the remote file system;volnamedefines the name to use for the volume.
Usage:
sshfs \
-o 'auto_cache,reconnect,defer_permissions,noappledouble,volname=Data'
'user@nas.lan:/path/to/remote/dir' \
'/path/to/local/dir'
Installation
# Mac OS X requires `macports`, since `brew` does not offer 'sshfs' anymore
sudo port install 'sshfs'
Troubleshooting
No matching host key type found
Error message example:
Unable to negotiate with XXX port 22: no matching host key type found. Their offer: ssh-rsa.
Cause: the server only supports the kind of RSA with SHA-1, which is considered weak and deprecated in newer SSH versions.
Workaround: explicitly set your client to use the specified key type adding
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
to your ~/.ssh/config like so:
Host azure-devops
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
+ HostkeyAlgorithms +ssh-rsa
+ PubkeyAcceptedAlgorithms +ssh-rsa
Solution: update the SSH server.
Further readings
SSH_CONFIG(5)man pagessh_configexampleSSHD_CONFIG(5)man pagesshd_configdefaultssshd_configexample- ssh-agent
- Use GPG keys for SSH authentication
Sources
- Use SSHFS to mount a remote directory as a volume on OSX
- Using the SSH config file
- How to list keys added to ssh-agent with ssh-add?
- Multiple similar entries in ssh config
- How to enable SSH access using a GPG key for authentication
- How to perform hostname canonicalization
- How to reuse SSH connection to speed up remote login process using multiplexing
- Get started with OpenSSH for Windows
- Restrict SSH login to a specific IP or host
- Stick with security: YubiKey, SSH, GnuPG, macOS
- How to check if an RSA public / private key pair match