OpenSSH
From HerzbubeWiki
Contents |
Overview
This page provides information about configuring and using SSH (or rather, the quasi-standard OpenSSH implementation).
References
- http://www.securityfocus.com/infocus/1810
- A very good introductory article about user identities.
- http://www.securityfocus.com/infocus/1812
- A very good introductory article about using ssh-agent
Debian packages
The following Debian package needs to be installed:
ssh
This is a meta package which resolves to
openssh-server openssh-client
Server configuration
Global configuration
So far, no manual configuration has been necessary.
For future reference:
- the daemon's configuration is located in
/etc/ssh/sshd_config
- the (unencrypted) private and public host keys are located in
/etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key.pub
Per user configuration
To allow login by public/private key instead of password-based, those public keys that are allowed to login must be listed in
~/.ssh/authorized_keys
To quote from man sshd: "The content of the file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others.". My personal file therefore looks like this:
patrick@pelargir:~$ l .ssh total 12 drwxr-xr-x 2 patrick patrick 4096 Jun 11 21:04 . drwxr-xr-x 8 patrick patrick 4096 Jul 13 20:00 .. -rw------- 1 patrick patrick 725 Nov 12 2009 authorized_keys patrick@pelargir:~$ cat .ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCuR259CxKjoSQd7cHy0IkXoUbmjqhTHkrSBX1NlZll0OluMVqZ/Pj6ntf4oqPL [...]
Note: See this HOWTO on the PGP page for a instructions on how to use GnuPG to generate an RSA key that is usable for SSH authentication.
Client configuration
Location of configuration files
The client's configuration is located in these files:
- /etc/ssh_config : Default configuration for all users on the machine
- ~/.ssh/config : User-specific configuration
Identity/Public key authentication
Instead of providing a password for authentication, it is also possible to identify using an RSA or DSA public/private keypair. Basically it works like this:
- You generate a keypair
- You copy the public key to the remote machine and add it to the file ~/.ssh/authorized_keys in the target user's home directory
- You keep the private key on the local machine in the file ~/.ssh/id_rsa (if it's an RSA key) in your home directory
- You initiate an SSH session
- SSH asks you for the private key's passphrase
- If the passphrase is correct, the login will be successful.
- If you don't want to enter the passphrase for each new SSH session, you have to either use an unencrypted private key (BAD idea), or use ssh-agent (see appropriate section further down)
- Note: When logging in, the private key is never transmitted from local to remote machine! Instead the two machines work out a challenge that can only be "solved" by the local machine when it has access to the decrypted private key. When the user supplies the correct passphrase, the local machine gains access to the decrypted private key, can "solve" the challenge and therefore prove to the remote machine that the local user is indeed who he claims to be. To see all the stuff that happens behind the scenes during a login, use the command line option -v.
To create an RSA public/private keypair (public key is stored in ~/.ssh/id_rsa.pub, private key is stored in ~/.ssh/id_rsa):
ssh-keygen -t rsa
To view the fingerprint of an RSA key (using the public part of the keypair):
ssh-keygen -lf id_rsa.pub
Multiple identities
- If you want to allow multiple identities to login to a remote account, that account's authorized_keys file must contain a list of all those keys.
- If you want to have multiple identities on your local machine, each identity's private key must be placed in its own file. You then have to select the appropriate identity file using the
-icommand line option, or the identity file must be specified on a per-host basis in SSH's configuration file~/.ssh/config. For instance, to use a different identity for each different user on a remote system, place the following snippet in~/.ssh/config:
Host pelargir pelargir.herzbube.ch # %r expands to the remote user name IdentityFile ~/.ssh/%r.id_rsa
Multiple identities (roles) with which to connect to the same remote account
A real-life example that I use to distinguish between the administrator and user roles when working with Gitosis (see the Git page on this wiki):
Host gitosis-admin HostName pelargir User gitosis IdentityFile ~/.ssh/admin.id_rsa IdentitiesOnly yes Host gitosis-user HostName pelargir User gitosis IdentityFile ~/.ssh/patrick.id_rsa IdentitiesOnly yes
What does this mean?
- We have defined two host aliases: One is called "gitosis-admin", the other "gitosis-user"
- Whenever we refer to one of these aliases in the future, SSH will use the options below the alias to perform the connection to the server
- If we want to perform administrative duties, we use the alias "gitosis-admin" which will cause SSH to use the "admin" identity
- If we want to do normal developer work (which hopefully will be most of the time) we use the alias "gitosis-user", which will cause SSH to use the "patrick" identity
- 'The
IdentitiesOnly yesoption is required to preventssh-agentfrom offering the wrong key file to SSH. Instead,ssh-agentis forced to only use the identity that is explicitly specified under the host alias. To understand the issue, let's have a look at the following scenario:- You have done some work under the normal user identity, which means that
ssh-agenthas now cached that identity's key - Now you want to perform admin work and try to clone the
gitosis-admin.gitrepository - BOOM, cloning does not work and you get a mysterious message "Repository read access denied" - What happens here is this: Because
ssh-agenthas cached the normal user identity key, it offers that key to SSH every time a connection is about to be made. When SSH finds out that the key is allowed to login to the server'sgitosisaccount, it happily accepts and uses the key. Once the connection has been established, SSH hands control over to the Gitosis software which finds out - too late - that the identity used does not have sufficient access rights to read thegitosis-admin.gitrepository
- You have done some work under the normal user identity, which means that
- The problem here is conceptual: SSH only cares about authentication, not authorization - authorization is the domain of the application using SSH (Gitosis in this case). In other words: For SSH, every identity has the same "value": Either it is allowed to login (authenticate) to the remote side, or it is not. Gitosis, though, attaches an additional meaning to identities: Authorization, or access rights. The
IdentitiesOnlyoption must therefore be used to ensure that the proper identity is used on every connection attempt, regardless of the state of thessh-agentcache at connection time.
Using ssh-agent
If you make repeated connections to the same remote user/host, it quickly becomes tiring to enter the same passphrase for accessing the authenticating RSA key over and over again. One solution would be to store the private key unprotected, i.e. without a passphrase. For obvious reasons, this is not a very good solution.
An alternative is to use the Authentication Agent ssh-agent. ssh-agent will cache a private RSA key once it has been decrypted so that it can be used repeatedly for SSH connections. It works like this:
- Start ssh-agent, e.g. when you log in.
- This can be done automatically by adding the appropriate command to ~/.profile or some similar login-hook file.
- On some systems, automatic startup of ssh-agent might already be configured in a similar way.
- On Mac OS X, ssh-agent starts automatically when the first SSH connection is made.
- Use ssh-add to add the desired keys to ssh-agent
- ssh-agent will prompt you for the passphrase (is this true? or is it ssh-add which does the prompting?)
- On success, ssh-agent caches the decrypted key
- Make an SSH connection
- When ssh would normally require the private key for its operation, it will first query ssh-agent whether or not it has the required key
- ssh-agent never gives out the key itself. Instead, ssh tells ssh-agent to perform the required operation(s) on its behalf, and ssh-agent returns the operation's result back to ssh
- ssh-add -L lists all keys cached by ssh-agent
- ssh-add can also be used to remove keys from ssh-agent
Authenticating Agent Forwarding can be used to create an "authentication chain" that spans multiple systems. If you are logged in to a remote system A and from there would like to make another connection to remote system B, you can setup a forwarding mechanism so that ssh-agent on your local machine will be queried when you make the connection attempt to remote system B. In this way, the private authenticating RSA key never has to leave your local machine. This forwarding mechanism is enabled like this:
ssh -A <host>
In the configuration file, the following enables forwarding:
ForwardAgent yes
X11 Forwarding
The following command logs into a remote system and forwards X11 traffic from that system to the local system (which acts as X server):
ssh -X <host>
Note: It appears that X11 forwarding circumvents access control set up with xhost (at least this is the case on my Mac OS X box). It becomes clearer why this is the case if we look at how ssh sets the DISPLAY variable on the remote system: localhost:10.0. This means that the X11 connection is not made through a normal X11 network connection (which would be protected by xhost), but the connection is made through the SSH connection. To the local X server it appears that a locally launched program (= ssh) wants to display stuff.
X11 forwarding may be enabled by default by adding the following to the local config file (either globally or for specific hosts only):
ForwardX11 yes
Port Forwarding
Port forwarding (tunneling) is similar to X11 forwarding, but more generalized. The following command establishes port forwarding:
ssh -L 9110:mail.example.net:110 shell.example.net
From now on, all connections to localhost:9110 are routed via shell.example.net to port 110 at the destination host mail.example.net. Notes:
- mail.example.net sees the connection as coming from shell.example.net
- Traffic between shell.example.net and mail.example.net is not encrypted!!!
- All locally logged in users can see and use port 9110; this can be either useful or dangerous...
- Users that are logged in via a remote connection cannot see or use port 9110, unless the user establishing the forwarding tunnel has specified the -g option
- Ports below 1024 are privileged and can be used for forwarding only with root privileges; this makes sense if you think of a multi-user system where it is not desirable that one user can change an important port such as 25 (SMTP) or 53 (DNS) into a forwarding tunnel, without the other users noticing
- On the server side, port forwarding can be disallowed by specifying AllowTcpForwarding no in the server config file /etc/ssh/sshd_config. I have read somewhere, though, that this may be circumvented if someone is really determined
Port forwarding may also be enabled through the local config file:
Hostname shell.example.com LocalForward 9110 mail.example.com:110
Note: Use RemoteForward to establish a "reverse-forwarding" connection, i.e. when you connect to a remote system, a port is forwarded from that remote system back to your local system.
Compression
Useful on a slow network connection: Data transferred over the SSH connection can be gzip compressed with the following command:
ssh -C <host>
Compression may also be enabled by adding the following to the local config file:
Compression yes CompressionLevel <lvl>
Possible compression levels are 1 (fast, worst compression) to 9 (slow, best compression). The default level is 4.
Cipher selection
It is possible to select the Cipher that should be used for encrypting the SSH connection. Selecting a different cipher is probably most useful for SSH1 connections where the default cipher is the slow 3DES and it is desirable to select a faster cipher such as Blowfish.
The command to select a specific cipher is
ssh -c <cipher_spec> <host>
The cipher can be specified using one of the allowed keywords, or a comma-separated list of such keywords. The allowed keywords differ between SSH1 and SSH2. See the man page for details.
The cipher to use can also be specified in the configuration file (different options for SSH1 and SSH2):
Cipher <cipher> # SSH1 connections Ciphers cipher_spec> # SSH 2 connections
Running remote shell commands
Instead of running an interactive shell on the remote system, it is also possible to run a single command:
ssh <host> ls -l
It is possible to pipe data to the remote command:
tar cf - <srcdir> | ssh <host> 'cat >dest.tar'
(the remote command in this case is enclosed in single quotes to prevent the local shell from evaluating the ">" character)
SSH on the Mac
Outgoing
When a user starts his first SSH session to a remote machine, launchd automatically starts an ssh-agent process in the background, which from then on captures all private keys that are used to login to remote machines. If a private key is protected with a passphrase, a GUI dialog pops up where you have to enter the passphrase (instead of a command line prompt in Terminal.app). Optionally, you can allow the passphrase to be stored in your personal Mac OS X keychain, in which case you will not have to enter the passphrase in the future (the entry into the keychain is made so that ssh-agent, ssh-add and ssh always have access to the passphrase).
Note: If you change or delete a private key file, ssh-agent continues to cache the old key (no doubt with surprising results) until you remove the cached key using ssh-add -d.
X11.app is launched automatically when an SSH connection is made with X11 Forwarding.
Incoming
To allow SSH login to a Macintosh machine, go to Systemsettings->Sharing and enable "remote login" ("Entfernte Anmeldung" on German systems). You must provide admin privileges to do so.
