SSH authentication in 4 flavors
… and check why 5600+ Rails engineers read also this
SSH authentication in 4 flavors
We are connecting with remote servers every day. Sometimes we explicitly provide passwords, sometimes it just happens without it. A lot of developers don’t care how it works internally, they just get access, so why to bother at all. There are a couple ways of authentication, which are worth to know and I’d like to present you them briefly.
Each authentication method requires some setup on the very beginning. Once it’s done, we can forget about it and connect without any further configuration. However there are different ways to configure authentication on your server with different secure level and initial setup process. Let’s review the most common.
The SSH authentication protocol is a general-purpose user authentication protocol. It is intended to be run over the SSH transport layer protocol. This protocol assumes that the underlying protocols provide integrity and confidentiality protection.
From: http://tools.ietf.org/html/rfc4252
Ordinary password authentication
- User makes initial connection and sends a username as a part of SSH protocol.
- Server SSH daemon responds with password demand.
- SSH client prompts for password, which is transported through encrypted connection.
- If passwords match, access is granted and secure connection is established to a login shell.
Pros:
- Simple to set up
- Easy to understand
Cons:
- Brute force prone
- Each time password entering
Public key access
Prerequisites are that user creates a pair of public and private keys.
Private keys are often stored in an encrypted form at the client host, and the user must supply a passphrase before the signature can be generated. Even if they are not, the signing operation involves some expensive computation.
From: http://tools.ietf.org/html/rfc4252#page-9
Then, public key is added to $HOME/.ssh/authorized_keys
on a server. That may be done via ssh-copy-id
. You can read nice tutorial describing it quite well.
Connection itself:
- User makes initial call with username and request to authenticate using key.
- Server SSH daemon creates some challenge based on
authorized_keys
file and sends it back to SSH client. - SSH client looks for user’s private key encrypted by passphrase and prompts user for it.
- After user enters matching password, response for server is being created using that private key.
- Server validates the response and grants access to the system.
Pros:
- Using passphrase instead of password, which is identical for multiple servers with your public key in
authorized_keys
- Public keys cannot be easily brute-forced
Cons:
- More steps behind the scenes
- More complicated first-time configuration
Public key access with agent support
Both of previous methods was equally cumbersome because of necessity to enter password or passphrase each time we want co connect. This may be tedious when we communicate often with our remote servers.
Key agent provided by SSH suite comes with help, because it can hold private keys for us, and responds to request from remote systems. Once unlocked, it allows to connect without prompting for credentials anymore.
- User makes initial call with username and request to authenticate using key.
- Server SSH daemon creates some challenge based on
authorized_keys
file and sends it back to SSH client. - SSH client after receiving key challenge, forwards it to agent, which opens user’s private key.
- User sees one-time prompt for the passphrase to unlock the private key.
- Key agent constructs the response based on received challenge and sends it back to SSH, which does not know anything about private key at all.
Pros:
- Does not prompt for password each time, but only the first time
- SSH doesn’t have access to private key, which never leaves the agent
Cons:
- Requires additional key agent setup
- If remote server makes some further connection to ssh servers elsewhere, it requires either password access or private key on our remote server
Public key access with agent forwarding
This last way is the most perfect of all above, because it gets rid of the second disadvantage in almost ideal previous method. Instead of requiring passwords or passphrases on intermediate servers, it forwards request, through chained connections, back to initial key agent.
- We are connected and authenticated in the same way as in previous method already
- Our remote server (Foo) makes remote call to another one (let’s name it Bar) and connection requires provisioning using key.
- SSH daemon residing in Bar constructs a key challenge based on its own
authorized_keys
file. - When SSH client on Foo receives challenge, it forwards that challenge to SSH daemon on the same machine. Now
sshd
can pass received challenge down to original client that invoked the initial call. - The agent running on home machine constructs a response and hands it as a response to Foo server.
- Now Foo connects back to Bar and answers with challenge solution. If it’s valid, access is granted.
For better understanding and real-life example, let’s imagine that this second connection may be some kind of scp
or sftp
transfer.
Pros:
- No need to struggle with irritating prompts anymore
Cons:
- Requires public keys installation on targeted systems
More about key negotiation
In order to connect with SSH server and authenticate using your public/private keypair, you have to first share your public key with the server. As we described before, that can be done using ssh-copy-id
or some script
#!/bin/sh
KEY="$HOME/.ssh/id_rsa.pub"
if [ ! -f ~/.ssh/id_rsa.pub ]; then
echo "Public key not found at $KEY"
echo "* please create it with "ssh-keygen -t dsa" *"
echo "* to login to the remote host without a password. *"
exit
fi
if [ -z $1 ]; then
echo "Please specify user@host as the first switch to this script"
exit
fi
echo "Putting your key on $1... "
KEYCODE=`cat $KEY`
ssh -q $1 "mkdir ~/.ssh 2>/dev/null; \
chmod 700 ~/.ssh; \
echo "$KEYCODE" >> ~/.ssh/authorized_keys; \
chmod 644 ~/.ssh/authorized_keys"
echo "done!"
Once it’s done, server can construct some challenge based on your public key. Because RSA algorithm is asymmetric, message encrypted using public key can be decrypted using private key and opposite.
Key negotiaton may be as follows: client receives a message encrypted by your public key and can decrypt it using your private key. Next, it encrypts this message with server public key and sends back to server, which uses its own private key to decrypt and validates if message matches this sent one initially.
Of course the above flow is only the example of how challenges may works. They are often more complicated and contain some MD5 hashing operations, session IDs and randomization, but the general rule is really similar. RFC offers far more comprehensive explanation of this whole process.
What is worth to know, there are to versions (v1 and v2) of SSH standard. According to OpenSSH’s ssh-agent protocol:
Protocol 1 and protocol 2 keys are separated because of the differing cryptographic usage: protocol 1 private RSA keys are used to decrypt challenges that were encrypted with the corresponding public key, whereas protocol 2 RSA private keys are used to sign challenges with a private key for verification with the corresponding public key. It is considered unsound practice to use the same key for signing and encryption.
Note that private key belongs only to you and is never shared anywhere.
Possible threats
As I described before, the basic benefit of using SSH agents is to protect your private key without need to expose it anywhere. The weakest link is SSH agent itself. Any kind of implementation must provide some way that allows to make request from client, some kind of interface to interact with. It’s usually done with UNIX socket accessible via file API. Although this socket is heavily protected by the system, nothing can really prevent from accessing it by root
. Any key agent set by root
has immediately granted necessary permissions so there’s no method preventing root
user from hijacking SSH agent socket. It may not be the best solution to connect with Bar server when Foo cannot be entirely trusted.
Summary
Now you see how authentication works and what are the ways to set it up. You may choose any configuration based on your needs, it’s advantages and drawbacks. Let’s secure your server without any fear now. Hope you find this useful.