http://www.g-loaded.eu/2005/11/10/ssh-with-keys/
https://help.ubuntu.com/community/SSH/OpenSSH/Keys
"
Secure Shell or SSH is both a computer program and an associated network protocol designed for logging into and executing commands on a networked computer." -WikiPedia-
An SSH server can be set up in various ways, but in this document I’ll describe how it can be configured to:
- only support connections through the 2nd version of the SSH protocol (SSH-2)
- use DSA keys for user authentication, without permitting authentication with passwords
- allow only a specific group of users to connect
The SSH-2 protocol, apart from many other useful features, provides stronger security than SSH-1. It’s a bit more cpu hungry than the latter, but this should not be a problem. Using the above configuration, someone must be extremely lucky to manage to break into our system.
But, let me say a few words about how the authentication is done. The user creates a keypair, which consists of a private key, that can be protected with a passphrase, and a public key. The public key is transfered to the server and the private key is kept in our workstation. We assume that the user has accounts in both the server machine and his workstation. Everytime he tries to connect to the server, the keys are validated and the user is granted access.
Prerequisites
A
user account in the SSH server machine.
You need to install the following packages to the SSH server machine:
The client machines should have the following:
First things first…
I assume that our server machine (
server.example.com) is a headless one and that the SSH server is up and running with the default configuration. This permits users, including root, to login with their username/password combination. I also assume that we have already set up a user account on the server with the username "
leopard". From a client machine (
pc1.example.com) we connect like this:
# ssh leopard@server.example.com
Keypair generation
The default key directory is "
~/.ssh". Create this directory
in both the user leopard’s home on the server and in your current home directory on the client machine and chmod it so that only the users have access to it.
# mkdir ~/.ssh
# chmod 0700 ~/.ssh
Now, we will create our keypair
on our client machine. The following command creates a standard 1024-bit DSA keypair:
# ssh-keygen -t dsa -f ~/.ssh/id_dsa
You will be asked for a
passphrase for the private key. You can type any phrase here or leave it blank. Keep in mind that if you do not set a passphrase for you private key and someone else gets access to it, then it will take him only a few seconds to connect to your user account on the server. Anyway, this is up to you. After the key generation is finished, the files
id_dsa(private key) and
id_dsa.pub (public key) are created in the
~/.ssh/ directory.
Now, we will copy the public key to the
/home/leopard/.ssh/ directory on the server saving it with the name
authorized_keys and delete id_dsa.pub from our client machine, just because it’s not needed to be there.
# scp ~/.ssh/id_dsa.pub leopard@server.example.com:~/.ssh/authorized_keys
# rm -f ~/.ssh/id_dsa.pub
Make sure that you chmod both keys so that only the respective users have access to them. Issue the following command on
both the server and the client machine:
# chmod 0600 ~/.ssh/*
A limited group of SSH users
As an extra security measure, we will create a new group
on the server machine and configure the SSH server to only allow this group’s members to authenticate. So, we create a group named "
sshusers" and add user "
leopard" to it. This has to be done as root:
# groupadd sshusers
# usermod -a -G sshusers leopard
The SSH Server configuration
The SSH server’s configuration file is
/etc/ssh/sshd_config. Most of the default options do not need to be modified. What we’ll do is to set it up so that only the members of the "
sshusers" group can authenticate using keys instead of passwords. So, as root, fire up your favourite text editor and edit the server configuration file.
NOTE: It’s a good habit to create backups before editing system files.
The options that need to be modified are shown below:
Port 22
Protocol 2
AddressFamily inet
ListenAddress 192.168.0.1
With these we configure the server to listen on port 22, accept connections only over the SSH-2 protocol, use the IPv4 address family and bind on the 192.168.0.1 IP address. Only the "
protocol" option is really critical. You can set the others as you like or leave the defaults.
HostKey /etc/ssh/ssh_host_dsa_key
Uncomment or add this line. This is exactly the same as the default option, but needs to be uncommented in the server configuration file, so that the server shows its DSA key’s fingerprint when the client tries to authenticate the server during the connection process. If this is not set, then the server shows its RSA key’s fingerprint (the reason is unknown to me).
LoginGraceTime 2m
PermitRootLogin no
MaxAuthTries 1
The
LoginGraceTime option sets a time limit for the user authentication process. If this time passes and the user has not yet authenticated succesfully, then the server closes the connection. Leave this value to the default "
2m" until everything is set up properly, so that you have enough time to read any server messages. After that, you can lower it to a reasonable value. I have set it to "
20s".
Setting the "
PermitRootLogin" option to "
no" the server does not allow root to login directly. You can still use "
su" after you have succesfully logged in as a normal user.
The "
MaxAuthTries" option sets the maximum login attempts per connection. Since we use keys and key validation never fails, we set it to "1".
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
These are the default options. I just add them here so that you make sure they are set up properly in your config.
RSAAuthentication no
PasswordAuthentication no
UsePAM no
KerberosAuthentication no
GSSAPIAuthentication no
We do not want the server to let users authenticate using passwords or use SSH-1 based authentication methods. You should comment out any Kerberos or GSSAPI options too.
AllowGroups sshusers
Only users that belong to the "
sshusers" group can authenticate. Any other user will be rejected without even being given the oportunity to authenticate.
MaxStartups 2
This option specifies the maximum number of concurrent unauthenticated connections to the SSH Server. It has nothing to do with the number of authenticated connections. The default value is "10". We lower this value in order to limit the connections from third parties which do not have an account on our server machine.
Banner /etc/ssh/banner
Finaly, you can set a text file that will be displayed as a banner when someone connects to the server. Just remember that it is displayed before the authentication takes place, so do not be very descriptive. The banner is not really needed.
This is all we have to do. The rest of the configuration options should be left to their default values, unless you need something different. This is up to you.
Restarting the server
Now, that we have finished editing the config file, we need to restart the server, so that our changes take effect. Before that, I would recommend deleting any existing server keys. Don’t worry, they will be recreated as soon as the service is restarted. A quick way to delete all the keys is to:
# rm -f ssh_host*key*
Then restart the server:
# service sshd restart
Note that the key creation time may vary from machine to machine, so it may take a few minutes if the CPU is slow.
The server logging is done through syslog and authentication information is sent to
/var/log/secure. This file should not be world-readable.
A last thing is to take a note of the server’s DSA public key fingerprint, so that we can compare it with the fingerprint the server sends to our client when we connect. This is important for connections to the server from locations other than our LAN in order to be sure that we actually connect to our server. On the server console type:
# ssh-keygen -l -f /etc/ssh/ssh_host_dsa_key.pub
Take a note of the fingerprint.
Connect to the server
To connect to our SSH server from our client machine (pc1.example.com), we type:
# ssh leopard@server.example.com
I suggest that the first time you connect you should add the
-v option to the above command for verbose output.
Before the user authentication takes place, the ssh client will try to authenticate the SSH server. Since, there is no stored information about your server it will present you the server’s public DSA key fingerprint so you can compare it with the fingerprint you had previously taken a note of during the server configuration. If the fingerprints are identical, you can answer positively to the question. At this time the file
~/.ssh/known_hosts is created on your client machine and it contains the trusted SSH server’s information. You will never be asked again if you trust this server. If the fingerprint comparison took you longer than the server’s
LoginGraceTime, the user authentication does not take place. Just try to reconnect. This time you will eventually log in succesfully using key authentication.
Hashing the known_hosts file
Because the servers’ hostnames and addresses are stored in plain text in the
known_hosts file, hashing it is a good habit. This can be done using the ssh-keygen utility. Type:
# ssh-keygen -H -f ~/.ssh/known_hosts
This process makes it unreadable, but the ssh programs can still read the contents. Make sure you permanently delete the
known_hosts.old backup file.
Change your private key’s passphrase
If you ever need to change the private key’s passphrase you can use ssh-keygen:
# ssh-keygen -p -f ~/.ssh/id_dsa
The ssh-agent
Although key authentication has many advantages over the authentication with passwords, it has one significant drawback: we have to type the passphrase every time we make a connection to the SSH server. One solution would be not to use a passphrase for our private key. But, this is unacceptable. If someone else gets access to our key and finds out to which servers we connect, things get really bad. A second solution is to use the
ssh-agent (part of the openssh package) which caches our passphrase in the memory and then it’s automatically used when we make the connection to the SSH server. This way, we only need to type the passphrase once. This is by far more secure than not using a passphrase.
The ssh-agent is a small daemon that runs in the background. When it is run, it exports some environment variables (SSH_AUTH_SOCK, SSH_AGENT_PID) which can be used by programs like
ssh-add in order to manage the agent’s cached info or by other programs like the
ssh client in order to use this cached info for user authentication. These environment variables must be available to these programs, so the ssh-agent needs to be started in our login shell. There are many different ways to start the agent. Here I’ll describe a rather simple, but very efficient one.
The ssh-agent’s configuration
What we need is to start the agent when we login to our client machine’s shell and stop it when we log out. So, we add the following line to
~/.bash_profile:
eval `ssh-agent`
Why do we use
eval? When the ssh-agent is started, it just prints some commands to the stdout. These commands set and export the environment variables we talked about earlier. We use eval, so that these commands are actually executed, or better, evaluated by the shell, so the environment variables are made available to all applications that can use them.
We add the following line to
~/.bash_logout
eval `ssh-agent -k`
This "unsets" the environment variables and kills the agent every time we logout.
Management of cached passphrases
A small utility called
ssh-add is used to manage the cached passphrases.
To add a key to the ssh-agent’s cache, we issue the command:
# ssh-add ~/.ssh/id_dsa
We are prompted for the passphrase. After typing it succesfully, it gets cached. From now on, the cached passphrase will be automatically used for every connection we make to the SSH server. Convenient!
If we store our key to the standard location
~/.ssh/ and name it with the standard filename
id_dsa, then ssh-add can be run without arguments. Our key will be used.
To list the cached keys we type:
# ssh-add -l
To remove a cached key:
# ssh-add -d ~/.ssh/id_dsa
To empty the ssh-agent’s cache:
# ssh-add -D
Further Reading
There are numerous articles around the web about SSH. Just use google. Keep in mind though that all the necessary info is in the man pages. You should not just read them, but rather study them:
- The official openssh manuals
- The openssh FAQ
-------------------------------------------------------------
Troubleshooting
Encrypted Home Directory
If you have an encrypted home directory, SSH cannot access your authorized_keys file because it is inside your encrypted home directory and won't be available until after you are authenticated. Therefore, SSH will default to password authentication.
To solve this, create a folder outside your home named /etc/ssh/ (replace "" with your actual username). This directory should have 755 permissions and be owned by the user. Move the authorized_keys file into it. Theauthorized_keys file should have 644 premissions and be owned by the user.
Then edit your /etc/ssh/sshd_config and add:
AuthorizedKeysFile /etc/ssh/%u/authorized_keys
Finally, restart ssh with:
sudo service ssh restart
The next time you connect with SSH you should not have to enter your password.
username@host's password:
If you are not prompted for the passphrase, and instead get just the
username@host's password:
|
prompt as usual with password logins, then read on. There are a few things which could prevent this from working as easily as demonstrated above. On default Ubuntu installs however, the above examples should work. If not, then check the following condition, as it is the most frequent cause:
On the host computer, ensure that the /etc/ssh/sshd_config contains the following lines, and that they are uncommented;
PubkeyAuthentication yes
RSAAuthentication yes
If not, add them, or uncomment them, restart OpenSSH, and try logging in again. If you get the passphrase prompt now, then congratulations, you're logging in with a key!
Permission denied (publickey)
If you're sure you've correctly configured sshd_config, copied your ID, and have your private key in the .ssh directory, and still getting this error:
Permission denied (publickey).
|
Chances are, your /home/ or ~/.ssh/authorized_keys permissions are too open by OpenSSH standards. You can get rid of this problem by issuing the following commands:
chmod go-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Debugging and sorting out further problems
The permissions of files and folders is crucial to this working. You can get debugging information from both the client and server.
if you think you have set it up correctly , yet still get asked for the password, try starting the server with debugging output to the terminal.
sudo /usr/sbin/sshd -d
To connect and send information to the client terminal
ssh -v ( or -vv) username@host's
Where to From Here?
No matter how your public key was generated, you can add it to your Ubuntu system by opening the file .ssh/authorized_keys in your favourite text editor and adding the key to the bottom of the file. You can also limit the SSH features that the key can use, such as disallowing port-forwarding or only allowing a specific command to be run. This is done by adding "options" before the SSH key, on the same line in the authorized_keys file. For example, if you maintain a CVS repository, you could add a line like this:
command="/usr/bin/cvs server",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc ssh-dss ...
When the user with the specified key logged in, the server would automatically run /usr/bin/cvs server, ignoring any requests from the client to run another command such as a shell. For more information, see the sshd man page. /755
SSH/OpenSSH/Keys (last edited 2011-03-20 15:06:19 by
dpm)
This article appeared in the digg.com homepage on November 16th, 2005. I thank all “diggers” by heart.