Getting Ready: Initial Setup

We now embark on a detailed discussion of SSH server configuration, using both keywords and command-line options. Please keep in mind that modern SSH products are actively developed and their features may change. Be sure to read their documentation for the latest information.

We begin with initial setup decisions, such as: where should important files be kept? What should their permissions be? What TCP/IP settings should be used? Which encryption algorithms should be supported?

5.3.1 File Locations

sshd expects certain files to exist, containing the server’s host key, the random seed, and other data. The server looks for these files in default locations, or you may override them with keywords and command-line options as described later.

Although you may place these files anywhere you like, we strongly recommend keeping them on a local disk on your server machine, not on a remotely mounted disk (e.g., via NFS). This is for security reasons, as NFS will gleefully transmit your sensitive files unencrypted across the network. This would be especially disastrous for the unencrypted private host key!

As a running example, we use an invented directory, /usr/local/ssh, as our preferred (nondefault) location for the SSH server’s files.

5.3.1.1 Host key files

The host key of sshd uniquely identifies a server to SSH clients. The host key is stored in a pair of files, one containing the private key and the other the public key. OpenSSH has distinct host keys in DSA (/etc/ssh/ssh_host_dsa_key) and RSA (/etc/ssh/ssh_host_rsa_key) formats, as well as a legacy SSH-1 protocol key, /etc/ssh/ssh_host_key. These private keys are readable only by privileged programs such as the SSH server and clients. Their locations may be changed with the HostKey keyword:[49]

    # OpenSSH
    HostKey /usr/local/ssh/my_dsa_key
    HostKey /usr/local/ssh/my_rsa_key
    HostKey /usr/local/ssh/my_old_ssh1_key

Each private key has a corresponding public key, stored in a second file with the same name but with .pub appended. So, in the above example, the public keys would be /usr/local/ssh/my_dsa_key.pub, /usr/local/ssh/my_rsa_key.pub, and /usr/local/ssh/my_old_ssh1_key.pub.

For Tectia, the default private key file is /etc/ssh2/hostkey if the server is run by the superuser or ~/.ssh2/hostkey if run by any other user. To specify a different private key file, use the HostKeyFile keyword:

    # Tectia
    HostKeyFile /usr/local/ssh/key

The server’s public key file, normally /etc/ssh2/hostkey.pub for superusers or ~/.ssh2/hostkey.pub for others, may be changed independently with the PublicHostKeyFile keyword:

    # Tectia
    PublicHostKeyFile /usr/local/ssh/pubkey

If you prefer command-line options, sshd supports the -h command-line option to specify the private key file:

    $ sshd -h /usr/local/ssh/key

Once again, the public key filename is derived by appending .pub to the private key filename, in this case, /usr/local/ssh/key.pub.

OpenSSH allows each type of host key to be specified with a separate -h option (and detects the type of each key automatically):

    # OpenSSH
    $ sshd -h /usr/local/ssh/my_dsa_key -h /usr/local/ssh/my_rsa_key -h /usr/local/ssh/
my_old_ssh1_key

For Tectia, if the -h option is repeated, only the last file is used and all earlier -h options are ignored. This is consistent with its usual behavior with command-line options. [5.2.3]

5.3.1.2 Random seed file

The SSH server generates pseudo-random numbers for cryptographic operations. [3.6.4] It maintains a pool of random data for this purpose, derived either from the operating system if provided (e.g., /dev/random on Linux) or from various bits of changing machine state (e.g., clock time, statistics on resource use by processes, etc.). This pool is called the random seed.

If running on a system with a random-bit source, such as /dev/urandom, OpenSSH doesn’t create a random seed file. Tectia stores a random seed in /etc/ssh2/random_seed, and the location may be overridden with the RandomSeedFile keyword:

    # Tectia
    RandomSeedFile /usr/local/ssh/seed2

5.3.1.3 Process ID file

The OpenSSH server’s pid is stored in /var/run/sshd.pid, and you can override this location with the PidFile keyword:

    # OpenSSH
    PidFile /usr/local/ssh/pid

OpenSSH doesn’t record the process ID when it runs in debug mode. [5.9]

There is no corresponding keyword for Tectia. Its pid file is always named /var/run/sshd2_ n .pid, or if there is no /var/run directory, /etc/ssh2/sshd2_ n .pid, where n is the TCP port number of the server.[50] Since the default port is 22, the default pid file is sshd2_22.pid. If multiple sshd2 processes are run simultaneously on different ports of the same machine, their pid files can be distinguished by this naming convention. The directory used to store pid files can be changed by the configure option --with-piddir. [4.3.5.1]

5.3.1.4 Server configuration file

The server configuration file is normally /etc/ssh/sshd_config for OpenSSH and /etc/ssh2/sshd2_config for Tectia. An alternative configuration file can be specified with the -f command-line option:

    $ sshd -f /usr/local/ssh/config

This is useful when testing a new server configuration: create a new file and instruct sshd to read it. It is also necessary if you are running multiple sshd s on the same machine and want them to operate with different configurations.

Only a single configuration file is read. If you provide multiple -f options, the last one is used and all others are ignored.

5.3.1.5 User SSH directory

Tectia’s sshd expects a user’s SSH-related files to be in the directory ~/.ssh2 by default, but this can be changed with the UserConfigDirectory keyword. (OpenSSH has no such capability.) The directory name may be literal, as in:

    # Tectia
    UserConfigDirectory /usr/local/ssh/my_dir

or it may be specified with printf-like patterns, as in:

    # Tectia
    UserConfigDirectory %D/.my-ssh

The %D pattern expands to the user’s home directory. So, the preceding example expands to ~/.my-ssh. The following table shows the available patterns:

Pattern

Meaning

%D

User’s home directory

%U

User’s login name

%IU

User’s uid (Unix user ID)

%IG

User’s gid (Unix group ID)

If the % character is followed by any other characters, it is left unchanged.[51]

