Client Configuration in Depth

ssh and scp take their cues from command-line options, configuration-file keywords, and environment variables. OpenSSH and Tectia clients behave differently and obey different settings, but as usual, we cover them simultaneously. When a setting is supported by only some of these products, we’ll say so.

Both OpenSSH and Tectia ssh will print a usage message briefly describing all its options:

    $ ssh --help

You can get the same effect if you omit all arguments (OpenSSH) or use -h (Tectia). Tectia will also print its version number on request, with the -V option:

    # Tectia
    $ ssh -V
    ssh: SSH Tectia Server 4.2.1 on i686-pc-linux-gnu
    Build: 1
    Released 2004-11-30 (YYYY-MM-DD).
    Crypto library version: SSH Cryptographic Library, version 1.2.4
    FIPS certification mode: DISABLED
    Product: SSH Tectia Server (T)
    License type: commercial

7.4.1 Remote Account Name

ssh and scp assume that your local and remote usernames are the same. If your local username is henry and you run:

    $ ssh server.example.com

ssh assumes your remote username is also henry and requests a connection to that account on server.example.com. If your remote account name differs from the local one, you must tell the SSH client your remote account name. For henry to connect to a remote account called sally, he can use the -l command-line option:

    $ ssh -l sally server.example.com

If copying files with scp, the syntax is different for specifying the remote account name, looking more like an email address. [7.5.1] To copy the file myfile to the remote account sally on server.example.com:

    $ scp myfile [email protected]:

If you frequently connect to a remote machine using a different username, instead of monkeying with command-line options specify the remote username in your client configuration file. The User keyword serves this purpose, and both ssh and scp pay attention to it. Here’s how to declare that your remote username is sally on a given remote host:

OpenSSH

Tectia

Host server.example.com

server.example.com:

 User sally

 User sally

Now, when connecting to server.example.com, you don’t have to specify that your remote username is sally:

    # The remote username sally will be used automatically
    $ ssh server.example.com

7.4.1.1 Tricks with remote account names

With User and nicknames, you can significantly shorten the command lines you type for ssh and scp. Continuing the preceding example with sally, if you have the configuration shown:

OpenSSH

Tectia

Host simple

simple:

 HostName server.example.com

 Host server.example.com

 User sally

 User sally

then these long commands:

    $ ssh server.example.com -l sally
    $ scp myfile [email protected]:

may be reduced to:

    $ ssh simple
    $ scp myfile simple:

Here’s how to specify separately several different account names on different hosts, each in its own section of the configuration file:

OpenSSH

Tectia

Host server.example.com

server.example.com:

 User sally

 User sally

 ...

 ...

Host another.example.com

another.example.com:

 User sharon

 User sharon

 ...

 ...

This technique is convenient if you have only one account on each remote machine. But suppose you have two accounts on server.example.com, called sally and sally2. Is there some way to specify both in the configuration file? The following attempt doesn’t work (we show OpenSSH syntax only):

    # THIS WILL NOT WORK PROPERLY!!!
    Host server.example.com
     User sally
     User sally2
     Compression yes

because only the first value (sally) prevails. To get around this limitation, you can use nicknames to create two sections for the same machine in your configuration file, each with a different User:

    # OpenSSH
    # Section 1: Convenient access to the sally account
    Host sally-account
     HostName server.example.com
     User sally
     Compression yes

    # Section 2: Convenient access to the sally2 account
    Host sally2-account
     HostName server.example.com
     User sally2
     Compression yes

Now you can access the two accounts easily by nickname:

    $ ssh sally-account
    $ ssh sally2-account

This works, but it isn’t ideal. You’ve duplicated your settings (HostName and Compression) in each section. Duplication makes a configuration file harder to maintain, since any future changes need to be applied twice. (In general, duplication isn’t good software engineering.) Are you doomed to duplicate? No, there’s a better solution. Immediately after the two sections, create a third section with a Host wildcard that matches both sally-account and sally2-account. Suppose you use sally*-account and move all duplicated settings into this new section:

    # OpenSSH
    Host sally*-account
     HostName server.example.com
     Compression yes

The end result is:

OpenSSH

Tectia

Host sally-account

sally-account:

 User sally

 User sally

Host sally2-account

sally2-account:

 User sally2

 User sally2

Host sally*-account

sally*-account:

 HostName server.example.com

 Host server.example.com

 Compression yes

 Compression yes

Since sally*-account matches both previous sections, its full name and compression settings apply to both sally-account and sally2-account. Any settings that differ between sally-account and sally2-account (in this case, User) are kept in their respective sections. You’ve now achieved the same effect as in the previous example—two accounts with different settings on the same remote machine—but with no duplication of settings.

7.4.2 User Identity

SSH identifies you by an identity represented by a key pair (OpenSSH) or a collection of key pairs (Tectia). [6.1] Normally, SSH clients use your default key file (OpenSSH) or default identification file (Tectia) to establish an authenticated connection. However, if you’ve created other keys, you may instruct SSH clients to use them to establish your identity. A command-line option (-i ) and configuration keyword (IdentityFile) are available for this purpose.

In OpenSSH, for example, if you have a private-key file called my-key, you can make clients use it with the commands:

    $ ssh -i my-key server.example.com
    $ scp -i my-key myfile server.example.com:

or with the configuration keyword:

    IdentityFile my-key

The file location is assumed to be relative to the current directory, i.e., in these cases the file is ./my-key.

Tectia also has -i and IdentityFile, but their meanings are slightly different from those of OpenSSH. Instead of a key file, you supply the name of an identification file:

    # Tectia
    $ ssh -i my-id-file server.example.com

    # Tectia configuration file
    IdentityFile my-id-file

Tip

If Tectia complains about your identity file:

    warning: /home/smith/.ssh2/id_dsa_2048_a: 4: parsing line failed.

you probably handed ssh a key file (id_dsa_2048_a) instead of an identity file like ~/.ssh2/identification.

Multiple identities can be quite useful. [6.4] For example, you can set up your remote account to run specific programs when a second key is used. The ordinary command:

    $ ssh server.example.com

initiates a regular login session, but:

    $ ssh -i other_identity server.example.com

can run a complex batch process on server.example.com. Using configuration keywords, you can accomplish the same effect by specifying an alternative identity, as shown in this table:

OpenSSH

Tectia

Host SomeComplexAction

SomeComplexAction:

 HostName server.example.com

 Host server.example.com

 IdentityFile other_identity

 IdentityFile other_identity

 ...

 ...

You can then invoke:

    $ ssh SomeComplexAction

OpenSSH can specify multiple identities in a single command:[107]

    # OpenSSH
    $ ssh -i id1 -i id2 -i id3 server.example.com

or:

    # OpenSSH
    Host server.example.com
     IdentityFile id1
     IdentityFile id2
     IdentityFile id3

Multiple identities are tried in order until one successfully authenticates. However, OpenSSH limits you to 100 identities per command.[108]

If you plan to use multiple identities frequently, remember that an SSH agent can eliminate hassle. Simply load each identity’s key into the agent using ssh-add, and you won’t have to remember multiple passphrases while you work.

7.4.2.1 Using identities

IdentityFile specifies an identity you’d like to use for authentication, but it does not restrict authentication to that identity. Suppose your client configuration file says:

    # OpenSSH
    Host server.example.com
     IdentityFile wendy
     IdentityFile abby

and you run:

    # OpenSSH
    $ ssh server.example.com

ssh will dutifully try to authenticate using identities wendy and abby; but if it fails, ssh will try other identities held in your SSH agent, in case one of them might succeed. You can change this behavior with the IdentitiesOnly keyword:

    # OpenSSH
    Host server.example.com
     IdentityFile wendy
     IdentityFile abby
     IdentitiesOnly yes      Restrict authentication only to listed identity files

Now if ssh fails to authenticate by identities wendy and abby, it will stop trying (and move on to other non-public-key techniques, if configured to do so).

