© Tony Lawrence, aplawrence.com
Basics- sshMay 2001
Although "ssh" stands for "Secure Shell", it is not a shell like sh, csh or ksh. Rather, think of it as a way to secure your shell, whatever it is. Secure in this context means encrypted conversations between your machine and some other machine, and that's just about all it means: it doesn't mean that your system or even the system you are ssh'ing to are immune to break-ins or other security breaches and it doesn't necessarily even mean that you can be 100% sure that you really are even connected to the machine you think you are connected to (though you can be pretty sure- more on that below). Encrypted connections are really all that ssh does- everything else that the ssh suite includes, like the ability to copy files or run remote commands, is really just tools added to use the encrypted communications channel.
Why do you care about encryption? Well, because the standard Unix tools like telnet and ftp are not encrypted- everything you type, including your precious passwords, travels in packets that can at least potentially be seen by every machine they pass by or through. Even if you aren't protecting anything especially sensitive, it's not a good idea to have your passwords traveling the network (internal or the Internet) in plain sight for anyone to see. With ssh, that's not true- if you use passwords, they will be encrypted. You can also use ssh so passwords aren't used at all- so that it uses public key cryptography to authenticate you. In that case, everything is still encrypted, but no passwords are passed at all (see below for more explanation of this).
There are other tools that do similar things to ssh. For example, Kerberos is an authentication system that is fairly popular, and may become even more so due to Windows 2000's use of it. IPSEC is very low level authentication and encryption; it moves the responsibilities for this to the IP stack itself: programs like telnet and ftp are just used as they would be normally; the encryption and decryption is completely transparent to users. There are other less well known or related tools also. At one time, for example, PGP signatures and file encryption were a pretty common sight- but PGP is file oriented, not connection oriented- it's really not anything like ssh (yet it is, of course, a way to encrypt files).
The advantage of ssh is that it's fairly light weight, not demanding a lot of resources at the client or server end. It's easy for users to comprehend (at least at the simplest usage levels) and it pretty much "just works". It's flexible, powerful, and both feature rich and yet easy to use and understand- a rare combination.
Always keep in mind that ssh is just one small part of system security, and that security methods are constantly changing. Don't let your use of ssh lull you into thinking that you don't need to constantly be alert to that.
A simple ssh connection
Let's assume that you have an account on my server aplawrence.com (you don't, but let's just pretend). For reasons that have to do with my private amusement, your account on my server is "boopy" and your password is "mUstB50wAys2LOGin". No, you can't change your password.
I don't allow telnet connections to my server, so you are going to have to use ssh. You are logged in to your own Unix/Linux machine (there are Windows ssh clients available, for example PuTTY.) and you want to login as "boopy" on my machine. You type:
(I also like the AlphaCom 3 Terminal Emulator)
ssh -l boopy aplawrence.com
You will be asked for "boopy"'s password, and if you supply it correctly, you'll be logged in. Your login will look very much like it would had you been able to telnet, and in fact operates very much like telnet (but the standard telnet escapes will NOT work).
Had I been nice enough to give you an account with the same login name as you use on your own machine, you could have omitted the "-l boopy" and everything else would be the same. But we'll leave it at "boopy" (By the way, there IS NO "boopy" account at aplawrence.com- don't bother to try it).
The password (that awful password) and indeed everything else that passed between our two machines during this session would be encrypted. Even if I sat and watched your packets as they flowed in and out, I wouldn't gain any information about your activities (well, of course that's not strictly true- the volume of packets or lack thereof is information of a sort- so if you were doing a lot of "something", I'd know that, even if I couldn't know exactly what you were doing). For example, it was recently (recently if you are reading this in Spring 2001) discovered that someone watching a ssh conversation would be able to guess the approximate length of the password, and apparently even get the actual length of shell commands used during the session. The length of a password isn't much by itself, but if the system had also been compromised so that the hacker has access to the systems encrypted passwords (/etc/shadow for example), knowing the length makes brute force guessing attacks easier.
Well, as I said at the beginning, ssh is just one part of security. You might think from your usage so far that all that ssh is providing here is the encrypted password. That's not quite true, and I had alluded to that at the very beginning of this article. In addition to handling the encryption of your password, ssh also tries to make sure you are really connecting to the server you think you are connecting to. I say "tries", because in most situations all you can really trust is that the connection you made is to the very same machine that you have been connecting to in the past. Think of it like this: you can recognize your best friend, and would know if someone else tried to impersonate that person. But that person you've known "forever" might actually be an imposter- the driver's license they carry might really be someone elses, etc. Normally, ssh has the same relationship with the other computers it talks to. It has "known" them since its first conversation with them, and it can very safely guarantee that the system you connect to now is the same system it "knows". The ssh clients and servers exchange "host keys", which are uniquely generated and should be impossible to forge because they use public-key cryptography to for authentication.
Public key cryptography is complex and makes my head hurt, but conceptually it's pretty simple. You have a pair of "keys", one of which is public (anyone can know it) and the other is kept "private" (only you know it). If you have something encrypted with one of the keys, it can be decrypted with the other. How THAT part works is what makes my head hurt, so we'll just treat that as PFM (Pure Funky Magic) for the moment. But how to use that magic for security is pretty straight forward. Let's say that I want to prove to you that I'm really me. You have my public key, so you send me some data and ask me to encrypt it using my private key. I do so, and send it back to you encrypted. If, using my public key, you decrypt what I sent back and it matches the data you originally sent, you know that I have the private key that matches the public key that you "know" belongs to me.
Ah, but how do you know that? Well, in the case of ssh clients and servers, probably because the very first time the client talked to the server, the server gave the client its public key. It's possible that the public key came from some other source (SSL security works like that) , or in the mail, and was physically installed on the client, but in the case of the "boopy" account at aplawrence.com, your machine got pcunix's public key just by making a connection. In fact, on your very first connection, ssh would have told you that it didn't have a public key for aplawrence.com and would ask if you still wanted to connect. Replying "yes" to that causes aplawrence.com's public key to be stored in ~/.ssh/known_hosts for future use.
OK, so now you have a public key for me. What happens if somebody else steals my ip address or compromises DNS or your routing so that your attempt to ssh to me actually lands you somewhere else? Well, that person won't be able to decrypt something encrypted with the real aplawrence.com's public key. Your ssh client will tell you that, and warn you that you there could be a "man in the middle" attack going on right now -that's where the person who hijacked me connects to the real aplawrence.com also and makes you think you really reached me, but in reality the "man in the middle" is recording everything that happens between us and perhaps even altering data.
The same thing happens if I change my server. In fact, that has happened already- as aplawrence.com has grown, I have had to migrate it to more powerful hardware. My ssh server generates a different public/private key pair each time this happens, so if you tried to connect the day after I changed my hardware, your ssh client would complain (and the fix would be to remove aplawrence.com from ~/.ssh/known-hosts and make a "new" connection).
If that were all ssh could do, it would be pretty cool and pretty useful. But there's more. It can also copy files, or run remote commands. If you exit back to your server (just as you would from telnet- "exit" or CTRL-D), you can copy a file:
scp /etc/passwd [email protected]:~/mypassword
Once again you will be asked for "boopy"'s password, and if you can type it correctly once more, your file will be copied. You can copy with wildcards (but keep in mind that wildcards are expanded by your shell, not by anything at the other end). When using wildcards, you'll only be asked for your password once. You can run commands, too: how about a quick "ls -l"?
ssh [email protected] ls -l
Your ability to type the password rewards you with the expected results or rejects you as an incompetent typist (or just someone with a bad memory). Have you decided that this ssh is a neat idea but just too much work? Hang in there, we have a solution.
Obviously, part of the problem is all that typing of "boopy" and "aplawrence.com" (yeah, retyping the password is annoying too- we'll get to that in a minute). So, ssh. lets you create a configuration file. Put this in your ~/.ssh/config:
Host pcunix Hostname aplawrence.com User boopy
With that, just "ssh pcunix" or "scp pcunix:~myfile myfile" will work. There's much more that can be done in a config file; the system wide file (probably /usr/local/ssh/etc/ssh_config) gives examples. But we've still got that repetitive password entry.
Agents and KeysThere are other ways to authenticate yourself to the other server when using ssh. Actually, there are a number of different ways, and some of them are obscure, complex, or only necessary in unusual cases. The methods supported also vary by ssh version, so I'm going to pass right by the exotic stuff: if you need Kerberos or Security Dynamics or S/Key, you'll be doing whatever it is you need to do to make it work, but the majority of users will use either login passwords (as described above) or passphrase authentication- which I'm about to describe. Technically, there is also Trusted Hosts authentication, which works very much like traditional rlogin, but I'm going to ignore that here.
We already know that ssh uses public key cryptography to identify hosts. It can also use it to identify you. To do, this, you need to create an "identity". That's easy:
You'll be asked for a passphrase. This is used to protect the private part of your identity. The public part will be created in ~/.ssh/identity.pub and needs to be copied to the server you want to access:
scp ~/.ssh/identity.pub boopy:~/.ssh/authorized_keys
For my Linux system, I had to do
ssh-keygen -t dsa scp ~/.ssh/id_dsa.pub boopy:~/.ssh/authorized_keys2
Rob Fantini pointed out:
But the procedure will cause problems if a more than one computer is used to connect to the server by the user.
That will overwite the file. Instead what I do is scp the .pub keys to $HOME on the target server. Then from $HOME/.ssh I run the following script:
#!/bin/bash # add $HOME/*pub to .ssh/authorized_keys* # b4 running this 'scp *pub' would be done from $HOME.ssh from # the remote host. #cd $HOME/.ssh of the user . not in this script # as root might do this for users being setup. # Next make keys when user account is created, # scp them to other servers. # then run this script on other servers.. # may need to use rdist to transfer the file & run a script # on the remote server. # #set -x if [ -e ../identity.pub ] then cat ../identity.pub >> authorized_keys rm ../identity.pub fi if [ -e ../id_dsa.pub ] then cat ../id_dsa.pub >> authorized_keys2 rm ../id_dsa.pub fi chmod 700 ../.ssh chmod 600 *
Once you have created an ssh identity (which is just a pair of public/private keys), an attempt to access a server that knows your public key (this is YOUR public key now, nothing to do with the host keys) no longer asks you for your password. Instead, it asks you for a passphrase, which is text that you entered when you created your identity keys. To you, this looks very much like using a password- it seems all that you've done is replaced the password with another string of text. However, underneath, things are now working quite differently:
Rather than sending your password, the authentication works just like the server authentication described earlier: a bit of data is encrypted with the public key, and if you can decrypt it with the private key, that proves who you are. The passphrase is only used to decrpt the private key, which in turn is then used to decrypt the public key encrypted challenge, so nothing private gets sent over the network at all. Remember that your password was sent encrypted, but this way, nothing secret is sent at all.
Great, so it's more secure. But you still have to type in the passphrase every single time you copy a file or reconnect. Well, that's what the ssh-agent is for. Try this:
ssh-agent /bin/ksh ssh-add
You don't have to use /bin/ksh- use whatever shell you like. When you type sssh-add, you will be asked for your passphrase, but that's the last time you'll be asked- until you exit out of ssh-agent, of course. Now, when you use ssh or scp, the ssh-agent provides the passphrase for you. No more repetitive typing.
You can automate that more: create a script called "agent" containing
ssh-agent /bin/bash --init-file ~/.ssh_bash_start
and a .ssh_bash_start containing "ssh-add". Now running "agent" prompts for your key and that's all you have to do. You need a verion of Bash that supports --init-file.
It's also possible to create a passwordless ssh connection. You might need to do that for a service that you want to start automatically. You should realize that you are running some risk with that, but ssh does let you specify that only a specific command can be run, and that the connection has to originate from a specific ip address.
There's a lot more to ssh. It can also do port forwarding- for example, see the description of using ftp through ssh in DSL and Cable Modem Security. You can have multiple identities, and identities can use blank passphrases- useful for unattended cron jobs, for example. If you are going to make serious use of ssh, you'll also want to read SSH-The Definitive Guide.