For the system administrator, the UserConfigDirectory keyword provides a quick way to override all users’ Tectia preferences. Specifically, you can cause sshd to ignore everybody’s ~/.ssh2 directories, substituting your own instead. For instance, the line:

    # Tectia
    UserConfigDirectory /usr/sneaky/ssh/%U

tells sshd to seek the preferences for each user in /usr/sneaky/ssh/ <username> instead of ~/.ssh2. This powerful feature can also be misused if your machine is compromised. If an intruder inserted the following line into sshd2_config:

    # Tectia
    UserConfigDirectory /tmp/hack

and uploaded his own public key file into /tmp/hack, he would gain SSH access to every user’s account.

5.3.1.6 Per-account authorization files

The OpenSSH server expects to find a user’s public-key authorization file in ~/.ssh/authorized_keys. This location can be changed with the AuthorizedKeysFile keyword, followed by the new location:

    # OpenSSH
    AuthorizedKeysFile .ssh/permitted_keys

Filenames can be absolute or are relative to the user’s home directory. Additionally, the location can contain a few special symbols: %h to mean the user’s home directory, %u for the username, or %% for a percent sign. So, when user smith authenticated on a server machine with this line in /etc/ssh/sshd_config:

    # OpenSSH
    AuthorizedKeysFile /usr/local/access/%u

the authorization filename would expand to /usr/local/access/smith.

The Tectia server uses a different key file layout than OpenSSH. [6.1.2] Its authorization file, normally ~/.ssh2/authorization, contains names of separate public key files, rather than the keys themselves. sshd can be instructed to find the authorization file elsewhere via the keyword AuthorizationFile:

    # Tectia
    AuthorizationFile my_public_keys

Filenames can be absolute or are relative to each user’s Tectia configuration (.ssh2) directory. The preceding example specifies the file ~/.ssh2/my_public_keys.

5.3.1.7 utmp file structure

The utmp file (e.g., /var/run/utmp) contains information about users currently logged in, such as their username, tty, and most notably for us, the hostname from which they’ve logged in (for remote logins). OpenSSH’s sshd can limit the length of hostname information written to the utmp file. (It’s inspired by a similar feature in the telnet daemon telnetd.)

    # OpenSSH
    $ sshd -u 25         Limit hostnames to 25 characters or less

If a remote hostname is longer than this limit, the host’s IP address will be written instead. Why is this useful? For two reasons:

  • Hostnames longer than the default length—which may vary on different systems—will normally be truncated in the utmp file. While you cannot increase the utmp length with the -u option, you can notify sshd of the length limitation so that IP addresses get used in place of long hostnames. This way, you’ll accurately record the host’s identity. See /usr/include/utmp.h to learn the length limit for your system.

  • If you specify -u0, IP addresses will always be used in place of hostnames. This has the side effect of forcing sshd not to make DNS requests for these hostname lookups. (It will not entirely suppress DNS, however, since it might be needed for authentication.)

5.3.2 File Permissions

As security products, OpenSSH and Tectia require certain files and directories on the server machine to be protected from unwanted access. Imagine if your authorized_keys or .rhosts file were world-writable; anyone on that host could modify them and gain convenient access to your account. sshd has several configuration keywords for reducing this risk.

5.3.2.1 Acceptable permissions for user files

Users aren’t always careful to protect important files and directories in their accounts, such as their .rhosts file or personal SSH directory. Such lapses can lead to security holes and compromised accounts. To combat this, you can configure sshd to reject connections to any user account that has unacceptable permissions.

The StrictModes keyword, with a value of yes (the default), causes sshd to check the permissions of important files and directories. They must be owned by the account owner or by root, and group and world write permission must be disabled. For OpenSSH, StrictModes checks:

  • The user’s home directory

  • The user’s ~/.rhosts and ~/.shosts file

  • The user’s SSH configuration directory, ~/.ssh

  • The user’s SSH ~/.ssh/authorized_keys file

  • The user and system “known hosts” files

For Tectia, the list is smaller and is checked only for hostbased authentication:[3.4.3.6]

  • The user’s home directory

  • The user’s ~/.rhosts and ~/.shosts file

If any check fails, the server rejects SSH connection attempts to the account. If StrictModes is given the value no, these checks aren’t performed:

    StrictModes no

However, we strongly suggest you leave these checks enabled.

Tectia recognizes an undocumented keyword, StrictModes.UserDirMaskBits, to control the checks more precisely. The value is an octal number representing the file permission bits that must be disabled. For example, to require that files grant no group or world access (read, write, or execute):

    # Tectia
    StrictModes.UserDirMaskBits 077

The default value is 022, indicating that group and world write permission must be disabled.

Even if StrictModes is enabled, it can be defeated by using POSIX access control lists (ACLs), which are supported in Solaris and some other flavors of Unix, to set file permissions with greater precision. sshd doesn’t check ACLs, so one could argue that StrictModes is an incomplete test.

5.3.3 TCP/IP Settings

Since the SSH protocol operates over TCP/IP, sshd permits control over various parameters related to TCP/IP.

5.3.3.1 Port number and network interface

By default, sshd listens on TCP port 22. The port number may be changed with the Port keyword:

    Port 9876

or the -p command-line option:

    $ sshd -p 9876

If you repeat the Port keyword or -p option, OpenSSH listens on all of the specified ports:

    # OpenSSH
    $ sshd -p 22 -p 9876

Tectia, on the other hand, allows only a single port setting: if multiple Port keywords or -p options are specified, the server uses only the last one and ignores all earlier instances.[52]

You may also configure sshd to bind its listening port on a particular network interface. By default, the port is bound on all active network interfaces on the host. The ListenAddress keyword limits sshd to listen only on specific interfaces; the default value is 0.0.0.0.

For example, suppose a computer has two Ethernet cards and is attached to two different networks. One interface has the address 192.168.10.23, and the other, 192.168.11.17. By default, sshd listens on both interfaces; therefore, you can reach the server by connecting to port 22 at either address. However, this may not always be what you want; perhaps you want to provide SSH service only to hosts on one network and not the other:

    ListenAddress 192.168.10.23