This feature is particularly useful with a server that limits the number of public-key authentication attempts, such as OpenSSH. If you have many keys in your agent, only a few can be tried before the server disconnects you for “too many failures.” The configuration shown avoids this problem by indicating exactly which keys to use for a given host. Even though the IdentityFile keyword refers to files, the OpenSSH client will try those keys from the agent if they’ve been loaded. You are prompted for a passphrase only if the needed key isn’t in the agent and is encrypted on disk.

7.4.3 Host Keys and Known-Hosts Databases

Every SSH server has a host key [3.3] that uniquely identifies the server to clients. This key helps prevent spoofing attacks. When an SSH client requests a connection and receives the server’s host key, the client checks it against a local database of known host keys . If the keys match, the connection proceeds. If they don’t, the client behaves according to several options you can control.

In OpenSSH, the host key database is maintained partly in a serverwide location (/etc/ssh/ssh_known_hosts) and partly in the user’s SSH directory (~/.ssh/known_hosts). In Tectia, there are two databases of host keys for authenticating server hosts (the “hostkeys” map in /etc/ssh2/hostkeys) and client hosts (the “knownhosts” map); in this section we are concerned only with the former. Similar to its OpenSSH counterpart, the Tectia hostkeys map is maintained in a serverwide directory (/etc/ssh2/hostkeys/ ) and a per-account directory (~/.ssh2/hostkeys/). In this section, we refer to the OpenSSH and Tectia map simply as the host key database.

7.4.3.1 Strict host-key checking

Suppose you request an SSH connection with server.example.com, which sends its host key in response. Your client looks up server.example.com in its host key database. Ideally, a match is found and the connection proceeds. But what if this doesn’t happen? Two scenarios may arise:

SCENARIO 1: Mismatched key

A host key is found for server.example.com in the database, but it doesn’t match the incoming key. This can indicate a security hazard, or it can mean that server.example.com has changed its host key, which can happen legitimately. [3.9.4]

SCENARIO 2: No key

No host key for server.example.com exists in the database. In this case, the SSH client is encountering server.example.com for the first time.

In each scenario, should the client proceed or fail? Should it store the new host key in the database, or not? These decisions are controlled by the keyword StrictHostKeyChecking, which may have three values:

yes

Be strict. If a key is unknown or has changed, the connection fails. This is the most secure value, but it can be inconvenient or annoying if you connect to new hosts regularly or if your remote host keys change frequently.

no

Not strict. If a key is unknown, automatically add it to the user’s database and proceed. If a key has changed, leave the known hosts entry intact, print a warning, and permit the connection to proceed. This is the least secure value.

ask

Prompt the user. If a key is unknown, ask whether it should be added to the user’s database and whether to connect. If a key has changed, ask whether to connect. This is the default and a sensible value for knowledgeable users. (Less-experienced users might misunderstand what they’re being asked and make the wrong decision.)

Here’s an example:

    StrictHostKeyChecking yes

Table 7-1 summarizes SSH’s StrictHostKeyChecking’s behavior.

Table 7-1. StrictHostKeyChecking behavior

Key found?

Match?

Strict?

Action

Yes

Yes

-

Connect

Yes

No

Yes

Warn and fail

Yes

No

No

Warn and connect

Yes

No

Ask

Warn and ask whether to connect

No

-

Yes

Warn and fail

No

-

No

Add key and connect

No

-

Ask

Ask whether to add key and to connect

OpenSSH has an additional keyword, CheckHostIP, to make a client verify the IP address of an SSH server in the database. Its values may be yes (the default, to verify the address) or no. The value yes provides security against name service spoofing attacks: [3.9.2]

    # OpenSSH
    CheckHostIP no

7.4.3.2 Verifying host keys by DNS

The known-hosts mechanism for verifying hostkeys is fine when dealing with a handful of hosts, but quickly becomes unwieldy for larger numbers. Later we discuss overarching authentication systems such as PKI or Kerberos to address this problem. [11.5] Another method is to use the DNS: if we could attach hostkeys to domain names, then SSH could verify the server by looking up its keys in the DNS. The method is documented in draft-ietf-secsh-dns. It uses DNS resource records with the following format:

    IN SSHFP <key type> <fingerprint type> <fingerprint>

where the key types can be 1 (for RSA) or 2 (DSS), and the fingerprint type can be 1 (for SHA-1).

ssh-keygen can generate these DNS records in a form ready to be included in a zone file for the BIND nameserver:

    # OpenSSH
    $ ssh-keygen -r host.domain.net -f /etc/ssh/ssh_host_dsa_key.pub
    host.domain.net IN SSHFP 2 1 7ae79057cbff7de6d61b30fba02d936d6a0f5b5f

    $ ssh-keygen -r host.domain.net -f /etc/ssh/ssh_host_dsa_key.pub -g
    host.domain.net IN TYPE44 # 22 02 01 7ae79057cbff7de6d61b30fba02d936d6a0f5b5f

The -g form is for nameservers that don’t understand the SSHFP RR type.

To have OpenSSH use these DNS records, set the VerifyHostDNS keyword to yes, no, or ask:

    # ~/ssh/config
    VerifyHostKeyDNS=yes

It’s vitally important to remember that the DNS itself is usually not secure! There is a standard for DNS security (DNSSEC, RFC-2535), but it is not much used yet. Without DNSSEC, DNS queries and replies can be easily intercepted and forged by attackers, so this level of hostkey verification may not be acceptable.

If VerifyHostKeyDNS is ask, and StrictHostKeyChecking is yes or ask, OpenSSH will indicate whether it found a matching hostkey in the DNS, but still obey the usual semantics of StrictHostKeyChecking in deciding whether to approve the server. VerifyHostKeyDNS yes is the same, except that matching fingerprints obtained via secure DNS are considered just as trustworthy as those stored in the known-hosts list. If StrictHostKeyChecking is no, then VerifyHostKeyDNS makes no difference.

7.4.3.3 Host key aliasing

OpenSSH uses a simple method to find the host key for server authentication: it simply looks up in the known-hosts list exactly what you type on the command line for the remote server name. Sometimes, the situation is more complicated; you know which host you’re actually contacting, but OpenSSH doesn’t. For instance, you might be using SSH-over-SSH to contact a remote host through a second SSH port forwarding, like so:

    $ ssh -L 2001:david:22 goliath
    $ ssh -p 2001 localhost

The second command will connect to the SSH server David through another one, goliath. However, the second ssh may complain about a host-key mismatch. It has no way of knowing about the port-forwarding indirection; it thinks you are connecting to an SSH server which is actually running on the local host, compares goliath’s hostkey to that of the local host, and finds they do not match. In this situation, you can tell OpenSSH which key to use with HostKeyAlias:

    # OpenSSH
    $ ssh -p 2001 -o HostKeyAlias=david localhost

7.4.3.4 Ignoring host keys for localhost

In many computing environments, users’ home directories are shared across many machines. As a result, users’ ~/.ssh configuration files are shared in this manner. This is useful but has one little glitch: the idiom ssh localhost.

The problem is that “localhost” means something different on every host! The first time you run this command, ssh will add a key for “localhost” to your known-hosts file—but the next time you do it on a different machine, SSH will complain about a host-key mismatch! You could get around this by adding multiple “localhost” lines to the known-hosts list, expanding the set of keys acceptable for that destination. However, since there’s little security to be gained in verifying the identity of the host you’re already logged into, OpenSSH has a special option, NoHostAuthenticationForLocalhost, to disable server authentication for the connections to the loopback address:

    # ~/.ssh/config
    NoHostAuthenticationForLocalhost yes

7.4.3.5 Moving the known hosts files

OpenSSH permits the locations of the host key database, both the serverwide and per-account parts, to be changed using configuration keywords. GlobalKnownHostsFile defines an alternative location for the serverwide file. It doesn’t actually move the file—only the system administrator can do that—but it does force your clients to use another file in its place. This keyword is useful if the default file is outdated and you want your clients to ignore the serverwide file, particularly if you’re tired of seeing warning messages from your clients about changed keys:

    # OpenSSH
    GlobalKnownHostsFile /users/smith/.ssh/my_global_hosts_file

