OpenSSH/Client Configuration Files
Client configuration files can be per user or system wide, with the former taking precedence over the latter and run-time arguments in the shell overriding both. In these configuration files, one parameter per line is allowed. The syntax is the parameter name followed by its value or values. Empty lines and lines starting with the hash (#) are ignored. An equal sign (=) can be used instead of white space between the parameter name and the values. Values are case-sensitive, but parameter names are not. The first value assigned is used. For key files, the format is different.
With either type of file, there is no substitute for reading the relevant manual pages on the actual systems involved, especially because they match the specific versions which are in use.
System-wide Client Configuration Files
System-wide client files set the default configuration for all users of OpenSSH clients on that system. These defaults can be overridden in most cases by the user's own default settings in a local configuration file. Both can be overridden, in many cases, by specifying various options or parameters at run time. The prioritization is as follows:
- run time arguments via the shell
- user's own configuration
- system-wide configuration
The first value obtained is used. The user's own configuration file and the system-wide configuration file can also point to additional configuration files to be included using the Include directive starting with OpenSSH 7.3. The Include directive can be specified anywhere in the configuration file even inside a Match or Host block. Care should be used when nesting configurations.
This file defines all the default settings for the client utilities for all users on that system. It must be readable by all users. The configuration options are described in detail in ssh_config(5).
Below a shortcut is made for connecting to arc.example.org.
Host arc Port 2022 HostName arc.example.org User fred IdentityFile ~/.ssh/id_rsa_arc
So with that configuration, it is enough to enter
ssh arc and the rest of the information gets filled in automatically.
This contains the system-wide list of known host keys used to verify the identity of the remote host and thus hinder impersonation or eavesdropping. This file should be prepared by the system administrator to contain the public host keys of all necessary hosts. It should be world-readable.
See ~/.ssh/known_hosts below for more explanation or see sshd(8) for further details of the format of this file.
This file resides on the server and programs in this file are executed there by ssh(1) when the user logs in, just before the user's shell or designated program is started. It is not run as root, but instead as the user who is logging in. See the sshd(8) manual page in the section "SSHRC" for more information.
User-specific Client Configuration Files
Users can override the default system-wide client settings and choose their own defaults. For situations where the same change is made repeatedly it can make save work to add it to the user's local configuration.
These files reside on the client machine.
The user's own configuration file which, where applicable, overrides the settings in the global client configuration file, /etc/ssh/ssh_config. The configuration options are described in detail in ssh_config(5).
This file must not be accessible to other users in any way. Set strict permissions: read/write for the user, and not accessible by others. It may group-writable if and only if that user is the only member of the group in question.
Local Override of Client Defaults
The file is usually named ~/.ssh/config. However, a different configuration file can be specified at runtime using the -F option. General options intended to apply to all hosts can be set by matching all hosts and should be done at the end of the configuration file. The first match takes precedence, therefore more specific definitions must come first and more general overrides at the end of the file.
Host server1 ServerAliveInterval 200 HostName 203.0.113.76 Host * ExitOnForwardFailure yes Protocol 2 ServerAliveInterval 400
Options given as runtime arguments will override even those in the configuration file. However, not all options can be set or overriden by the user. Those options which may not be set or overridden will be ignored.
This file is local to the user account and contains the known keys for remote hosts. Often these are collected from the hosts when connecting for the first time, but they can be added manually. As with those keys stored in the global file, /etc/ssh/ssh_known_hosts, these keys are used to verify the identity of the remote host, thus protecting against impersonation or man-in-the-middle attacks. With each subsequent connection the key will be compared to the key provided by the remote server. If there is a match, the connection will proceed. If the match fails, ssh(1) will fail with an error message. If there is no key at all listed for that remote host, then the key's fingerprint will be displayed and there will be the option to automatically add the key to the file. This file can be created and edited manually, but if it does not exist it will be created automatically by ssh(1) when it first connects to a remote host.
The ~/.ssh/known_hosts file can use either hashed or clear text host names. Even with hashed names, it can still be searched using ssh-keygen(1) using the -F option.
$ ssh-keygen -F server3.example.com
The default file to be searched will be ~/.ssh/known_hosts and the key is printed if found. A different file can be searched using the -f option. If a key must be removed from the file, the -R option works similarly to search by host and then remove it if found even if the host name is hashed.
$ ssh-keygen -R server4.example.com -f ~/.ssh/known_hosts
When a key is removed, it will then be appended to the file ~/.ssh/known_hosts.old in case it is needed later. Again, see the manual page for sshd(8) for the format of these known_host files.
If a non-default file is used with either -F or -R then the name including the path must be specified using -f. But -f is optional if the default file is intended.
If the global file /etc/ssh/ssh_known_hosts is used then it should be prepared by the system administrator to contain the public host keys of all necessary hosts and it should be world-readable.
Manually Adding Public Keys to ~/.ssh/known_hosts
Manually adding public host keys to known_hosts is a matter of adding one unbroken line per key. How the key is obtained is not important, as long as it is complete, valid, and guaranteed to be the real key and not a fake. The utility ssh-keyscan(1) can fetch a key and ssh-keygen(1) can be used to show the fingerprint for verification. See examples in the cookbook chapter on Public Key Authentication for methods of verification. Again, the corresponding system-wide file is /etc/ssh/ssh_known_hosts
About the Contents of the known_hosts Files
The known_hosts file is for verifying the identity of other systems. ssh(1) can automatically add keys to the user's file, but they can be added manually as well. The file contains a list of public keys for all the hosts which the user has connected to. It can also include public keys for hosts that the user plans to log into but are not already in the system-wide list of known host keys. Usually when connecting to a host for the first time, ssh(1) adds the remote host's public key to the user's known_hosts file, but this behavior can be tuned.
The format is one public key or certificate per unbroken line. Each line in contains a host name, number of bits, exponent, and modulus. At the beginning of the line is either the host name or a hash representing the host name. An optional comment can follow at the end of the line. These can be preceded by an optional marker to indicate a certificate authority, if an SSH certificate is used instead of a SSH key. These fields are separated by spaces. It is possible to use a comma-separated list of hosts in the host name field if a host has multiple names or if the same key is used on multiple machines in a server pool. Here are two examples for hosts with the basic host names:
anoncvs.fr.openbsd.org,184.108.40.206 ssh-rsa AAAA...njvPw== anoncvs.eu.openbsd.org ssh-rsa AAAAB3Nz...cTqGvaDhgtAhw==
Non-standard ports can be indicated by enclosing the host name with square brackets and following with a colon and the port number. Here are three examples referring to hosts listening for SSH on non-standard ports:
[ssh.example.org]:2222 ssh-rsa AAAAB3Nz...AKy2R2OE= [127.0.0.2]:4922 ssh-rsa AAAAB4mV...1d6j= [anga.funkfeuer.at]:2022,[220.127.116.11]:2022 ssh-rsa AAAAB...fgTHaojQ==
Host name patterns can be created using "*" and "?" as wildcards and "!" to indicate negation.
Up to one optional marker per line is allowed. If present it must be either @cert-authority or @revoked. The former shows that the key is a certificate authority key, the latter flags the key as revoked and not acceptable for use.
Server-Side Client Files
These client files reside on the server. By default they are kept in the user's directory. However, the server can be configured to look for them in other locations if needed.
authorized_keys is a one-key-per-line register of public ECDSA, RSA, and ED25519 keys that this account can use to log in with. The file's contents are not highly sensitive, but the recommended permissions are read/write for the user and not accessible by others. As always, the whole key including options and comments must be on a single, unbroken line.
Lines starting with a hash (#) are ignored and can be used as comments. Whitespace separates the key's fields, which are in sequence an optional list of login options, the key type (usually ssh-rsa or better like ecdsa-sha2-nistp256), the key itself encoded as base64, and an optional comment.
If a key is followed by an annotation, the comment does not need to be wrapped in quotes. It has no effect on what the key does or how it works. Here is an annotated key, the comment having been generated with the -C option ssh-keygen(1):
ssh-rsa AAAAB3NzaC1yc2EAAA...zAiVaOFy5Lwc8Lo+Jk= Fred @ Project FOOBAR
Keys can be preceded by a comma-separated list of options to affect what happens upon successful login. The first key below forces the session to launch tinyfugue automatically, the second forcibly sets the PATH environment variable:
command="/usr/bin/tinyfugue" ssh-rsa AAAAB3NzaC1yc2EAAA...OFy5Lwc8Lo+Jk= environment="PATH=/bin:/usr/bin/:/opt/gtm/bin" ssh-rsa AAAAB3N...4Y2t1j=
The format of authorized_keys is described in the sshd(8) manual page. Old keys should be deleted from the file when no longer needed. The server can specify multiple locations for authorized_keys. See the next section, Server-Side Client Key Login Options, for details.
By default this file does not exist. If it is specified in sshd_config(5), it contains a list of names which can be used in place of the username when authorizing a certificate. This option is useful for role accounts, disjoint account namespaces and "user@realm"-style naming policies in certificates. Principals can also be specified in authorized_keys.
If the server is configured to accept user-supplied, automatic changes to environment variables as part of the login process, then these changes can be set in this file.
If the server, the environment file and an authorization key all try to change the same variable, the file environment takes precedence over what a key might contain. Either one will override any environment variables that might have been passed by ssh(1) using SendEnv.
Authentication keys stored in authorized_keys can also be used to set variables. See also the AcceptEnv and PermitUserEnvironment directives in the manual page for sshd_config(5).
This is a script which is executed by sh(1) just before the user's shell or command is started. It is not run if ForceCommand is used. The script is run after reading the environment variables. The corresponding global file, /etc/ssh/sshrc, is not run if the user's rc script exists.
Local User's Public / Private Key Pairs
Users might have a variety of their own ECDSA, Ed25519, and RSA. DSA is considered deprecated. The time has passed for DSA keys and they are no longer considered safe and should be replaced with better keys. Individual user accounts can maintain their own list of keys or certificates for authentication or to verify the identity of remote hosts. The most common location is in the ~/.ssh/ directory. The naming convention for keys is only a convention but recommended to follow anyway. Public keys usually have the same name as the private key, but with .pub appended to the name. Trouble can arise if the names of the public and private keys do not match. If there is more than one key pair, then ssh-keygen(1) can use the -f option when generating keys to produce a useful name along with the -C option which embeds a relevant comment inside the public key.
Users can authenticate using a private key stored on their system, or even one fetched from a smartcard, if the corresponding public key is stored in authorized_keys on the remote system. The authorized_keys file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. The private keys, however, are very sensitive and should not be readable or even visible to other accounts. They should never leave the client and should certainly never be put on the server. See the chapter on Public Key Authentication for more discussion and examples.
The keys can be preceded by a comma-separated list of options. The whole key must be on a single, unbroken line. No spaces are permitted, except within double quotes. Any text after the key is considered a comment. See the section above on the authorized_keys file for more discussion. The authorized_keys file is a one-key-per line register of public RSA, Ed25519, and ECDSA keys that can be used to log in as this user.
User-specified Host-based Authentication Configuration is also possible using the ~/.shosts, ~/.rhosts, ~/.ssh/environment, and ~/.ssh/rc files.
Public Keys – ~/.ssh/id_ecdsa.pub ~/.ssh/id_ed25519.pub ~/.ssh/id_rsa.pub
These are only the default names for the public keys. Again, it can be a good idea to give more relevant names to keys.
Public keys are mainly used on the remote server for key-based authentication. Public keys are not sensitive and are allowed to be readable by anyone, unlike the private keys, but don't need to be. A public key, minus comments and restriction options, can be regenerated from a private key if lost. So while it can be useful to keep backups of the public key, it is not essential unlike for private keys.
Private Keys – ~/.ssh/id_ecdsa ~/.ssh/id_ed25519 ~/.ssh/id_rsa
These are only the default names for private keys. Private keys are always considered sensitive data and should be readable only by the user and not accessible by others. In other words, they use mode 0600. The directory they are in should also have mode 0700 or 0500. If a private key file is accessible by others, ssh(1) will ignore it.
It is possible to specify a passphrase when generating the key which will be used to encrypt the sensitive part of this file using AES128. Until version 5.3, the cipher 3DES was used to encrypt the passphrase. Old keys using 3DES that are given new passphrases will use AES128 when they are modified.
New private keys cannot be regenerated from public keys if they are lost. Nor can a new passphrase be set if the current one is forgotten. Gone is gone, unlike the public keys, which can be regenerated from an existing private key. If the private key is lost or forgotten then a whole new key pair must be generated and deployed.
These files might be encountered on very old or out of date systems but not on up-to-date ones.
.rhosts is a legacy from rsh containing a local list of trusted host-user pairs that are allowed to log in. Login requests matching an entry were granted access.
See also the global list of trusted host-user pairs, /etc/hosts.equiv
rhosts can be used as part of host-based authentication. Otherwise it is recommended not to use rhosts for authentication, there are a lot of ways to misconfigure the .rhosts file.
Legacy DSA Keys ~/.ssh/id_dsa ~/.ssh/id_dsa.pub
Deprecated DSA keys might be found named as id_dsa and id_dsa.pub, but any usage should be tracked down. If DSA keys are found, the whole key pair should be replaced with a better type.
Legacy SSH1 Protocol Keys ~/.ssh/identity ~/.ssh/identity.pub
The files identity and identity.pub were for SSH protocol version 1, and thus deprecated. If found they should be investigated as to what, if anything, uses them and why. Then once any remaining usage is resolved they should be removed and replaced with newer key types.
Server-Side Client Key Login Options
The login options available for use in the local user authorized keys file might be overridden or blocked by the server's own settings. However, within that constraint, the following options can be used.
Specifies that the listed key is a certification authority (CA) trusted to validate signed certificates for user authentication. Certificates may encode access restrictions similar to key options. If both certificate restrictions and key restrictions are present, then the most restrictive union of the two is applied.
Specifies a program and its options to be executed when the key is used for authentication. This is a good way of forcing a program to restrict a key to a single, specific operation such as a remote backup. However, TCP and X11 forwarding are still allowed unless explicitly disabled elsewhere.
The program is run on a PTY if the client requests it, otherwise the default is to run without a TTY. The default, running without a TTY, provides an 8-bit clean channel. If the default has been changed, specify no-pty to get an 8-bit clean channel. If no programs are allowed, then use an empty string "" to prevent anything from running.
no-pty,command="" ssh-rsa AAAAB3NzaC1yc2EAAA...OFy5Lwc8Lo+Jk=
If only one program is allowed, with specific options, then it can be spelled out explicitly.
restrict,command="/usr/bin/svnserve -t --tunnel-user=fred" ssh-ed25519 AAAAC3NzaC1lZDI1NT...skSUlrRPoLyUq
Quotes provided in the program's options must be escaped using a backslash. ('\')
command="sh -c \"mysqldump db1 -u fred1 -p\"" ssh-rsa AAAAB3NzaC1yc...Lwc8OFy5Lo+kU=
This option applies to execution of the shell, another program, or a subsystem. Thus any other programs specified by the user are ignored when command is present. However, the program originally specified by the client remains available as the environment variable SSH_ORIGINAL_COMMAND. That can be used by a script in a multiple-choice case statement, for example, to allow the account to select from a limited range of actions.
Sets the value of an environment variable when this key is used to log in. It overrides default values of the variable, if it exists. This option can be repeated to set multiple variables. This option is only allowed if the PermitUserEnvironment option is set in the SSH server's configuration. The default is that it is disabled. This option used to be disabled automatically when UseLogin is enabled, but UseLogin has been deprecated.
Either the canonical name of the remote host or its IP address required in addition to the key. Addresses and host names can be listed using a comma-separated list of patterns, see PATTERNS in ssh_config(5) for more information on patterns, or use the CIDR address/masklen notation.
no-agent-forwarding / agent-forwarding
This option forbids the authentication agent from forwarding the key when it is used for authentication. Alternately, it allows agent forwarding even if it was otherwise previously disabled by the restrict option.
no-port-forwarding / port-forwarding
Forbids TCP forwarding and any port forward requests by the client will return an error when this key is used for authentication. Alternately, override the restrict option and allow port forwarding. See also permitopen.
no-pty / pty
TTY allocation is prohibited and any request to allocate a PTY will fail. Alternately, TTY allocation is permitted, even if previously disabled by the restrict option.
no-user-rc / user-rc
Use the no-user-rc option in authorized_keys to disable execution of ~/.ssh/rc . Alternately, use user-rc to override the restrict option.
no-X11-forwarding / x11-forwarding
Prevent X11 forwarding when this key is used for authentication and requests to forward X11 will return an error. Alternately, override the restrict option and allow X11 forwarding.
Limits local port forwarding (
ssh -L) to only the specified host and port. IPv6 addresses can be specified with an alternative syntax: host/port. Multiple permitopen options may be used and must be separated by commas. No pattern matching is performed on the specified host names, they must be literal host names or IP addresses. Can be used in conjunction with agent-forwarding.
Specify a list of names that may be used in place of the username when authorizing a certificate trusted via the TrustedCAKeys option described in sshd_config(5).
Disable all options, such as TTY allocation, port forwarding, agent forwarding, user-rc, and X11 forwarding all at once. Specific options can then be explicitly allowed on an individual basis.
Select a specific tun(4) device on the server. Otherwise when a tunnel device is requested without this option the next available device will be used.
Designate an expiration date for the key in the system's configured time zone, written as YYYYMMDD or YYYYMMDDHHMM[SS]. Otherwise the key will be considered valid indefinitely.
When working with keys there are some basic, hopefully common sense, actions that should take place to prevent problems. The two most beneficial approaches are to use sensible names for the key files and to embed comments. The -f option for ssh-keygen(1) allows a custom name to be set. The -C option allows a comment to be embedded in both the public and private keys. With the comment inside the private key, it can be regenerated automatically if a replacement public key is ever made using the -y option.
Other than that, there are three main rules of thumb for managing keys:
- Keys should use strong passphrases. If autonomous logins are required, then the keys should be first loaded into an agent and used from there. See ssh-add(1) to get started there. It uses ssh-agent(1) which many systems have installed and some have running by default.
- Keys should always be stored in protected locations, even on the client side. This is especially important for private keys. The private keys should not have read permissions for any user or group other than their owner. They should also be kept in a directory that is not accessible by anyone other than the owner in order to limit exposure.
- Old and unused keys should be removed from the server. In particular, keys without a known, valid purpose should be removed and not allowed to accumulate. Using the comment field in the public key for annotation can help eliminate some of the confusion as to the purpose and owner once some time has passed. Along those lines, keys should be rotated at intervals. Rotation means generating new key pairs and removing the old ones. This gives a chance to remove old and unused keys. It is also an opportunity to review access needs, whether access is required and if so at what level.
Following the principle of least privilege can limit the chance for accidents or abuse. If a key is only needed to run a specific application or script, then its login options should be limited to just what is needed. See sshd(8) for the "AUTHORIZED_KEYS FILE FORMAT" section on key login options. For root level access, it is important to remember to configure /etc/sudoers or /etc/doas.conf appropriately. Access there can be granted to a specific application and even limit that application to specific options.
One major drawback to keys is that they never expire and are valid indefinitely in principle. In contrast, certificates can be assigned a validity interval with an end date, after which they can no longer be used.