Of course, this represents a real restriction only if the two networks aren’t otherwise connected together (say, by a router) so that port 22 on 192.168.10.23 is not reachable from the network 192.168.11.24.

To listen on multiple, specific interfaces, repeat the ListenAddress keyword:

    ListenAddress 192.168.10.23
    ListenAddress 192.168.11.17

For even more precise control, you can also specify the port for listening on a given interface. The syntax differs for OpenSSH and Tectia:

    # OpenSSH
    ListenAddress 192.168.11.17:12345 Port 12345. Notice the colon between the address and the port.

    # Tectia
    ListenAddress 192.168.11.17 12345 Port 12345. Notice the space between the address and the port.

The address 0.0.0.0 means to listen on all interfaces:

    ListenAddress 0.0.0.0

optionally qualified by a port number:

    # OpenSSH
    ListenAddress 0.0.0.0:9876

    # Tectia
    ListenAddress 0.0.0.0 9876

OpenSSH servers allow the address to be omitted (meaning all interfaces) if the port is specified:

    # OpenSSH
    ListenAddress :9876

Tip

For OpenSSH, a ListenAddress of 0.0.0.0:2222 will listen on port 2222 only on IPv4 interfaces, whereas :2222 means to listen on both IPv4 and IPv6 addresses. Additionally, you can specify IPv6 addresses with colons, but to avoid ambiguity between the address and the port specification, enclose the IPv6 part in square brackets, e.g., ListenAddress [::1]:2222.

Tectia servers recognize the address any for all interfaces, with or without a port:

    # Tectia
    ListenAddress any
    ListenAddress any 9876

Since Tectia uses only a single Port value, the only way to configure the server to listen on multiple ports is to use multiple ListenAddress keywords.

OpenSSH also permits hostnames in place of numeric addresses:

    ListenAddress server.example.com

If the hostname lookup yields multiple addresses, then they are all used.

Tip

If a ListenAddress value has no port specified, then the value (or possibly multiple values, for OpenSSH) of the Port keyword is used for that address. In such a case, the Port keyword(s) must precede that ListenAddress keyword.

Additionally, the -p command-line option overrides all Port and ListenAddress keywords in the configuration file. The server listens on all interfaces if any -p options are used. Use one or several -o options with the ListenAddress keyword to indicate specific interfaces on the command line.

5.3.3.2 Invocation by inetd or xinetd

sshd normally runs as a daemon, listening for incoming connection requests, and forking whenever it accepts a connection from a client. This spawns a separate child process (a copy of the parent sshd process) to handle each session. The child process exits when the session ends.

Alternatively, the server may be invoked by inetd or xinetd, like many other network daemons. In this case, the general-purpose network daemon listens for and accepts the SSH connections. It then starts a new instance of sshd for each session with the already-connected socket attached to the standard input, output, and error streams of sshd. Each sshd invocation is responsible for a single session.

If you prefer this behavior, place an appropriate line in the inetd or xinetd configuration file to describe the SSH service, invoking sshd with the -i command-line option. For inetd, add a single line to /etc/inetd.conf:

    ssh stream  tcp     nowait  root       /usr/local/sbin/sshd     sshd -i

Or if you’re using xinetd, create a new file /etc/xinetd.d/ssh containing:

    service ssh
    {
            socket_type = stream
            protocol    = tcp
            wait        = no
            user        = root
            server      = /usr/local/sbin/sshd
            server_args = -i
            disable     = no
    }

You will also need an entry for SSH in the server machine’s TCP/IP services database, usually /etc/services (or sometimes /etc/inet/services), such as:

    ssh    22/tcp    # SSH Remote Login Protocol

The -i option causes sshd to:

  • Ignore all Port and ListenAddress keywords and the -p command-line option, because inetd or xinetd itself is responsible for listening

  • (OpenSSH only) Ignore all MaxStartups keywords

  • (OpenSSH only) Direct debug output to syslog [5.9] instead of the standard error stream, since stderr is attached to the SSH socket by inetd or xinetd, and debug output would confuse the SSH client at the other end of the connection

The inetd/xinetd approach has advantages and disadvantages. On the up side, it allows a wrapper program to invoke sshd, should that be needed, and xinetd particularly supports many options that can complement the SSH server configuration. Also, inetd and xinetd provide a single, centralized point of control for all types of network connections, which simplifies maintenance. If you want to forbid all types of TCP/IP connections, for example, you can simply disable inetd/xinetd instead of running around killing other daemons. On systems where SSH connections are rare, using inetd/xinetd for the SSH service saves resources (memory and a process slot) otherwise consumed by the SSH server as it listens for incoming connections. Finally, starting a new sshd instance for each connection can make attacks more difficult by introducing additional randomness. On the down side, inetd/xinetd-based SSH connections may be slower to start up.[53]

5.3.3.3 Restarting the SSH server for each connection

SSH servers use randomness extensively for cryptographic algorithms and protocols, typically relying on the operating system (or other external state) to provide a source of random bits. [3.6.4] Some operating systems also support Address Space Layout Randomization (ASLR), which protects against certain kinds of attacks that require knowledge of predictable memory locations. ASLR causes random offsets to be used when program segments or shared libraries are loaded, memory regions are dynamically allocated, etc.

Most of the randomness introduced by ASLR occurs when a program is initially loaded and starts running. Even on systems without ASLR, dynamic memory allocations that primarily occur in the early stages of program execution can be affected by the global state of the system’s virtual memory, which is hard to predict. In contrast, when a long-running program merely forks to create many child processes, all of the children inherit the memory layout (and even contents) from the parent process. Restarting the child processes after each fork mitigates the risks associated with attacks that are based on guessing memory locations.

By default, the OpenSSH server restarts itself after it accepts each connection from a client, and forks to create a separate child process to handle the session.[54] Relative pathnames can’t be used for server restarts, since sshd changes its working directory shortly after it begins running:

    # OpenSSH
    $ ./sshd
    sshd re-exec requires execution with an absolute path