Similarly, you can change the location of your per-user part of the database with the keyword UserKnownHostsFile:

    # OpenSSH
    UserKnownHostsFile /users/smith/.ssh/my_local_hosts_file

7.4.4 SSH Protocol Settings

OpenSSH lets the client control a number of features relating to the SSH protocol itself.

7.4.4.1 Choosing a protocol version

OpenSSH supports protocols SSH-1 and SSH-2. By default, the client and server will try to negotiate an SSH-2 connection first, then fall back to an SSH-1 connection if unsuccessful. You can control which protocols are tried by the client, and in what order, with the Protocol keyword, just as for the server: [5.3.7]

    # OpenSSH
    Protocol 2,1         Comma-separated list of protocol versions

You should always use SSH-2 for maximum security, if your software supports it, so it’s a good idea to instruct your clients to avoid SSH-1 servers. You can do this for all hosts by placing a Protocol line at the bottom of your ~/.ssh/config file:

    # OpenSSH
    Host *
     Protocol 2

or by the command-line arguments -1 and -2, for protocols SSH-1 and SSH-2, respectively:

    # OpenSSH
    $ ssh -2 server.example.com   Require an SSH-2 connection

Tectia supports the -1 option, with required qualifiers t and i to control how the SSH-1 support is accomplished:

    # Tectia
    $ ssh-1t server.example.com   "traditional": invoke an external ssh1 program
    $ ssh-1i server.example.com   "internal": do SSH-1 protocol internally

7.4.4.2 Connection sharing

A single SSH connection can have multiple channels simultaneously supporting a variety of services: interactive terminals, remote program execution, file transfer, agent forwarding, etc. [3.4.4.1] Setting up an SSH connection is a computationally expensive process, and can take a few seconds. That’s no big deal if you do it once in a while, but if you have a procedure that makes many connections, the delay can get pretty annoying or problematic. The Unix “style” promotes this problem: for instance, you can use CVS over SSH by setting the environment variable CVS_RSH=ssh. If you’re running a lot of CVS commands, however, each will now take an extra five seconds or so, and computer users are notoriously impatient. Given that SSH can use channels, wouldn’t it be better to set up one SSH connection to a given host, and then somehow issue our various commands over that one session?

Well, yes it would, and OpenSSH has this feature in its ControlMaster and ControlPath keywords, and the -M and -S options of ssh. This command:

    # OpenSSH
    $ ssh -S /tmp/ssh-snowcrash -MfN snowcrash.neal.org

opens an SSH connection to the server snowcrash.neal.org, placing it in the background. It also tells this SSH process to act as a “master” process, allowing other ssh invocations (its “slaves”) to open channels to this server through it. Master and slave communicate via the Unix socket /tmp/ssh-snowcrash. So this:

    # OpenSSH
    $ ssh -S /tmp/ssh-snowcrash snowcrash.neal.org

will open a remote terminal on snowcrash, and will do it quickly because no new SSH connection is set up; it goes through the existing connection. You can make this more convenient with custom configuration:

    # ~/.ssh/config
    host snowcrash-master
      hostname snowcrash.neal.org
      ControlPath /tmp/ssh-snowcrash
      ControlMaster

    host snowcrash-slave
      hostname snowcrash.neal.org
      ControlPath /tmp/ssh-snowcrash

And thus you can efficiently run:

    # OpenSSH
    $ ssh -fN snowcrash-master
    $ ssh snowcrash-slave

7.4.4.3 Setting environment variables in the server

SSH clients can set environment variables in their remote SSH sessions. This mechanism is supported only by the SSH-2 protocol, and works only if it is permitted by the server, according to the keywords AcceptEnv (OpenSSH) or SettableEnvironmentVars (Tectia). [5.6.2]

OpenSSH clients use the SendEnv keyword to specify the names of environment variables that are sent to the server:

    # OpenSSH
    SendEnv COLOR

Multiple variables can be listed, separated by whitespace, or specified by multiple keywords. Wildcard characters * and ? send all variables in the client’s environment whose name matches the pattern:

    # OpenSSH
    SendEnv LANG LC_*
    SendEnv PATH TERM TZ

The value for each variable is copied from the environment of the OpenSSH client.

Tectia clients use the SetRemoteEnv keyword to specify both the name and the value, separated by an equals sign (with no whitespace):

    # Tectia
    SetRemoteEnv COLOR=blue

Use multiple keywords to send several variables to the server. Each variable must be named explicitly: no wildcards or patterns are used. The value can be omitted (to indicate an empty string), but the equals sign is required. Whitespace is permitted within the value, and is copied verbatim:

    # Tectia
    SetRemoteEnv GRANDDAUGHTERS=katie rebecca sarah

Note that the Tectia client’s environment is not consulted at all, and the variables that are sent to the server need not even be present in the environment of the client.

7.4.5 TCP/IP Settings

SSH uses TCP/IP as its transport mechanism. Most times you don’t need to change the default TCP settings, but in some situations it’s necessary:

  • Connecting to SSH servers on other TCP ports

  • Connecting via a particular network interface

  • Using privileged versus nonprivileged ports

  • Keeping an idle connection open by sending keepalive messages

  • Enabling the Nagle Algorithm (TCP_NODELAY)

  • Requiring IP addresses to be Version 4 or 6

7.4.5.1 Selecting a remote port

Most SSH servers listen on TCP port 22, so clients connect to this port by default. Nevertheless, sometimes you need to connect to an SSH server on a different port number. For example, if you are a system administrator testing a new SSH server, you might run it on a different port to avoid interference with an existing server. Then your clients need to connect to this alternate port. This can be done with the client’s Port keyword, followed by a port number:

    Port 2035

or the -p command-line option, followed by the port number:

    $ ssh -p 2035 server.example.com

You can also specify an alternative port for scp, but the command-line option is -P instead of -p : [109]

    $ scp -P 2035 myfile server.example.com:

Tectia also accepts a port number as part of the user and host specification, preceded by a hash sign. For example, the commands:

    # Tectia
    $ ssh server.example.com#2035
    $ ssh [email protected]#2035
    $ scp [email protected]#2035:myfile localfile

each connect to remote port 2035. (We don’t see much use for this syntax, but it’s available.)

After connecting to the server, ssh sets an environment variable in the remote shell to hold the port information. For OpenSSH, the variable is called SSH_CLIENT, and for Tectia it is SSH2_CLIENT. The variable contains a string with three values, separated by a space character: the client’s IP address, the client’s TCP port, and the server’s TCP port. For example, if your client originates from port 1016 on IP address 24.128.23.102, connecting to the server’s port 22, the value is:

    # OpenSSH
    $ echo $SSH_CLIENT
    ::ffff:24.128.23.102 1016 22

    # Tectia
    $ echo $SSH2_CLIENT
    24.128.23.102 1016 22

OpenSSH also sets an environment variable, SSH_CONNECTION, with slightly extended port information, appending the server’s IP address and port:

    # OpenSSH
    $ echo $SSH_CONNECTION
    ::ffff:24.128.23.102 10969 ::ffff:128.220.67.30 22

These variables are useful for scripting. In your shell’s startup file (e.g., ~/.profile, ~/.login), you can test for the variable and, if it exists, take actions. For example:

    #!/bin/sh
    # Test for an SSH_CLIENT value of nonzero length
    if [ -n "$SSH_CLIENT" ]
    then
    # We logged in via SSH.
      echo 'Welcome, OpenSSH user!'
      # Extract the IP address from SSH_CLIENT
      IP=`echo $SSH_CLIENT | awk '{print $1}'`
      # Translate it to a hostname.
      HOSTNAME=`host $IP | grep Name: | awk '{print $2}'`
      echo "I see you are connecting from $HOSTNAME."
    else
      # We logged in not by SSH, but by some other means.
      echo 'Welcome, O clueless one. Feeling insecure today?'
    fi

