As mentioned at the beginning of the chapter, the behavior of the server, sshd, may be controlled at three levels:
Compile-time configuration (Chapter 4) is accomplished when sshd is built. For example, a server may be compiled with or without support for rhosts authentication.
Serverwide configuration, the subject of this chapter, is performed by a system administrator and applies to a running instance of the server. For instance, an administrator may deny SSH access by all hosts in a given domain or make the server listen on a particular port.
Serverwide configuration may depend on compile-time configuration. For example, a server's hostbased authentication options work only if the server is compiled with hostbased authentication support included. Otherwise, the options have no effect. We identify such dependencies throughout the book. Figure 5-1 highlights the serverwide configuration tasks.
Per-account configuration (Chapter 8) is performed by the end user, specifically, the owner of the account to which an SSH connection has been requested. For example, users may permit or deny access to their own accounts from particular hosts, overriding the serverwide configuration.
Suppose user deborah on the machine client.unc.edu invokes an SSH client. The client's behavior is determined by several factors:
The compile-time options selected when the software was built
The machinewide client configuration file on client.unc.edu
User deborah's own client configuration file
The command-line options used by deborah when invoking the client
An SSH server running on server.unc.edu accepts deborah's connection to the account charlie. The server's behavior is determined by the compile-time options used when
sshd was built, the machinewide server configuration file on server.unc.edu, the command-line options used when the SSH server was run, and charlie's personal server configuration file (e.g., an authorized_keys file), plus several files that set environment variables for the successful login session.
With three levels of server configuration, and multiple entry points for modifying the behavior at each level, things can get complicated. In particular, different options may work together or cancel each other. For example, user charlie can configure his account on server.unc.edu to accept connections from client.unc.edu, while the system administrator of server.unc.edu can configure the SSH server to reject them. (In this case, Charlie loses.) Administrators must understand not only how to configure the server themselves, but also how their choices interact with compile-time and per-account settings.
Serverwide configuration is accomplished in two ways: through a server configuration file, or through command-line options. In a server configuration file, numerous configuration variables, called keywords , may have their values set. For example, to set the TCP port on which the server will listen, a configuration file can contain the line:
Port 1022
You may also separate the keyword and value by an equals sign (with optional whitespace):
Port = 1022
The configuration file is typically /etc/ssh/sshd_config for OpenSSH or
/etc/ssh2/sshd2_config for
Tectia.[45] The file contains keywords and their values, as in the
Port
example, with one pair
(keyword and value) per line. Keywords are case-insensitive: Port
, port
, and PoRt
are all treated identically. Comments
may appear in the file as well: any line beginning with a hash sign
(#) is a comment:
# This is a comment
Comments cannot be appended to keyword lines. For example, the following does not work:
Port 1022 # This comment is not allowed here, so don't do this
Empty lines (or lines containing only whitespace) are also ignored as comments.
To use a configuration file other than the default, invoke sshd with the -f command-line option, providing the alternative filename as an argument:
$ sshd -f /usr/local/ssh/my_config
Tectia supports some extensions to configuration files that we cover in a detailed case study: [11.6]
Structured comments at the top of the server configuration
file that define syntax rules for the rest of the file. For
example, the REGEX-SYNTAX
metaconfiguration statement selects one of several different
regular expression standards: grep style (egrep
), filename globbing (zsh_fileglob
), and others.
Alternative configuration files specific to particular
local accounts or remote hosts. The keywords UserSpecificConfig
and HostSpecificConfig
define the
associations between subconfiguration files and the affected accounts and hosts,
respectively. For example, the line:
# Tectia UserSpecificConfig smith /usr/local/ssh/smith.config
states that all connection attempts to the smith account must adhere to the configuration in file /usr/local/ssh/smith.config.
Tectia has unusual rules for quoted strings, namely, that quotes are largely ignored. The following sshd2_config lines are equivalent:
# Tectia Port 1022 Port "1022" Port "10"22
After you've changed a server configuration file (or constructed an initial version of the file), how do you know it's going to work and have the effects you intend? Later, when you upgrade the server to a more recent version, how can you detect incompatible changes in the meaning of keywords that you've been using?
The most thorough way to verify the server configuration, of course, is to run the server exactly as you plan to deploy it, and test all of the functionality that you expect to use. This kind of testing can be time-consuming, however, and you might not be able to afford interrupting service on a busy production machine.
Alternately, you could use some other test machine, or run the server on a different port [5.3.3.1] while the old configuration is still being used on the original machine. These approaches are almost as good, but they can be complicated if the server configuration refers to network characteristics of the machine where it will be deployed, or by firewalls that block access to nonstandard ports.
Both OpenSSH and Tectia have test features to help with these situations, or to just provide a quick check of the server configuration before more rigorous testing.
If the OpenSSH server is started with the -t (test) option, it starts up, checks the validity of its host keys and the server configuration file, and then immediately exits without performing any other actions. When no problems are found, the server silently returns a zero exit status to indicate successful operation. Otherwise, error messages are printed to the standard error and the server exits with a nonzero status:
# OpenSSH $ sshd -t /etc/ssh/sshd_config: line 33: Bad configuration option: BlurflPox /etc/ssh/sshd_config: Bad yes/no argument: maybe
The server must be run by a user (typically root) who has read access to the host key files and the server configuration file. Any other server options can be used in conjunction with -t, such as -h options [5.3.1.1] to specify new host key files, the -f option [5.2.1] to specify a new configuration file, or -d options [5.9] for more detailed debugging output (even if no errors are detected).
Tectia provides a separate program, sshd-check-conf, to check server configuration files.[46] Supply a hypothetical user and remote host, and sshd-check-conf will describe its access control decisions for them:
# Tectia $ sshd-check-conf rebecca@client.friendly.org Verifying rebecca@client.friendly.org[10.1.2.3]... Logins from client.friendly.org[10.1.2.3] allowed. Hostbased can be used from client.friendly.org[10.1.2.3]. Login by user rebecca allowed. User rebecca will not be chrooted. TCP forwarding by user rebecca allowed.
sshd-check-conf is especially helpful for verifying policies described by complicated patterns and subconfiguration files. [11.6.2] It uses the same code as sshd to parse the server configuration files and understands metaconfiguration information. [11.6.1]
If any errors are detected, sshd-check-conf prints messages to the standard error, as sshd would:
# Tectia $ sshd-check-conf rebecca@client.friendly.org Warning: Unrecognized configuration parameter 'BlurflPox'. Warning: Illegal IdleTimeout value 'never'. Warning: Failed to parse some variables from config file '/etc/ssh2/sshd2_config'. FATAL: Failed to read config file "/etc/ssh2/sshd2_config"
It is not necessary to run sshd-check-config as root, as long as the server configuration files can be read. By default, /etc/ssh2/sshd2_config is used if the program is run by the superuser, or $HOME/.ssh2/sshd2_config otherwise. As for sshd, the -f option specifies a different configuration file:
# Tectia $ sshd-check-conf -f /tmp/sshd2_config_new rebecca@client.friendly.org
The hypothetical SSH sessions are described by one or more
[user
@]host
arguments on the command line. A numerical user ID can be used in
place of a username, or the username can be omitted entirely to
check only the remote host. In this case,
sshd-check-conf substitutes UNKNOWN
for the username when it analyzes
the access controls:
# Tectia $ sshd-check-conf client.friendly.org Verifying UNKNOWN@client.friendly.org[10.1.2.3]... Logins from client.friendly.org[10.1.2.3] allowed. Hostbased can be used from client.friendly.org[10.1.2.3]. Login by user UNKNOWN denied.
An IP address can be used instead of a hostname: both the hostname and IP address are checked.
If a hostname resolves to multiple IP addresses, then only the first IP address is used, and a warning is printed by sshd-check-conf.
Here's a brash one-liner to check the access controls for all local users:
# Tectia $ sed -e "s/:.*/@`hostname`/" /etc/passwd | xargs sshd-check-conf
You can also run sshd-check-conf
interactively: just don't supply any
[user@]host
arguments on the command
line. The program prompts for [user@]host
strings, permits Emacs-style editing of the strings as you enter
them (using the GNU readline library), and maintains a history of
previously entered values.
In addition, sshd-check-conf recognizes a dump command to print keywords and values for the server configuration:
# Tectia $ sshd-check-conf ... ssh-check-conf>dump
# General Port = 22 ProtocolVersionString = 4.1.3.2 SSH Secure Shell MaxConnections = 0 ... # Authentication and authorization AllowedAuthentications = publickey,password IgnoreRhosts = no ... # Forwardings ForwardX11 = yes ForwardAgent = yes ... # Miscellaneous user setup UserConfigDirectory = %D/.ssh2 PrintMOTD = yes ... sshd-check-conf>quit
$
Tectia's sshd-check-conf dump command prints most configuration keywords and values, but not all of them.
To exit from interactive mode, use the quit
command, or type the end-of-file
character (usually ^D), or just kill the program
(typically with ^C). The quit
and dump
commands are case-insensitive.
Because sshd-check-conf matches
patterns for subconfiguration files [11.6.2], it reads the
main configuration file only when a
[user@]host
string has been given.
Therefore, the dump
command
can't be used before then:
# Tectia
$ sshd-check-conf
sshd-check-conf> dump
No config data to dump; input <user@host> first.
The sshd-check-conf program accepts the debug options -d and -v [5.9] to print more detailed debugging information as it reads the configuration files and analyzes access control decisions.
Additionally, when invoking the server, you may supply command-line options. For example, the port value may be specified on the command line with the -p option:
$ sshd -p 1022
Command-line options override settings in the configuration
file. Thus, if the configuration file says port 1022 but the server is
invoked with -p 2468
, the port used will be
2468.
Most command-line options duplicate the features found in the configuration file, for convenience, while a few provide unique functionality. For instance, the -f option instructs sshd to use a different configuration file, a feature that's useless to put in a configuration file.
On the other hand, most keywords don't have command-line equivalents. However, the -o option lets you specify any keyword and its value on the command line; for example, to set the TCP port number by this method:
$ sshd -o "Port 1022"
The argument for the -o option should be a keyword and value, exactly as specified in the configuration file.[47] An equals sign (with optional whitespace) can also be used:
$ sshd -o "Port = 1022"
You can omit the quotes if you avoid characters special to the shell (including the whitespace around the equals sign):
$ sshd -o Port=1022
You can repeat the -o option to set values for multiple keywords on the same command line.
Tectia servers always use the default egrep syntax for regular expressions on the command line. Unlike configuration files, command-line options have no way to change this via metaconfiguration, e.g., for -o options.
Command-line options can be repeated, but the effects of such repetition vary and even differ depending on the server implementation. In almost all cases, only the last repeated option is used, and all earlier instances of the same option are (silently) ignored. For example, an attempt to read two configuration files:
$ sshd -f /usr/local/ssh/main.conf -f /usr/local/ssh/alt.conf
Beware! Does not read both files!
will actually read only alt.conf and ignore main.conf.
The "last option wins" rule can be handy for scripting. Suppose you launch the server from a shell script called launch-sshd:
# launch-sshd: sshd -f /usr/local/ssh/main.conf "$@"
Since the $@
is replaced by
options from the command line, you can substitute a different
configuration file when using the script:
$ launch-sshd -f /usr/local/ssh/alt.conf
We have seen that the -o option is an exception: it can be repeated to set values for as many keywords as needed. There are only a few other exceptions, all for OpenSSH. The -p option can be repeated to listen on multiple ports: [5.3.3.1]
# OpenSSH $ sshd -p 2222 -p 3333
The -h option can be used multiple times to specify different types of host keys in separate files: [5.3.1.1]
# OpenSSH $ sshd -h /usr/local/ssh/my_dsa_key -h /usr/local/ssh/my_rsa_key -h /usr/local/ssh/ my_old_ssh1_key
Repeating the -d option increases the level of verbosity for debugging: [5.9]
# OpenSSH $ sshd -d -d -d
Tectia is more consistent than OpenSSH: it always uses the last instance of each option on the command line.
sshd reads its configuration file at startup. Therefore, if you modify the file while the server is running, the changes don't affect the server. You must force the server to reread the file in order to accept the changes. This is done by sending a SIGHUP signal to the server process. The pid of the server is found in a file, usually /var/run/sshd.pid for OpenSSH or /var/run/sshd2_22.pid for Tectia. [5.3.1.3]
Suppose the pid file is /var/run/sshd.pid, the default for OpenSSH. To send the SIGHUP signal, run the Unix kill command:
$ cat /etc/sshd.pid 19384 $ kill -HUP 19384
or more succinctly, with backquotes:
$ kill -HUP `cat /etc/sshd.pid`
or on systems with the pidof command, which prints pids of given, named processes:
$ kill -HUP `pidof sshd`
Linux systems (and others) have boot scripts that can signal the SSH server. For example, instead of explicitly sending SIGHUP to sshd, you can run:
$ /etc/init.d/sshd reload
Regardless of how it's sent, the SIGHUP signal restarts sshd (with a different pid) but doesn't terminate existing SSH connections, so you can send it safely while clients are connected. The new sshd process reads and conforms to the new configuration.
The SIGHUP technique affects settings defined in the configuration file, not command-line options. To change those, you must kill and restart the server with the new options. For example:
$ kill 19384
$ sshd new_options
Command-line options are often specified in boot scripts that
are used to start sshd. For example, some Linux
systems read an OPTIONS
variable
assignment from the file /etc/sysconfig/sshd (if it exists). You may
need to edit such options files if you want to permanently change the
command-line options used to start the SSH server at boot time. After
doing this, you can use the boot script to restart the server with the
new command-line options:
$ /etc/init.d/sshd restart
Boot scripts can perform other useful functions. To determine whether the SSH server is running, use:
$ /etc/init.d/sshd status
To start or stop the server, use:
$ /etc/init.d/sshd start $ /etc/init.d/sshd stop
Some configuration keywords refer to external files. If the contents of those files change, you might wonder if it is necessary to signal the SSH server. In almost all cases, the answer is no: only the filenames are recorded when the configuration file is read, and the external file's contents are reread each time they are needed. The host key file is an important exception, because it is normally read only when the server starts. [5.3.1.1]
Because command-line options override their configuration file equivalents, some interesting situations can arise. Suppose the configuration file sets the TCP port number to be 2222:
Port 2222
but the server is invoked with the -p command-line option, overriding this value with 3333:
$ sshd -p 3333
The server uses TCP port 3333. Now, suppose you restart sshd with SIGHUP:
$ kill -HUP `pidof sshd`
forcing sshd to reread the configuration file. What do you think happens to the port number? Does the server use port 2222 after rereading the configuration file, or does the command-line option remain in effect for port 3333? In fact, the command-line option takes precedence again, so port 3333 is reused. sshd saves its argument vector[48] and reapplies it on restart.