Tip

We’ll continue to use the relative pathname “sshd” for our examples as an abbreviation, since the full, absolute pathname usually isn’t relevant to our discussions about the sshd command line. Nevertheless, an absolute pathname is recommended in practice, and newer versions of OpenSSH now enforce this, as shown in the preceding example.

If the server restart fails for some other reason (e.g., the executable file used originally to start sshd was renamed or removed), then the child process continues to run after forking, but produces a warning (which is usually sent to syslog):

    error: rexec of /usr/sbin/sshd failed: No such file or directory

Before it restarts, the child process adds the undocumented -R option at the end of its command line: this is used by the new process to detect that it has been restarted, and should therefore use the already connected socket that it inherits from its parent for communication with the client.[55] The parent process (i.e., the one that listens for incoming connections) sends a copy of its configuration and the SSH-1 server key (if one is used) via another socket to the restarted child process, which knows to read the data because of the same -R option. The child process then proceeds to handle the session normally.

If OpenSSH is started by inetd or xinetd, then there is no need to restart the SSH server, because a new instance of sshd is started by inetd/xinetd for each connection. [5.3.3.2] In fact, the function of the restarted child process is so similar to the operation of the server with inetd/xinetd that the -R option enables the same side effects as the -i option: notably, debug output is forced to syslog instead of the standard error.

The restart mechanism can be disabled by the undocumented, lowercase -r option:

    # OpenSSH
    $ sshd -r

This is useful in conjunction with server debugging features, since restarts are an inconvenient complication, and the side effect of sending debug output to syslog after the child process restarts is undesirable. [5.9] The -r option can also be used to avoid the slight performance cost for server restarts, especially on systems without ASLR, where such restarts provide little or no additional randomness. There is no configuration option to disable the server restart feature at build time.

5.3.3.4 Keepalive messages

The keepalive feature (TCPKeepAlive in OpenSSH, KeepAlive in Tectia) is concerned with recognizing when a connection has failed. Suppose a client establishes an SSH connection, and sometime later, the client host crashes abruptly. If the SSH server has no reason to send unsolicited messages to the client, it may never notice the half-dead TCP connection to its partner, and the sshd remains around indefinitely, using up system resources such as memory and a process slot (and making the sysadmin’s ps output messy).

The TCPKeepAlive or KeepAlive keyword instructs sshd how to proceed if a connection problem occurs, such as a prolonged network outage or a client machine crash:

    # OpenSSH
    TCPKeepAlive yes
    # Tectia
    KeepAlive yes

The value yes (the default) tells the server to set the TCP keepalive option on its connection to the client. This causes TCP to transmit and expect periodic keepalive messages. If it doesn’t receive responses to these messages for a while, it returns an error to sshd, which then shuts down the connection.

The value no means not to use keepalive messages. Note that SSH clients can also enable keepalive messages from their side of the connections, so it’s important to disable those too if you want to avoid keepalive traffic completely. [7.4.5.4]

The TCP keepalive feature is intended to prevent half-dead connections from building up over time. The keepalive message interval and timeout period reflect this: they are quite long, typically on the order of hours. This is to minimize the network load imposed by the keepalive messages and also to prevent connections from being unnecessarily torn down because of transient problems, such as a temporary network outage or routing flap. These timers aren’t set in SSH; they are properties of the host’s TCP stack. They shouldn’t be altered lightly, since they affect every TCP connection using keepalives on that host.

This feature isn’t intended to prevent lost connections due to firewall, proxying, NAT, or IP masquerading timeouts. For instance, when your SSH connection is going across a firewall but has been idle for a while, the firewall can decide to tear down the connection. Since this is done to conserve shared resources (such as a limited pool of external, routable IP addresses), these timeouts are typically quite short, perhaps a few minutes to an hour or so. The name “keepalive” suggests that it might be the right thing to use, since that’s what you want to do—keep your connection alive. But really, “keepalive” is the wrong name for it; it would be better named “detect dead” (but that sounds like a second-level cleric spell to avoid being eaten by zombies). To deal with this problem, you’d have to shorten the TCP keepalive interval dramatically on the SSH host. This is contrary to its purpose and unwise because it affects not only SSH connections, but also every other TCP connection using keepalives, even those that don’t need it. Doing this on the server side is an especially bad idea as a general principle, since a busy server may be using lots of TCP connections, and enabling keepalives on many of them since it’s supposed to be an inexpensive feature. This can impose an unnecessary and damaging additional network load, especially if it becomes a widespread practice.

It’s good to remember that the timeout annoying you so much is there for a reason. You might like to leave an unused SSH connection up for a long time, but if it’s occupying one of a limited number of simultaneous outbound Internet TCP connections for your company, perhaps it’s better if you just suck it up for the common good. Typing ssh again once in a while is really not that hard; use your shell’s alias feature if you find the number of keystrokes onerous. If you genuinely think the timeout is inappropriate or unnecessary, argue the case with the network administrator, and try to get it changed.

For the occasions when it’s really necessary, the right way to accomplish this sort of keepalive behavior is with an application-level mechanism implemented in SSH—having it periodically send SSH protocol messages over the connection to make it appear nonidle. This is exactly what OpenSSH does with its ClientAliveInterval and ClientAliveCountMax keywords. ClientAliveInterval controls how the server sends client-alive messages.[56] Its argument is a length of time in seconds:

    # OpenSSH
    ClientAliveInterval 300         Send client-alive every 300 seconds, or five minutes

or a time value with optional units:

    # OpenSSH
    ClientAliveInterval 5m          Send client-alive every five minutes

If your server hasn’t heard from the client within the given amount of time, the server will send a client-alive message to the client. It will continue sending these messages at the given interval (in this case, every five minutes) until it receives a response or gives up. You control how it gives up with the third keyword, ClientAliveCountMax, representing the maximum number of consecutive client-alive messages the server will send:

    # OpenSSH
    ClientAliveCountMax 8           Try eight times, then give up. The default is three times.