7.4.5.2 Connecting via a given network interface

If your client machine has more than one network interface or IP address, OpenSSH clients can connect through a particular one with the BindAddress keyword:

    # OpenSSH
    BindAddress 192.168.10.235

or the -b command-line option:

    # OpenSSH
    $ ssh -b 192.168.10.235 server.example.com

7.4.5.3 Forcing a nonprivileged local port

SSH connections get locally bound to a privileged TCP port, one whose port number is below 1024. If you ever need to override this feature—say, if your connection must pass through a firewall that doesn’t permit privileged source ports—use the configuration keyword UsePrivilegedPort. Its values are yes (use a privileged port) and no (use a nonprivileged port, the default):

    # OpenSSH
    UsePrivilegedPort no

Hostbased authentication requires a privileged port.

7.4.5.4 Keepalive messages

The TCPKeepAlive (OpenSSH) and KeepAlive (Tectia) keywords instruct the client how to proceed if a TCP connection problem occurs, such as a prolonged network outage or a server machine crash:

    # OpenSSH
    TCPKeepAlive yes

    # Tectia
    KeepAlive yes

The value yes (the default) tells the client to transmit and expect periodic keepalive messages. If the client detects a lack of responses to these messages, it shuts down the connection. The value no means not to use keepalive messages.

Keepalive messages represent a trade-off. If they are enabled, a faulty connection is shut down even if the problem is transient. However, the TCP keepalive timeout on which this feature is based is typically several hours, so this shouldn’t be a big problem. If keepalive messages are disabled, an unused faulty connection can persist indefinitely.

TCP keepalive messages are generally more useful in the SSH server, since a user sitting on the client side will certainly notice if the connection becomes unresponsive. However, SSH can connect two programs together, with the one running the SSH client waiting for input from the other side. In such a situation, it may be necessary to detect dead connections eventually.

TCPKeepAlive and KeepAlive aren’t intended to deal with the problem of SSH sessions being torn down because of firewall, proxying, NAT, or IP masquerading timeouts. [5.3.3.4] In these cases, if you don’t send any data for some period of time, the firewall (or whatever) closes the TCP connection. Additionally, TCP keepalive messages are not secure, as they don’t use any real authentication technique.

OpenSSH provides a robust and secure solution to keep the connection up, called client-alive and server-alive messages. OpenSSH clients can send client-alive messages to the server, indicating the client is up. The client also detects server-alive messages sent by the OpenSSH server. [5.3.3.4]

If certain criteria are met, the client or server will tear down the connection. You can control this at three levels. First, the client’s initial connection to the server can obey a timeout. If the server hasn’t responded at all within a certain number of seconds, the client will give up. This is controlled by the ConnectTimeout keyword:

    # OpenSSH
    ConnectTimeout 60         If no connection with the server within one minute, give up

Next, the ServerAliveInterval keyword controls how the client sends server-alive messages. Its argument is a length of time in seconds:

    # OpenSSH
    ServerAliveInterval 300   Send server-alive every 300 seconds, or five minutes

If your client hasn’t heard from the server within the given amount of time, the client will send a server-alive message to the server. 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, ServerAliveCountMax, representing the maximum number of consecutive server-alive messages the client will send:

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

Once this maximum is reached, the client says, “Oh well, I guess the server has gone out for a walk,” and terminates the SSH connection. If you don’t want the client to send server-alive messages, set ServerAliveInterval to zero.

7.4.5.5 Controlling TCP_NODELAY

TCP/IP has a feature called the Nagle Algorithm, an optimization for reducing the number of TCP segments sent with very small amounts of data. [5.3.3.9] Tectia clients may also enable or disable the Nagle Algorithm using the NoDelay keyword:

    # Tectia
    NoDelay yes

Legal values are yes (to disable the algorithm) and no (to enable it; the default).

7.4.5.6 Requiring IPv4 and IPv6

OpenSSH can force its clients to use Internet Protocol Version 4 (IPv4) or 6 (IPv6) addresses. IPv4 is the current version of IP used on the Internet; IPv6 is the future version, permitting far more addresses than IPv4 can support. For more information on these address formats, visit:

To force IPv4 addressing, use the -4 flag:

    # OpenSSH
    $ ssh -4 server.example.com

or likewise for IPv6, use -6:

    # OpenSSH
    $ ssh -6 server.example.com

You can also control these settings with the AddressFamily keyword, with the values inet (IPv4 only), inet6 (IPv6 only), or any:

    # OpenSSH
    AddressFamily inet6      Use IPv6 only

7.4.6 Making Connections

Under the best conditions, an SSH client attempts a secure connection, succeeds, obtains your authentication credentials, and executes whatever command you’ve requested, be it a shell or otherwise. Various steps in this process are configurable, including:

  • The number of times the client attempts the connection

  • The look and behavior of the password prompt (for password authentication only)

  • Suppressing all prompting

  • Running remote commands interactively with a tty

  • Running remote commands in the background

  • Whether or not to fall back to an insecure connection, if a secure one can’t be established

  • The escape character for interrupting and resuming an SSH session

7.4.6.1 Number of connection attempts

If you run an OpenSSH client and it can’t establish a secure connection, it will retry. By default, it tries once. You can change this behavior with the keyword ConnectionAttempts:

    # OpenSSH
    ConnectionAttempts 10

In this example, ssh tries 10 times before admitting defeat. Most people don’t have much use for this keyword, but it might be helpful if your network is unreliable. Just for fun, you can force ssh to give up immediately by setting ConnectionAttempts equal to zero:

    # OpenSSH
    $ ssh -o ConnectionAttempts=0 server.example.com
    ssh: connect to host server.example.com port 22: Success
    $                                       ssh has exited: no connection was made

7.4.6.2 Password prompting in OpenSSH

If you’re using password authentication in OpenSSH, you may control the number of times you are prompted for your password if mistyped. By default, you’re prompted three times, and if you mistype the password repeatedly, the client exits. You can change this number with the keyword NumberOfPasswordPrompts:[110]

    #  OpenSSH
    NumberOfPasswordPrompts 2

Now your SSH client provides only two chances to type your password correctly.

7.4.6.3 Password prompting in Tectia

Tectia adds flexibility to password prompting. Instead of preset prompt strings, you can design your own with the PasswordPrompt keyword:

    # Tectia
    PasswordPrompt Enter your password right now, infidel:

You can insert the remote username or hostname with the symbols %U (remote username) or %H (remote hostname). For a typical username@hostname prompt you could use:

    # Tectia
    PasswordPrompt "%U@%H's password:"

Or you can be fancier:

    # Tectia
    PasswordPrompt "Welcome %U! Please enter your %H password:"

7.4.6.4 Batch mode: suppressing prompts

In some cases, you don’t want to be prompted for your password or passphrase. If ssh is invoked by an unattended shell script, for example, nobody will be at the keyboard to type a password. This is why SSH batch mode exists. In batch mode, all prompting for authentication credentials is suppressed. The keyword BatchMode can have a value of yes (disable prompting) or no (the default, with prompting enabled):

    BatchMode yes

Batch mode may be enabled for scp also with the -B option, for OpenSSH:

    # OpenSSH
    $ scp -B myfile server.example.com:

Batch mode doesn’t replace authentication. If a password or passphrase is required, you can’t magically log in without it by suppressing the prompt. If you try, your client exits with an error message such as “permission denied.” In order for batch mode to work, you must arrange for authentication to work without a password/passphrase—say, with hostbased authentication or an SSH agent. [11.1]

7.4.6.5 Pseudo-terminal allocation (TTY/PTY/PTTY)

A Unix tty (pronounced as it’s spelled, T-T-Y) is a software abstraction representing a computer terminal, originally an abbreviation for “teletype.” As part of an interactive session with a Unix machine, a tty is allocated to process keyboard input, limit screen output to a given number of rows and columns, and handle other terminal-related activities. Since most terminal-like connections don’t involve an actual hardware terminal, but rather a window, a software construct called a pseudo-tty (or pty, pronounced P-T-Y) handles this sort of connection.

