So as we saw in the introductory tutorial, SSH uses the Client-Server model. Now, technically a server is just the machine you are connecting to, and there is no reason in principle that it could not be another desktop, a laptop, or even a telephone if it has the appropriate software. and in the previous tutorial we showed how you can easily install and set up an ssh server on your home network using another computer or a Raspberry Pi so that you can experiment with these commands. The model really reduces to you as the client, and the other machine as the server. As with all Internet connections there are standards and protocols involved. The original Telnet communicated over TCP through port 23. Because SSH was conceived as a replacement, it used the same TCP protocols, and was assigned the adjacent port number of 22. This is the standard, but it is not set in stone. Indeed, one of the ways a you can add to security is to use a non-standard port. This requires that the server be configured for a different port. Servers monitor ports using daemons, so the server administrator would need to configure the daemon to listen to the alternate port, such as 16180, for SSH traffic, and then communicate this to the potential clients. This is a good thing to know if you are using SSH to log in to a remote server that you administer (for example, you may have a server co-located in a data center, or a Virtual Private Server that you control and administer). If a vulnerability in the SSH protocol were to be discovered, you can bet that the bad guys would immediately start to hammer on port 22 of every IP address on the Internet looking to take advantage, but if your server does this on a non-standard port it gives you that much more protection. Still, if you are connecting to a server that you do not control, you probably will connect to port 22, and chances are your client software is already configured to do that by default.
How It Works
To begin with, all SSH connections are initiated by the client. You as the client are going to the server and asking “Please, sir, may I have a shell connection?” And you will generally do this on port 22. The server will have a daemon listening to that port, and it should respond to your request. If you have the same account name on both your client and the server, you can just log in to the server. If they are different you should put in your account name. These examples assume you are using a terminal
Either of these would work if your account name is the same as on your local client. If they are different, you could speed things along by adding the account name:
Then if you want to connect to a different port, the ssh command has a -p switch that you can use, which would look like this if for example the server were configured to listen to port 1234:
ssh -p 1234 192.168.1.24
The server should then send back to your client the protocol version, which should be SSH 2.0. If your client also supports SSH 2.0. the connection proceeds. Other wise, the connection is dropped. All modern clients support SSH2.0, however. If you really want to dive in to the details, you can start with RFC 4253, written by the previously mentioned Tatu Ylönen. If you want to see everything going on, use the -v switch with the ssh command to turn on verbose mode. In fact, you should probably use -v switch at least a few times just to see what is going on. This will show you all of the communication going on between your client and the server. I noticed that recent version of Kubuntu leave out a lot of the messages back and forth that you want to see.
Then the Binary Packet Protocol kicks in. This specifies each of the fields in the packet sent using SSH. If you need the full details on this, consult RFC 4253, but this is probably something you can skip if you are not going to be writing your own client.
Next is the Server’s turn to identify itself, which it does by transmitting its public key. If this is your first time attempting to log in to this server, you will get something like this”
The authenticity of host 'myserver.host.com' can't be established.
RSA key fingerprint is d8:09:f4:42:....
Are you sure you want to continue connecting (yes/no)?
Since this is the first time you have tried to connect, you don’t know for sure if this really is the server you want. This is where a man-in-the-middle attack could take place. If you were sitting in a coffee shop using the free wifi, for instance, someone could be at the next table intercepting the traffic and could respond with their own public key, thus hijacking your session. This should only happen the first time you connect with this particular machine, because the public key should be stored for future reference in what is called the “known_hosts” file. On a Linux machine, this is usually found at ~/.ssh/known_hosts. On Windows 7 generally you can find it at %USERPROFILE%\ssh or %USERPROFILE%\.ssh. But if you get a new laptop you have to go through this initial connection again with each of the sites you connect to. Here is an example of what you might see in a known_hosts file:
|1|r+ApNZ081u8F3ehFRVp6ZNz8xBY=|N5yEjhrj8HuMv9cO5FWbo5SpyCg= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNiqUfhcBBhi7vutXABE9QP6r5FhPfe8Kt17+TKh/5vmcW+Tih5+XR35YjshUZFr+twl+lhfYDQWJZKc8DD2ojY=
|1|RHY96iugvQrTL7rXnZkQnRSqyig=|Jn/PouMCTCeXruls/TbXkg/Ty2E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOkr0/inWArXjcgCWLVRL+RL3QOtw1ZKwE8YLFcTF/wcLsmaQvYVhPAKe1Pq6wBD2o+yh6y03Xqnr42CD2bssT0=
This is entries for 2 sites and what it records is the key used to create an encrypted, secure connection.
But there is definitely a weakness here because you are accepting a key on the first login, so how can the server admins prevent this? Your login attempt got the fingerprint returned to you, so that is the key to this, if you will pardon the pun. You probably don’t want to post it publicly on an unsecured web site, for instance, since the bad guys might figure out a way to spoof it. And email carries the same risk. In a corporate environment you might post it on an encrypted web site behind the firewall, and require the employee to use their credentials to access it, or even have the IT department configure this for all users. The point is that the security of the connection depends on the key, and if a man-in-the-middle can get you accept a bad key, they own you after that.
The next step depends on whether you are using SSH v.1 or SSH v.2. Since the vulnerability in SSH v.1 was found long ago in Internet time, you probably should question what is happening if you see it used today. SSH v.2 was adopted in 2006, which makes it comparatively old and stable. As Micheal W. Lucas put it in his book SSH Mastery: “SSH-1 permits man-in-the-middle attacks and session hijacking, as discussed in Chapter 1. If someone insists on using SSH-1, practice saying “I told you so.” His book is excellent, and the e-book is only $10, and worth every cent. In particular, if you need to set up an SSH server, which I won’t really cover much of, this book is mandatory reading. Among the changes introduced by SSH v.2 are:
- improved encryption standards, including 3DES and AES
- Public key certification for clients (we will discuss later on)
- The use of sound cryptographic Message Authentication Code (MAC) algorithms for integrity checking
- SSH v.1 was monolithic, meaning that all of the protocols needed for encryption, authentications, etc. were part of a single large protocol built into SSH v.1 in SSH v.2 each protocol is split out into its own and defined in a separate RFC such as
- Transport Layer Protocol
- Connection Protocol
- Authentication Protocol
I don’t want to take the time to dig into how SSH v.1 works, and there are a few differences, so I will focus on SSH v.2 only here.
Once you have accepted the Public Key of the server, it is up to you as the client to respond. You do this by first generating a symmetric key (called the session key) which will be used to encrypt all traffic. Remember from our previous tutorials that Asymmetric key pairs carry a very large computational overhead, so they are generally used only to set up a connection and exchange the symmetric key. The client creates this key, then using Diffie-Hellman-SHA1 key exchange sends it back to the server.
NOTE: There is a provision in the protocol for a Certificate Authority to attest to the validity of the public keys used. This would help immensely in preventing the man-in-the-middle attack you are vulnerable to at your first connection since the CA would give you confidence in the validity of the server’s public key. But not all servers use this at present, in part because Certificates are expensive.
We are not done yet. You should only have access to the server in accord with the rights you were given when your account was created. This means it is time to authenticate. And that is the topic for the next tutorial.
Listen to the audio version of this post on Hacker Public Radio!