Once this maximum is reached, the server considers the SSH connection inactive and terminates it. If you don’t want the server to send client-alive messages, set ClientAliveInterval to zero.

If your SSH implementation has no similar feature (Tectia doesn’t), we recommend simply sending characters over your connection once in a while. Run Emacs with a clock in its mode line. Run a program in the background that prints “Boo!” to your terminal if it’s been idle for 20 minutes. You get the idea.

5.3.3.5 Idle connections

Keepalive messages are concerned with recognizing that a connection has failed. A related feature is recognizing when a healthy connection is unused and should be terminated. Tectia supports the IdleTimeout keyword for this purpose. If an SSH connection is established between a server and a client, but no data passes over the connection for a long time, what should the server do: keep the connection, or terminate it?

The IdleTimeout keyword tells the server what to do if a connection is idle, i.e., if the user doesn’t transmit any data in a given period. If IdleTimeout is zero (the default), the server does nothing, leaving idle connections intact:

    # Tectia
    IdleTimeout 0

Otherwise, the server terminates the connection after a specified interval of idleness. The time value can specify units, e.g., three hours:

    # Tectia
    IdleTimeout 3H

See the sidebar "Time Values in Configuration Files" for more syntax details.

The idle timeout can also be set for a given key in a user’s authorized_keys file using the idle-timeout option. [8.2.7] Notably, this option overrides the server’s IdleTimeout value but only for that key. This is a rare instance of a per-account option overriding a serverwide option; however, the server will only allow a client to decrease the timeout.

5.3.3.6 Failed logins

Suppose a user attempts to log in via SSH but fails to authenticate. What should the server do? The keywords LoginGraceTime, MaxAuthTries (OpenSSH), and PasswordGuesses (Tectia) control the server’s response.

Users are given a limited time to authenticate successfully. The default is 120 seconds (2 minutes) for OpenSSH or 600 seconds (10 minutes) for Tectia. This timeout is controlled by the LoginGraceTime keyword, given a value in seconds:

    LoginGraceTime 60

or the -g command-line option:

    $ sshd -g 60

OpenSSH allows time units to be used in the configuration file or on the command line:

    # OpenSSH
    LoginGraceTime 5m

    # OpenSSH
    $ sshd -g 5m

To disable this feature, provide a LoginGraceTime value of zero:

    LoginGraceTime 0

or by command-line option:

    $ sshd -g 0

Tip

OpenSSH ignores LoginGraceTime in debug mode. [5.9]

OpenSSH limits the number of times (six by default) that a user can attempt to authenticate in a single SSH connection:

    # OpenSSH
    MaxAuthTries 4         Permit four attempts, and log the third and fourth failures if they occur

If authentication fails half the number of times specified (in this example, two times, half of four), then failures are logged by sshd. In other words, sshd gives you the benefit of the doubt at first, then considers you suspicious. By default, you have six chances to authenticate in one connection.

If password authentication is used for a connection request, Tectia’s sshd permits a client three tries to authenticate before dropping the connection. This restriction may be modified with the PasswordGuesses keyword for Tectia:

    # Tectia
    PasswordGuesses 5

There are two sorts of requests a client can make in this regard: a query whether a particular public key is authorized to log into the target account, and an actual authentication attempt including a signature by the corresponding private key. As Tectia does not limit the number of public-key authentication requests, there’s no issue with it. The OpenSSH MaxAuthTries setting, however, limits the number of failed authentication requests overall, of any type, and OpenSSH counts a “no” answer to a public-key query as a failure. A common side effect is an unexpected limit to the number of keys you can usefully have in an agent! If you have five keys in your agent, and it happens to be the fifth one that would let you in, you’re out of luck: the server will disconnect you after the client tries the fourth key. And that’s assuming the client didn’t try and fail some other methods first, e.g., GSSAPI or hostbased; then even fewer keys could be tried. (See [7.4.2.1] for a workaround.)

There are various security arguments to made here, of course. The server can’t distinguish between a legitimate user trying keys and an attacker knocking on the door, so it measures all attempts against the repeated-authentication limit. In fact, one can argue that the server shouldn’t honor public-key queries because they reveal information to an attacker: which key to try to steal, or whether an account can be accessed at all. These are all trade-offs of convenience versus security, and different server implementations take different approaches.

You can work around this issue by listing your most relevant keys in your client configuration file, ~/.ssh/config, with the IdentityFile keyword. [7.4.2] Keys that are in both the agent and the configuration file are tried first by the client. Therefore, you can associate particular keys with a particular host so that they’re tried first for authentication.

5.3.3.7 Limiting simultaneous connections

sshd can handle an arbitrary number of simultaneous connections by default. Both OpenSSH and Tectia provide keywords to limit the maximum number, if you want to conserve resources on your server machine or reduce the risk of denial-of-service attacks. For OpenSSH it is MaxStartups, and for Tectia it is MaxConnections:

    # OpenSSH
    MaxStartups 32

    # Tectia
    MaxConnections 32

To specify an unlimited number of connections, provide a value of zero:

    # OpenSSH
    MaxStartups 0

    # Tectia
    MaxConnections 0

Of course, the number of connections is also limited by available memory or other operating system resources. These keywords have no effect on these other factors. (Sorry, you can’t increase your CPU speed by setting a keyword!)

OpenSSH’s MaxStartups keyword has one additional bit of functionality. If you provide a triple of integers separated by colons, of the form A:B:C, this tells the server to refuse connections based on probabilities. Specifically, if the number of connections is A or greater, sshd will begin rejecting connections. When there are A connections, the probability of rejection is B%. When there are C connections, the probability of rejection is 100% (every attempt is rejected). Between A and C connections, the probability increases linearly from B% to 100%. So, for example, if you have:

    # OpenSSH
    MaxStartups 10:50:20

then at a load of 10 connections, the probably of rejection is 50%; at 15 connections (halfway between 10 and 20) it’s 75% (halfway between 50% and 100%), and at 20 connections it’s 100%.