When a client requests an SSH connection, the server doesn’t necessarily allocate a pty for the client. It does so, of course, if the client requests an interactive terminal session, e.g., just ssh host. But if you ask ssh to run a simple command on a remote server, such as ls :

    $ ssh remote.server.com /bin/ls

no interactive terminal session is needed, just a quick dump of the output of ls. In fact, by default sshd doesn’t allocate a pty for such a command. On the other hand, if you try running an interactive command like the text editor Emacs in this manner, you get an error message:

    $ ssh remote.server.com emacs -nw
    emacs: standard input is not a tty

because Emacs is a screen-based program intended for a terminal. In such cases, you can request that SSH allocate a pty using the -t option:

    $ ssh -t server.example.com emacs

Tectia also has the keyword ForcePTTYAllocation, which does the same thing as -t .[111]

    # Tectia
    ForcePTTYAllocation yes

Also, OpenSSH can request not to use a pty with the -T option, though most of the time this isn’t needed:

    # OpenSSH
    $ ssh -T server.example.com who
    barrett      :0           Aug 25 21:51  (console)
    byrnes       pts/1        Aug 25 15:19  (yoyodyne.org)
    silverman    pts/2        Aug 22 09:42  (client.example.com)

If SSH allocates a pty, it also automatically defines an environment variable in the remote shell. The variable is SSH_TTY (for OpenSSH) or SSH2_TTY (for Tectia) and contains the name of the character device file connected to the “slave” side of the pty, the side that emulates a real tty. We can see this in action with a few simple commands. Try printing the value of SSH_TTY on a remote machine. If no tty is allocated, the result is blank:

    $ ssh server.example.com 'echo $SSH_TTY$SSH_TTY2'
    [no output]

If you force allocation, the result is the name of the tty:

    $ ssh -t server.example.com 'echo $SSH_TTY$SSH_TTY2'
    /dev/pts/1

Thanks to this variable, you can run shell scripts on the remote machine that use this information. For example, here’s a script that runs your default editor only if a terminal is available:

    #!/bin/sh
    if [ -n $SSH_TTY -o -n $SSH2_TTY ]; then
       echo 'Success!'
       exec $EDITOR
    else
       echo "Sorry, interactive commands require a tty"
    fi

Place this script in your remote account, calling it myscript (or whatever), and run:

    $ ssh server.example.com myscript
    Sorry, interactive commands require a tty
    $ ssh -t server.example.com myscript
    Success!
    ...Emacs runs...

7.4.6.6 Backgrounding a remote command

If you try running an SSH remote command in the background, you might be surprised by the result. After the remote command runs to completion, the client automatically suspends before the output is printed:

    $ ssh server.example.com ls &
    [1]  11910
    $
    ... time passes ...
    [1] + Stopped (SIGTTIN)        ssh server.example.com ls &

This happens because ssh is attempting to read from standard input while in the background, which causes the shell to suspend ssh. To see the resulting output, you must bring ssh into the foreground:

    $ fg
    README
    myfile
    myfile2

ssh provides the -n command-line option to get around this problem. It redirects standard input to come from /dev/null, which prevents ssh from blocking for input. Now when the remote command finishes, the output is printed immediately:

    $ ssh -n server.example.com ls &
    [1]  11912
    $
    ... time passes ...
    README
    myfile
    myfile2

Tectia has a keyword, DontReadStdin, that does the same thing as -n, accepting the values yes or no (the default is no):

    # Tectia
    DontReadStdin yes

7.4.6.7 Backgrounding a remote command, take two

The preceding section assumed you didn’t need to type a password or passphrase, e.g., that you’re running an SSH agent. What happens if you use -n or Tectia’s DontReadStdin but the SSH client needs to read a password or passphrase from you?

    $ ssh -n server.example.com ls &
    $
    Enter passphrase for RSA key 'smith@client':

Warning

STOP! Don’t type your passphrase! Because the command is run in the background with -n, the prompt is also printed in the background. If you respond, your password will be visible! This is because you will be typing to the shell, not the ssh prompt.

You need a solution that not only disables input and sends the process into the background, but also permits ssh to prompt you. This is the purpose of the -f command-line option, which instructs ssh to do the following, in order:

  1. Perform authentication, including any prompting

  2. Cause the process to read from /dev/null, exactly like -n

  3. Put the process into the background: no “&” is needed

Here’s an example:

    $ ssh -f server.example.com ls
    Enter passphrase for RSA key 'smith@client': ********
    $
    ... time passes...
    README
    myfile
    myfile2

Tectia has a keyword, GoBackground, that does the same thing, accepting the values yes or no (the default):

    # Tectia
    GoBackground yes

GoBackground and -f also set up any port forwardings you may have specified on the command line. [9.2.6] The setup occurs after authentication but before backgrounding.

7.4.6.8 Escaping

Recall that the ssh client has an escape sequence feature. [2.3.2] By typing a particular character, normally a tilde (~), immediately after a newline or carriage return, you can send special commands to ssh: terminate the connection, suspend the connection, and so forth. Table 7-2 summarizes the supported escape sequences. It’s followed by a list that describes each sequence’s meaning.

Tip

If the next character following the escape character isn’t in Table 7-2, then OpenSSH sends the entire (unrecognized) escape sequence to the server verbatim, whereas Tectia discards the escape sequence and sends nothing.

Table 7-2. ssh escape sequences

Sequence

Example with <ESC> = ~

Meaning

<ESC> ^Z

~ ^Z

Suspend the connection (^Z means Control-Z)

<ESC> .

~ .

Terminate the connection

<ESC> #

~ #

List all forwarded connections

<ESC><ESC>

~ ~

Send the escape character (by typing it twice)

<ESC> ?

~ ?

Print a help message

OpenSSH only:

  

<ESC> &

~ &

Send ssh into the background when waiting for connections to terminate

<ESC> B

~ B

Send a break to the server )

<ESC> C

~ C

Open a command line to add or remove a port forwarding

<ESC> R

~R

Request rekeying immediately

Tectia only:

  

<ESC> -

~ -

Disable the escape character

<ESC> c

~ c

Print statistics for individual channels

<ESC> l

~ l

Switch to line mode

<ESC> r

~r

Request rekeying immediately

<ESC> s

~ s

Print statistics about this session

<ESC> V

~ V

Print version information

  • “Suspend the connection” puts ssh into the background, suspended, returning control of the terminal to the local shell. To return to ssh, use the appropriate job control command of your shell, typically fg. While suspended, ssh doesn’t run, and if left suspended long enough, the connection may terminate since the client isn’t responding to the server. Also, any forwarded connections are similarly blocked while ssh is suspended. [9.2.9]

  • “Terminate the connection” ends the SSH session immediately. This is most useful if you have lost control of the session: for instance, if a shell command on the remote host has hung and become unkillable, or if you tried exiting while a tunnel (forwarding) is still active. Any X or TCP port forwardings are terminated immediately as well. [9.2.9]

  • “List all forwarded connections” prints a list of each X forwarding or TCP port forwarding connection currently established. This lists only active instances of forwarding; if forwarding services are available but not currently in use, nothing is listed here.

  • “Send ssh into the background,” like the “suspend connection” command, reconnects your terminal to the shell that started ssh, but it doesn’t suspend the ssh process. Instead, ssh continues to run. This isn’t ordinarily useful, since the backgrounded ssh process immediately encounters an error.[112] This escape sequence becomes useful if your ssh session has active, forwarded connections when you log out. Normally in this situation, the client prints a message about waiting for forwarded connections to terminate. The client typically waits (silently) in the foreground for the forwarded connections to close before it exits: you can detect this by using the “list all forwarded connections” escape. While the client is in this state, the “send ssh into the background” escape sequence returns you to the local shell prompt.

  • “Request rekeying immediately” causes the SSH client and server to generate and use some new internal keys for encryption and integrity. Normally, the client and server agree to rekey automatically at regular intervals. [5.3.4]

  • “Send the escape character” tells the client to send a real tilde (or whatever the escape character is) to the SSH server as plaintext, not to interpret it as an escape.

  • “Disable the escape character” prevents further escape sequences from having any effect, and is therefore irrevocable.

  • “Open a command line to add or remove a port forwarding” prompts for -L or -R options to create a new local or remote port forwarding, respectively. [9.2] An existing remote forwarding can be canceled using -KR, followed by the target port number.[113] To obtain a help message, type -h or ?.

  • “Switch to line mode” causes characters to be collected by the client and then sent together to the server after a newline has been entered. This allows line-editing features that are available on the client machine to be used, even in situations when similar features are not available on the server machine. Line mode is temporary: after a single line has been sent, the client resumes its normal operation of sending each character to the server as soon as it has been entered.

The rest of the escape sequences are self-explanatory.

Sometimes the default escape character can cause a problem. Suppose you connect by ssh from host A to host B, then from host B to host C, and finally from host C to host D, making a chain of ssh connections (we represent the machines’ shell prompts as A$, B$, C$, and D$):

    A$ ssh B
    ...
      B$ ssh C
      ...
        C$ ssh D
        ...
          D$

While logged onto host D, you press the Return key, then ~ ^Z (tilde followed by Control-Z) to suspend the connection temporarily. Well, you’ve got three ssh connections active, so which one gets suspended? The first one does, and this escape sequence brings you back to the host A prompt. Well, what if you want to escape back to host B or C? There are two methods, one with forethought and one on the spur of the moment.

If you prepare in advance, you may change the escape character for each connection with the configuration keyword EscapeChar, followed by a character:

    EscapeChar %

or the -e command-line option, followed again by the desired character (quoted if necessary to protect it from expansion by the shell):

    $ ssh -e '%' server.example.com

OpenSSH supports the value none to mean no escape character:

    # OpenSSH
    EscapeChar none

So, going back to our example of hosts A through D, you want a different escape character for each segment of this chain of connections. For example:

    A$ ssh B
    ...
      B$ ssh -e '$' C
      ...
        C$ ssh -e '%' D
        ...
          D$

Now, while logged onto host D, a tilde still brings you back to host A, but a dollar sign brings you back to host B and a percent sign back to host C. The same effect can be achieved with the EscapeChar keyword, but the following table shows that more forethought is required to set up configuration files on three hosts.

OpenSSH

Tectia

# Host A configuration file

# Host A configuration file

Host B

B:

 EscapeChar ~

 EscapeChar ~

  

# Host B configuration file

# Host B configuration file

Host C

C:

 EscapeChar ^

 EscapeChar ^

  

# Host C configuration file

# Host C configuration file

Host D

D:

 EscapeChar %

 EscapeChar %

Even if you don’t normally make chains of SSH connections, you might still want to change the escape character. For example, your work might require you to type a lot of tildes for other reasons, and you might accidentally type an escape sequence such as ~. (tilde period) and disconnect your session. Oops!

There’s a second method that requires no forethought: type the escape character multiple times. Typing it twice sends the character literally across the SSH connection. [7.4.6.8] Therefore, you can suspend the second SSH connection by typing two escapes, the third by typing three escapes, and so on. Remember, you must precede your escape characters by pressing the Return key. While logged onto host D, you could escape back to host B, for example, by hitting the Return key, then typing two tildes, and Control-Z.

7.4.7 Proxies and SOCKS

SOCKS is an application-layer network proxying system supported by various SSH implementations. Proxying in general provides a way to connect two networks at the application level, without allowing direct network-level connectivity between them. Figure 7-3 shows a typical SOCKS installation.

The figure shows a private network and the Internet. The gateway machine is connected to both, but doesn’t function as a router; there’s no direct IP connectivity between the two networks. If a program running on H wants to make a TCP connection to a server on S, it instead connects to the SOCKS server running on G. Using the SOCKS protocol, H requests a connection to S. The SOCKS server makes a connection from G to S on behalf of H and then steps out of the way, passing data back and forth between H and S.

A typical SOCKS installation

Figure 7-3. A typical SOCKS installation

A general drawback of application-level proxying is lack of transparency: only those programs written with support for the particular proxying scheme have network access. SOCKS, however, isn’t specific to any higher-level protocol such as HTTP or SMTP. It provides general services: makes a TCP connection, pings a host, performs a traceroute, etc. Many of its services match the existing programming boundary between applications and network-services libraries. As a result, on modern computer systems employing dynamically linked libraries, it is often possible to extend SOCKS to non-SOCKS-aware applications, such as SSH, by replacing the right libraries with SOCKS-aware ones.

SOCKS comes in two versions, SOCKS4 and SOCKS5. There are two major added features in SOCKS5: authentication and naming support. SOCKS5 supports user authentication so that a proxy can apply access control and user logging to its service. “Naming support” refers to the fact that in SOCKS4, a proxy client expresses the socket it wants to reach as an (IP address, port) pair. In real-world situations, however, the client will often know only the name, not the address, of the host it wants to reach. Furthermore, it may not be able to resolve that name directly, since being behind a proxy, it is likely to be in a different naming context than the server (e.g., a corporate network with split DNS). With SOCKS5, the client can instead pass a (name, port) pair to the proxy server, leaving the proxy to perform the name lookup where it is mostly likely to succeed.

There are two ways in which SSH clients use SOCKS:

  • As a normal SOCKS client, as described earlier.

  • As a SOCKS server, in conjunction with port forwarding. This allows for dynamic forwarding, by which other SOCKS clients may reach any TCP socket on the other side of an SSH connection, through a single forwarded port.

OpenSSH supports only the second method, while Tectia supports both.

7.4.7.1 SOCKS in OpenSSH: using DynamicForward

Dynamic forwarding in OpenSSH is done using the -D switch or DynamicForward configuration statement:

    $ ssh -D1080 server

or:

    # ~/.ssh/config:
    host server
      DynamicForward 1080

As with static (-L) port forwarding, this command causes the SSH client to listen for TCP connections on the given port (here 1080, the standard SOCKS port). Note, however, that there’s no argument specifying a target socket for the forwarding! That’s because this sort of forwarding is completely flexible: each connection to port 1080 can go to a different remote socket, given at connection time via the SOCKS protocol. Set any network client with SOCKS support to use this SSH-forwarded port as its “SOCKS server,” and it will have complete TCP access to the network on the other side of the SSH connection.

Just as with static forwarding, a dynamically forwarded port by default listens only on the loopback address. Use the -g switch to have it listen on all host addresses. This option affects all locally forwarded ports established with this instance of ssh.

Unfortunately, OpenSSH does not have SOCKS client support built in. However, there are a number of packages around for conveniently “socksifying” existing programs on the fly; two such packages are tsocks and runsocks. They both play with the system dynamic linker to replace basic network library calls with SOCKS-aware wrappers, and they are both effective on OpenSSH.

If this sort of linking trick doesn’t work, then you can use a separate program instead. You’ll need a simple utility which makes the connection through your SOCKS proxy, e.g., a socksified version of netcat (nc):

Then simply:

    # OpenSSH
    # ssh -o ProxyCommand="nc %h %p" ...

7.4.7.2 SOCKS in Tectia

Tectia supports both SOCKS client and server (dynamic-forwarding) features, and both SOCKS4 and SOCKS5. However, it does not support user authentication in the SOCKS5 client.

Tectia SOCKS client The Tectia SOCKS client feature is controlled with a single parameter, set with the SocksServer configuration keyword or the SSH_SOCKS_SERVER environment variable. The configuration option overrides the environment variable if both are present.

The SocksServer keyword is a string with the following format:

socks://[user]@gateway[:port]/[net1/mask1,net2/mask2,...]

Here, gateway is the machine running the SOCKS server, user is the username you supply for identification to SOCKS, and port is the TCP port for the SOCKS server (by default, 1080). The net/mask entries indicate netblocks that are to be considered local; that is, ssh uses SOCKS only for connections lying outside the given network ranges. The mask is given as the length of the network prefix, not an explicit mask, e.g., 192.168.10.0/24 rather than 192.168.10.0/255.255.255.0.