Tectia’s behavior is simpler. After the maximum number of connections have been accepted, new connection attempts are rejected, and the server sends a “Too many connections” error message back to the client before it disconnects. Tectia can also limit the number of connections at compile time via the --with-ssh-connection-limit option. [4.3.5.3]

If sshd is launched by xinetd, then you can control server resources much more precisely: the rate of incoming connections, server memory, and more. [5.3.3.2]

5.3.3.8 Reverse IP mappings

The SSH server optionally does a reverse DNS lookup on a client’s IP address. That is, it looks up the name associated with the address, then looks up the addresses for that name and makes sure that the client’s address is among them. If this check fails, the server refuses the connection. This feature uses standard system services like gethostbyname() and gethostbyaddr() to perform these mappings, so the databases that are consulted depend on the host operating system configuration. It might use the DNS, the Network Information Service (NIS or YP), static files on a server machine, or some combination.

To enable this check for OpenSSH, provide the UseDNS keyword with a value of yes or no:[57]

    # OpenSSH
    UseDNS yes

This feature is a bit of security-oriented consistency checking. SSH uses cryptographic signatures to determine a peer’s identity, but the list of peer public keys (the known hosts database) is often indexed by hostname, so SSH must translate the address to a name in order to check the peer’s identity. Reverse mapping tries to ensure that someone isn’t playing games with the naming service in a cracking attempt. There is a trade-off, however, since in today’s Internet, the DNS reverse-address mappings aren’t always kept up to date. The SSH server might reject legitimate connection attempts because of poorly maintained reverse-address mappings over which you have no control. In general, we recommend turning off this feature; it isn’t usually worth the hassle, and you avoid long reverse-lookup delays at times when DNS is down.

5.3.3.9 Controlling the Nagle Algorithm

TCP/IP has a feature called the Nagle Algorithm, which is designed to reduce the number of TCP segments sent with very small amounts of data (e.g., one byte), usually as part of an interactive terminal session. Over fast links such as Ethernet, the Nagle Algorithm generally isn’t needed. Over a wide-area network, however, it can cause noticeable delays in the responsiveness of X clients and character terminal displays, as multibyte terminal control sequences may be transmitted inconveniently by the algorithm. In such cases, you should turn off the Nagle Algorithm using the NoDelay keyword:

    # Tectia
    NoDelay yes

NoDelay disables the Nagle Algorithm by toggling the TCP_NODELAY bit when requesting a TCP connection from the Unix kernel. Legal values are yes (to disable) and no (to enable; the default).

NoDelay can be enabled or disabled by the Tectia client, rather than serverwide, using the client configuration keyword NoDelay. [7.4.5.5] It usually makes more sense to use NoDelay for a single client connection than to control the Nagle Algorithm globally for all connections on the server side.

5.3.3.10 Discovering other servers

Tectia can seek out and discover other Tectia servers automatically. The keyword MaxBroadcastsPerSecond, when given an integer value greater than zero, causes a Tectia server to respond to UDP broadcasts sent to port 22:

    # Tectia
    MaxBroadcastsPerSecond 10

The server responds to only this many queries per second; any excess broadcasts are silently ignored. All UDP broadcasts received on port 22 apply to this limit, including unrecognized or malformed packets. The rate limiting prevents a denial-of-service attack that floods the server with queries, causing it to spend all its time replying to them.

By default, Tectia servers do not respond to UDP broadcasts. This behavior can be specified explicitly by setting MaxBroadcastsPerSecond to zero:

    # Tectia
    MaxBroadcastsPerSecond 0

No mechanism is provided to use a UDP port other than 22, and the UDP port is completely independent of the TCP port(s) used for ordinary SSH connections.

A program supplied with Tectia, ssh-probe, sends queries to one or more specified broadcast addresses. It listens for replies, and prints the locations (IP addresses and ports) along with the versions of any Tectia servers that it finds:

    # Tectia
    $ ssh-probe 10.1.2.255
    10.1.2.3:22:SSH Tectia Server 4.1.3.2
    10.1.2.5:22:SSH Tectia Server 4.1.3.2
    10.1.2.5:2222:SSH Tectia Server 4.1.3.2
    10.1.2.5:3333:SSH Tectia Server 4.1.3.2
    10.1.2.9:22:SSH Tectia Server 4.1.3.2
    ...

Directed broadcasts (i.e., those on different networks) can be used if intervening gateways are willing to forward them. IP addresses of specific hosts (but not hostnames) can also be used.

Tip

UDP datagrams received on non-broadcast addresses are usually delivered only to a single process, so if several Tectia servers are running on a target host, then only one will respond. Use broadcast addresses to detect multiple servers.

ssh-probe does not use the ProtocolVersionString to determine the version: this string is part of the initial negotiation between SSH servers and clients for TCP connections. [5.3.7] Tectia servers always supply their actual version string in response to UDP queries by ssh-probe.

The default output format is intended to be parsed easily by programs. The -r option prints results in a more human-readable format:

    # Tectia
    $ ssh-probe -r 10.1.2.255
    Server address = "10.1.2.3"
    Server port = "22"
    Server version = "SSH Tectia Server 4.1.3.2"
    ...
    12 servers detected.

The -s option causes ssh-probe to operate silently, returning only an exit value of 0 to indicate that at least one server was found, 1 if no replies were received, or -1 if some other error occurred:

    # Tectia
    $ ssh-probe -s 10.1.2.255
    $ case $? in
    >     0) echo "Tectia found.";;
    >     1) echo "Tectia missing.";;
    >     *) echo "Something bad happened to ssh-probe!";;
    > esac
    Tectia found.

By default, ssh-probe waits one second for replies. The -t option specifies a longer timeout, e.g., for slow or distant servers:

    # Tectia
    $ ssh-probe -t 5 10.1.2.255

ssh-probe supports the -d option for debug output. [5.9] The program uses the module names SshProbe and SshServerProbe.

Port-scanning programs such as nmap provide a more general way to locate SSH servers, including other implementations like OpenSSH, even though port scans typically don’t provide version information as ssh-probe does for Tectia servers. For example, to use nmap to scan a range of network addresses for any kinds of SSH servers listening on (TCP) port 22:

    $ nmap -v -p 22 10.1.2.0/24

The ScanSSH program [58] scans ranges of network addresses, identifying SSH servers (along with open proxies and other interesting servers, such as HTTP and SMTP). It attempts to determine the version for each. For example, to scan the same network address range:

    $ scanssh -s ssh 10.1.2.0/24

MaxBroadcastsPerSecond and ssh-probe are a rather ad hoc solution for locating Tectia servers, and port scans are questionable, since authorized users typically know the identity of specific servers to which they have been granted access. Probes often don’t work across firewalls, and they might be mistaken for attacks by people and programs that monitor network activity.

Better techniques are available to enumerate servers for administrative tasks, e.g., maintaining a list of servers in a netgroup or other database. Dynamic DNS and SRV records are alternatives, although this nameserver functionality is still not widely used.

5.3.4 Key Regeneration

All SSH servers maintain a persistent host key. It is generated by the system administrator when installing SSH and identifies the host for authentication purposes. [5.3.1.1] Additionally, SSH-2 clients and servers exchange keys for data encryption and integrity. By default, the Tectia client and server perform this key exchange every hour (3600 seconds) but you can set this with the RekeyIntervalSeconds keyword. A value of zero disables rekeying.

    # Tectia
    RekeyIntervalSeconds 7200

This keyword only controls the automatic, periodic session rekeying that is initiated by the server. An SSH client can still request session rekeying at any time.

You can make the ssh client force rekeying with the escape sequence ~R (OpenSSH) or ~r (for Tectia). [7.4.6.8]

5.3.5 Encryption Algorithms

The SSH server can use a number of data-encryption algorithms for its secure connection; the client chooses a cipher from the list the server allows. The Ciphers keyword describes the subset of allowable ciphers, selected from those the server software supports. Its value is a comma-separated list of algorithm names (strings), case-sensitive,[59] indicating which algorithms are permissible. For example:

    Ciphers 3des-cbc
    Ciphers 3des-cbc,blowfish-cbc,arcfour

The order of the values is not significant, since the client drives the choice of the cipher.

If multiple Ciphers keywords are specified, the values are not accumulated into a single list. Instead, OpenSSH uses the list for the first Ciphers keyword, and Tectia uses the last.

Warning

OpenSSH treats unrecognized cipher names as fatal errors, but Tectia silently ignores them, which makes typos hard to detect. For troubleshooting, use the sshd -d command-line option [5.9] with the SshConfigParse module and a high debug level:

    # Tectia
    sshd -d SshConfigParse=9

Look for “ssh_config_set_param_algs” in the output to see the actual list of cipher names that were used.

The Ciphers keyword is useful for quickly disabling individual encryption algorithms—say, if a security hole is discovered in one of them. Just omit that algorithm from the Ciphers list and restart the server.

Both OpenSSH and Tectia support the following standard ciphers that are defined by the IETF SECSH draft:

In addition, Tectia implements the following standard ciphers:[60]

none
twofish-cbc
twofish128-cbc
twofish192-cbc
twofish256-cbc

The “none” cipher means that no encryption is used. This is unsuitable for production use, but it might occasionally be convenient for testing, e.g., if you are watching SSH traffic using a network sniffer for diagnostic purposes. Subconfiguration files can restrict insecure ciphers like “none” to specific hosts or users. [11.6.2]

OpenSSH also implements a number of nonstandard ciphers:

[61]
aes128-ctr
aes192-ctr
aes256-ctr

By default, all ciphers supported by the OpenSSH server (both standard and nonstandard) are allowed.

Tectia supports a different set of recommended, nonstandard ciphers:

Tectia also recognizes special values for the Cipher keyword indicating sets of algorithms:

AnyStd

Any standard algorithm implemented by Tectia, including none

AnyStdCipher

Same as AnyStd, but excluding none

Any

Any standard or recommended, nonstandard algorithm implemented by Tectia, including none

AnyCipher

Same as Any, but excluding none

These special values are case-insensitive, in contrast to the other values for cipher names. We recommend using the capitalization shown earlier, but you may see lowercase values in older Tectia configuration files or documentation.

An important and unfortunate restriction is that the special values for cipher sets cannot be mixed with other cipher names:

    # Tectia: This is ILLEGAL
    Ciphers 3des-cbc,AnyStd

The default for Tectia is AnyStdCipher.

Tectia’s extensive but poorly documented cryptographic library actually supports a much wider range of ciphers, including:

These are not included in the sets for Any or AnyCipher. In some cases, this is because the ciphers are considered experimental or inferior. For example, DES is usually not recommended because of its short key length, and block ciphers in ECB mode are considered vulnerable to replay attacks. Other modes such as CFB, OFB, and CTR are plausible alternatives to the default CBC, however.

Finally, Tectia recognizes a small number of convenient aliases for sets of ciphers:

Value

Meaning

aes-cbc

aes128-cbc, aes192-cbc aes256-cbc

cast

cast128-cbc

twofish

twofish-cbc, twofish128-cbc, twofish192-cbc, twofish256-cbc

Tip

In most cases, the names of block ciphers in CBC mode are also recognized by Tectia without “-cbc”, since CBC is considered the default mode. There are exceptions, however, that don’t follow any obvious pattern:

We therefore recommend explicitly specifying -cbc in cipher names.

Tectia is rather forgiving (or sloppy, depending on your point of view) about the @ssh.com suffix for cipher names, which is supposed to be used consistently for nonstandard ciphers.

Most standard cipher names are also recognized with this suffix. The exceptions are:

  • aes128-cbc

  • aes192-cbc

  • aes256-cbc

  • twofish128-cbc

  • twofish192-cbc

  • twofish256-cbc