The parts of the string enclosed in square brackets are optional. So, an SSH_SOCKS_SERVER value can be as simple as this:

socks://laces.shoes.net

With this value, ssh uses SOCKS for all connections. It connects to a SOCKS server running on laces.shoes.net, port 1080, and it doesn’t supply a username. You’ll probably never want to use an SSH_SOCKS_SERVER setting as simple as this one, which uses the SOCKS server for all ssh connections, even those connecting back to the same machine or to a machine on the same network. A better setup is to use SOCKS only for hosts on the other side of the gateway from you. Here’s a more complete example:

socks://[email protected]:4321/127.0.0.0/8,192.168.10.0/24

With this value, ssh connects directly to itself via its loopback address (127.0.0.1), or to hosts on the class C network, 192.168.10.0. It uses SOCKS for all other connections, supplying the username “dan” and looking for the SOCKS server on port 4321.

Tectia SOCKS server (dynamic port forwarding) Tectia also has dynamic port forwarding via SOCKS, as described earlier for the OpenSSH -D option. [7.4.7.1] It works analogously, using this syntax:

    # Tectia
    $ ssh -L socks/1080 server

You could then even use a separate ssh command as a SOCKS client of this one, to reach a second SSH server on the far side of the first one:

    # Tectia
    $ ssh -o 'SocksServer socks://localhost/' ...

7.4.8 Forwarding

Port forwarding and X forwarding are covered in Chapter 9 and agent forwarding in Chapter 6. We mention them here only for completeness, since forwarding can be controlled in the client configuration file and on the command line.

7.4.9 Encryption Algorithms

When establishing a connection, an SSH client and server have a little conversation about encryption. The server says, “Hello client, here are the encryption algorithms I support.” In return, the client says, “Hi there server, I’d like to choose this particular algorithm, please.” Normally, they reach agreement, and the connection proceeds. If they can’t agree on an encryption algorithm, the connection fails.

Most users let the client and server work things out themselves. But if you like, you may instruct the client to request particular encryption algorithms in its conversation with the server. This is done with the Ciphers keyword followed by a comma-separated list of encryption algorithms of choice:

    Ciphers blowfish,3des

or the -c command-line option, either followed by a comma-separated list (OpenSSH) or specified multiple times (Tectia):

    # OpenSSH
    $ ssh -c blowfish,3des server.example.com

    # Tectia
    $ ssh -c blowfish -c 3des server.example.com

indicating that any of these algorithms is acceptable.

All ciphers acceptable by a server may be specified for the client. [5.3.5] Check the latest SSH documentation for a current list of supported ciphers.

7.4.10 Integrity-Checking (MAC) Algorithms

The -m command-line option lets you select the integrity-checking algorithm, known as the message authentication code (MAC), used by the SSH-2 protocol : [3.8.3]

    $ ssh -m hmac-sha1 server.example.com

You can specify multiple algorithms on the command line, either as a comma-separated list (OpenSSH) or with multiple -m options (Tectia):

    # OpenSSH
    $ ssh -m hmac-sha1,hmac-md5 server.example.com

    # Tectia
    $ ssh -m hmac-sha1 -m hmac-md5 server.example.com

and the SSH server selects one to use. OpenSSH supports the MACs keyword to do the same thing:

    # OpenSSH
    MACs hmac-sha1,hmac-md5

7.4.11 Host Key Types

OpenSSH lets you choose host key types you will accept. Provide a comma-separated list of types, from highest to lowest precedence, to the HostKeyAlgorithms keyword. See the ssh_config manpage for the current selection of algorithms.

    # OpenSSH
    HostKeyAlgorithms ssh-dss,ssh-rsa

Suppose you are about to SSH to a new server for the first time. Being security conscious, you have obtained the server’s RSA hostkey through reliable means and placed it in ~/.ssh/known-hosts. But when you connect, you find that OpenSSH uses the server’s DSA key instead, and complains about an unknown hostkey. OpenSSH is not smart enough to prefer a key type it has over one it doesn’t—but you can work around this by setting HostKeyAlgorithms to ssh-rsa.

7.4.12 Session Rekeying

The RekeyIntervalSeconds keyword specifies how often (in seconds) the Tectia client performs key exchange with the server to replace the session data-encryption and integrity keys. The default is 3600 seconds (one hour), and a zero value disables rekeying:

    # Tectia
    RekeyIntervalSeconds 7200

7.4.13 Authentication

In a typical SSH setup, clients try to authenticate by the strongest methods first. If a particular method fails or isn’t set up, the next one is tried, and so on. This default behavior should work fine for most needs.

Nevertheless, your clients may request specific types of authentication if they need to do so. For example, you might want to use public-key authentication only, and if it fails, no other methods should be tried.

7.4.13.1 Requesting an authentication technique

OpenSSH clients can request specific authentication methods by keyword. The syntax is the same as the server’s in /etc/ssh/sshd_config, and you can specify all the same authentication methods. [5.4.1] Examples are PasswordAuthentication, PubKeyAuthentication, and KerberosAuthentication, followed by yes or no:

    # OpenSSH
    PasswordAuthentication no
    PubKeyAuthentication yes

Additionally, you can specify the order in which the client should try these authentication methods, with the PreferredAuthentications keyword:

    # OpenSSH
    PreferredAuthentications publickey,hostbased,password

The ssh_config(5) manpage lists the currently supported methods.

For Tectia, the AllowedAuthentications keyword selects one or more authentication techniques. Again, the keyword has the same use here as for the Tectia server: [5.4.1]

    # Tectia
    AllowedAuthentications publickey, password

7.4.13.2 The server is the boss

When a client specifies an authentication technique, this is just a request, not a requirement. For example, the configuration:

    PasswordAuthentication yes

informs the SSH server that you, the client, agree to participate in password authentication. It doesn’t guarantee that you will authenticate by password, just that you are willing to do it if the server agrees. The server makes the decision and might still authenticate you by another method.

For a client to require an authentication technique, it must tell the server that one, and only one, technique is acceptable. To do this, the client must deselect every other authentication technique. For example, to try only password authentication with the server, use OpenSSH’s PreferredAuthentications keyword:

    # OpenSSH
    PreferredAuthentications password

or Tectia’s AllowedAuthentications keyword, which has the same syntax as the server keyword of the same name: [5.4.1]

    # Tectia
    AllowedAuthentications password

If the server doesn’t support password authentication, however, this connection attempt will fail.

7.4.13.3 Detecting successful authentication

Tectia provides two keywords for reporting whether authentication is successful: AuthenticationSuccessMsg and AuthenticationNotify. Each of these causes Tectia clients to print a message after attempting authentication.

AuthenticationSuccessMsg controls the appearance of the message “Authentication successful” after authentication, which is printed on standard error. Values may be yes (the default, to display the message) or no:

    # Tectia
    $ ssh server.example.com
    Authentication successful.
    Last login: Sat Jun 24 2000 14:53:28 -0400
    ...
    $ ssh -p221 -o 'AuthenticationSuccessMsg no' server.example.com
    Last login: Sat Jun 24 2000 14:53:28 -0400
    ...

AuthenticationNotify, an undocumented keyword, causes Tectia’s ssh to print a different message, this time on standard output. If the authentication is successful, the message is “AUTHENTICATED YES”; otherwise, it’s “AUTHENTICATED NO”. Values may be yes (print the message) or no (the default):

    $ ssh -q -o 'AuthenticationNotify yes' server.example.com
    AUTHENTICATED YES
    Last login: Thu Jun 24 2004 14:53:35 -0400
    ...