Similarly, the suffix can be omitted from most nonstandard cipher names. The lone exception is [email protected], because the name without the suffix is used as an alias for all AES ciphers in CBC mode with any key length, as described earlier.

Misusing the @ssh.com suffix in this way is inadvisable, because it violates the IETF SECSH draft.

5.3.6 Integrity-Checking (MAC) Algorithms

The MACs keyword selects the allowable integrity-checking algorithms, known as the message authentication code (MAC), used by sshd. [3.4.2.3] Except as described below, the MACs keyword behaves exactly like the Ciphers keyword. [5.3.5] Here are some examples:

    MACs hmac-sha1
    MACs hmac-sha1,hmac-md5

Both OpenSSH and Tectia support the following standard MAC algorithms defined by the IETF SECSH draft:

hmac-sha1
hmac-sha1-96
hmac-md5
hmac-md5-96

In addition, Tectia implements the standard “none” MAC, meaning that no integrity checking is performed. This is intended only for testing.

Tip

In Tectia’s FIPS mode, only the hmac-sha1 MAC is supported.

OpenSSH also implements a nonstandard MAC algorithm, [email protected]. The name hmac-ripemd160 is also recognized without the @openssh.org suffix, but this is deprecated, since all nonstandard names are supposed to use a domain suffix. Tectia also supports some nonstandard MAC algorithms:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Tectia recognizes special values for the Macs keyword to describe sets of algorithms:

AnyStd

Any standard algorithm implemented by Tectia, including none

AnyStdMac

Same as AnyStd, but excluding none

Any

Any standard or nonstandard algorithm implemented by Tectia, including none

AnyMac

Same as Any, but excluding none

By default, Tectia allows algorithms in the AnyStdMac set. (The Any value includes all supported MAC algorithms, unlike the Ciphers keyword.) OpenSSH allows all its available MACs by default.

Tip

Tectia also recognizes standard MAC names with the @ssh.com suffix. The suffix cannot be omitted for nonstandard MAC names, however, in contrast to the Ciphers keyword.

It’s best to use the suffix consistently according to the IETF SECSH draft, only for nonstandard names.

5.3.7 SSH Protocol Settings

OpenSSH lets you limit its protocol support to SSH-1, SSH-2, or both, using the Protocol keyword. Permissible values are 1 (for SSH-1), 2 (for SSH-2), or both 1 and 2 separated by a comma (the default):

    # OpenSSH
    Protocol 2,1

If you specify both protocols, the order doesn’t matter since the client, not the server, drives the authentication process. And as we’ve said before, the SSH-1 protocol is less secure and we recommend avoiding it. [3.5]

5.3.7.1 Protocol version string

SSH servers and clients exchange protocol version information as part of their initial negotiations, to agree on a protocol. [3.4.4.2] You can see the protocol version string used by the server by connecting to the SSH port:

    $ telnet localhost 22
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    SSH-2.0-4.1.3.2 SSH Secure Shell

By default, Tectia servers use a string like “4.1.3.2 SSH Secure Shell” for the comment part (after the second hyphen) of the protocol version. This can be changed using the undocumented ProtocolVersionString keyword:

    # Tectia
    ProtocolVersionString Generic SSH Implementation

Port-scanning tools that connect to the SSH port and observe the protocol version string will not see the detailed information about the specific installed version of Tectia if the string is changed:

    $ telnet localhost 22
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    SSH-2.0-Generic SSH Implementation

Tip

ProtocolVersionString changes only the comment part of the version string. The initial parts (e.g., SSH-2.0) always specify the protocol(s) that the server is willing to use, according to the SSH protocol standard.

Although an obscured ProtocolVersionString might thwart very simplistic port-scanning tools, in practice it doesn’t help much, since many attacks try to exploit bugs regardless of the version string, and determined attackers can probably figure out the implementation by noticing specific behavioral quirks of the server anyway. If the Tectia server is configured to respond to UDP queries by ssh-probe [5.3.3.10], then it always will respond to such queries with the actual version information, not the changed ProtocolVersionString. Furthermore, changing ProtocolVersionString might prevent workarounds by clients for known server incompatibilities or bugs.

The OpenSSH server always uses a string like “OpenSSH_3.9p1” for its protocol version string. This cannot be changed except by modifying the source code.

5.3.8 Compression

The data flowing between the SSH client and server may optionally be compressed to save bandwidth. Often this option is set by the client [7.4.14], but OpenSSH gives the server the ultimate authority on whether data compression is permitted, using the Compression keyword:

    # OpenSSH
    Compression no

The default value is yes.



[49] HostKey has the aliases HostRsaKey and HostDsaKey, but they are deprecated and might be removed in a future version of OpenSSH.

[50] More precisely, n is the value for the Port keyword, even if ListenAddress keywords cause the server to use different ports. [5.3.3.1]

[51] You need not double the percent sign (%%) to get a literal percent character, i.e., as required for the C function printf.

[52] The port setting (either explicit or the default value, 22) is used in the name of the process ID file. [5.3.1.3] Tectia servers can listen on multiple ports, but this requires use of the ListenAddress keyword.

[53] Only if you use the SSH-1 protocol, where sshd generates a new server key each time it’s invoked. But you’re not using SSH-1, are you?

[54] This feature is new in OpenSSH 3.9.

[55] Never use the -R option to start sshd; it’s really part of the protocol for communication between the parent and the (restarted) child server processes.

[56] OpenSSH clients have analogous ServerAliveInterval and ServerAliveCountMax keywords. [7.4.5.4]

[57] Tectia has a similar-sounding keyword, RequireReverseMapping, but it applies only to the AllowHosts and DenyHosts features. [5.5.3]

[59] Older versions of OpenSSH treat the algorithm names as case-insensitive.

[60] A few standard ciphers aren’t supported by either OpenSSH or Tectia: idea-cbc, serpent128-cbc, serpent192-cbc, and serpent256-cbc. These are all considered optional by the IETF SECSH draft.

[61] Cipher [email protected] is not allowed by default; it must be explicitly enabled.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.201.209