The behavior of these two keywords differs in the following ways:

  • AuthenticationSuccessMsg writes to stderr; AuthenticationNotify writes to stdout.

  • The -q command-line option [7.4.17] silences AuthenticationSuccessMsg but not AuthenticationNotify. This makes AuthenticationNotify better for scripting (for example, to find out if an authentication can succeed or not). Notice that exit is used as a remote command so that the shell terminates immediately:

        #!/bin/csh
        # Tectia
        # Get the AUTHENTICATION line
        set line = `ssh -q -o 'AuthenticationNotify yes' server.example.com exit`
        # Capture the second word
        set result = `echo $line | awk '{print $2}'`
        if ( $result == "YES" ) then
          ...

    In fact, AuthenticationNotify is used precisely in this manner by Tectia’s scp and sftp, when these programs run ssh in the background to connect to the remote host for file transfers. They wait for the appearance of the “AUTHENTICATED YES” message to know that the connection was successful, and they can now start speaking to the sftp-server.

AuthenticationSuccessMsg provides an additional safety feature: a guarantee that authentication has occurred. Suppose you invoke Tectia’s ssh and are prompted for your passphrase:

    # Tectia
    $ ssh server.example.com
    Passphrase for key "mykey": ********

You then see, to your surprise, a second passphrase prompt:

    Passphrase for key "mykey":

You might conclude that you mistyped your passphrase the first time, and so you type it again. But what if the second prompt came not from your ssh client, but from the server, which has been cracked by an evil intruder? Your passphrase has just been stolen! To counteract this potential threat, ssh prints “Authentication successful” after authentication, so the previous session actually looks like this:

    # Tectia
    $ ssh server.example.com
    Passphrase for key "mykey": ********
    Authentication successful.
    Passphrase for key "mykey":      Suspicious!

The second passphrase prompt is now revealed as a fraud.

7.4.13.4 Using ssh-keysign for hostbased authentication

Earlier we described how hostbased authentication requires a privileged program that provides SSH credentials to user processes. [3.4.3.6] In OpenSSH, this program is ssh-keysign. It must be installed setuid root (or any account that can read the client hostkey).

To allow a client system to perform hostbased authentication, the system administrator must set the EnableSSHKeysign keyword in /etc/ssh/ssh_config:

    # ssh_config
    EnableSSHKeysign yes

Most options in ssh_config are for the ssh program itself, but this one option is read by ssh-keysign. Hostbased authentication relies critically on the integrity of the client host and on other administrative requirements, such as correspondence of account names across hosts. It is crucial that it not be used unless these requirements are met; this option is to make sure that it is not enabled unless the system administrator consciously chooses to do so.

7.4.14 Data Compression

SSH connections may be compressed. That is, data sent over an SSH connection may be compressed automatically before it is encrypted and sent, and automatically uncompressed after it is received and decrypted. If you’re running SSH software on fast, modern processors, compression is generally a win. However, it also depends on your network speed, and whether the data you’re transferring is already compressed or not (say, a large compressed tar file).

To enable compression for a single session, use command-line options. Unfortunately, the implementations have incompatible syntax. For OpenSSH, compression is disabled by default, and the -C command-line option turns it on:

    # OpenSSH: turn compression ON
    $ ssh -C server.example.com
    $ scp -C myfile server.example.com:

For Tectia, however, -C means the opposite, turning compression off:

    # Tectia: turn compression OFF
    $ ssh -C server.example.com

and +C turns it on:

    # Tectia: turn compression ON
    $ ssh +C server.example.com

(There is no compression option for Tectia’s scp.) To enable or disable compression for all sessions, use the Compression keyword, given a value of yes or no (the default):

    Compression yes

7.4.15 Program Locations

The auxiliary Tectia program ssh-signer is normally located in Tectia’s installation directory, along with the other Tectia binaries. [3.4.3.6] You can change this location with the undocumented keyword SshSignerPath:

    # Tectia
    SshSignerPath /usr/alternative/bin/ssh-signer2

If you use this keyword, be sure to set it to the fully qualified path of the program. If you use a relative path, hostbased authentication works only for users who have ssh-signer2 in their search path, and cron jobs fail without ssh-signer2 in their path.

7.4.16 Subsystems

Subsystems are predefined commands supported by an SSH server. [5.8] Each installed server can implement different subsystems, so check with the system administrator of the server machine for a list.[114]

The -s option of ssh invokes a subsystem on a remote machine. For example, if the SSH server running on server.example.com has a “backups” subsystem defined, you run it as:

    $ ssh server.example.com -s backups

OpenSSH uses the remote command as the subsystem name: this must be specified last on the ssh command line. In contrast, Tectia obtains the subsystem name from the command-line argument that immediately follows the -s option. Therefore, our previous example works in both cases, so we highly recommend this syntax. Other orderings of the command line are possible for specific implementations:

    # OpenSSH
    $ ssh -s server.example.com backups

    # Tectia
    $ ssh -s backups server.example.com

Command-line arguments cannot be used with subsystems: neither OpenSSH nor Tectia provides any mechanism for passing them from client to server. If any extra arguments are given on the ssh command line, OpenSSH (mis)interprets them as part of the subsystem name:

    # OpenSSH
    $ ssh server.example.com -s backups /home
    Request for subsystem 'backups /home' failed on channel 0

whereas Tectia simply forbids extra command-line arguments if -s is used:

    # Tectia
    $ ssh server.example.com -s backups /home
    ssh: FATAL: No command allowed with subsystem.

7.4.17 Logging and Debugging

Earlier in the chapter, we introduced the -v command-line option which causes SSH clients to print verbose debugging messages. [7.3] Verbose mode works for ssh and scp, e.g.:

    $ ssh -v server.example.com

OpenSSH also has the LogLevel keyword, which takes the following levels as an argument: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG1, DEBUG2, and DEBUG3 (in order of increasing verbosity). The value DEBUG is equivalent to DEBUG1, and:

    # OpenSSH
    $ ssh -o LogLevel=DEBUG

is equivalent to ssh -v.

Verbose mode can also be turned on for Tectia with the (surprise!) VerboseMode keyword:

    # Tectia
    VerboseMode yes

If you ever encounter problems or strange behavior from SSH, your first instinct should be to turn on verbose mode.

Tectia’s ssh has multiple levels of debug messages; verbose mode corresponds to level 2. You can specify greater or less debugging with the -d command-line option, followed by an integer from 0 to 99:

    # Tectia
    $ ssh -d0      No debugging messages
    $ ssh -d1      Just a little debugging
    $ ssh -d2      Same as -v
    $ ssh -d3      A little more detailed
    $ ssh -d#      And so on...

Tectia’s -d option may also use the same module-based syntax as for serverdebugging: [5.9]

    # Tectia
    $ ssh -d Ssh2AuthPasswdServer=2 server.example.com

Tectia’s scp also supports this level of debugging, but the option is -D instead of -d since scp -d is already used to mean something else:

     # Tectia
    $ scp -D Ssh2AuthPasswdServer=2 myfile server.example.com

To disable all debug messages, use -q:

    $ ssh -q server.example.com

or specify it with the LogLevel (OpenSSH) or QuietMode (Tectia) keyword:

    # OpenSSH
    LogLevel QUIET

    # Tectia
    QuietMode yes

Finally, to print the program version number, use -V:

    $ ssh -V

7.4.18 Random Seeds

Tectia lets you change the location of your random seed file, which is ~/.ssh2/random_seed by default: [5.3.1.2]

    # Tectia
    RandomSeedFile /u/smith/.ssh2/new_seed


[107] Tectia accomplishes the same thing with identification files, which may contain multiple keys.

[108] Per the constant SSH_MAX_IDENTITY_FILES in the source code.

[109] scp already has a lowercase -p option that means “preserve file permissions.” [7.5.4]

[110] Although this is a client setting, the SSH server ultimately controls how many authentication attempts to accept.

[111] The no-pty option in the authorization file can override this request for a tty. [8.2.8]

[112] The error occurs as ssh attempts to read input from the now disconnected pseudo-terminal.

[113] Local forwardings cannot be canceled.

[114] Or examine the remote machine’s server configuration file yourself for lines beginning with subsystem.

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

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