After reading the selected answer of "Diffie-Hellman Key Exchange" in plain English 5 times I can't, for the life of me, understand how it protects me from a MitM attack.

Given the following excerpt (from tylerl's answer):


  
  I come up with two prime numbers g and p and tell you what they are.
  You then pick a secret number (a), but you don't tell anyone. Instead you compute ga mod p and send that result back to me. (We'll call that A since it came from a).
  I do the same thing, but we'll call my secret number b and the computed number B. So I compute gb mod p and send you the result (called "B")
  Now, you take the number I sent you and do the exact same operation with it. So that's Ba mod p. 
  I do the same operation with the result you sent me, so: Ab mod p.
  


Here are the same 5 steps with Alpha controlling the network:


You attempt to send me g and p, but Alpha intercepts and learns g and p
You come up with a and attempt to send me the result of ga mod p (A), but Alpha intercepts and learns A
Alpha comes up with b and sends you the result of gb mod p (B)
You run Ba mod p
Alpha runs Ab mod p


During this whole process Alpha pretends to be you and creates a shared secret with me using the same method.

Now, both you and Alpha, and Alpha and me  each have pairs of shared secrets.

You now think it's safe to talk to me in secret, because when you send me messages encrypted with your secret Alpha decrypts them using the secret created by you and Alpha, encrypts them using the secret created by Alpha and me, then sends them to me. When I reply to you, Alpha does the same thing in reverse.

Am I missing something here?

Diffie-Hellman is a key exchange protocol but does nothing about authentication.

There is a high-level, conceptual way to see that. In the world of computer networks and cryptography, all you can see, really, are zeros and ones sent over some wires. Entities can be distinguished from each other only by the zeros and ones that they can or cannot send. Thus, user "Bob" is really defined only by his ability to compute things that non-Bobs cannot compute. Since everybody can buy the same computers, Bob can be Bob only by his knowledge of some value that only Bob knows.

In the raw Diffie-Hellman exchange that you present, you talk to some entity that is supposed to generate a random secret value on-the-fly, and use that. Everybody can do such random generation. At no place in the protocol is there any operation that only a specific Bob can do. Thus, the protocol cannot achieve any kind of authentication -- you don't know who you are talking to. Without authentication, impersonation is feasible, and that includes simultaneous double impersonation, better known as Man-in-the-Middle. At best, raw Diffie-Hellman provides a weaker feature: though you do not know who you are talking to, you still know that you are talking to the same entity throughout the session.



A single cryptographic algorithm won't get you far; any significant communication protocol will assemble several algorithms so that some definite security characteristics are achieved. A prime example is SSL/TLS; another is SSH. In SSH, a Diffie-Hellman key exchange is used, but the server's public part (its gb mod p) is signed by the server. The client knows that it talks to the right server because the client remembers (from a previous initialization step) the server's public key (usually of type RSA or DSA); in the model explained above, the rightful servers is defined and distinguished from imitators by its knowledge of the signature private key corresponding to the public key remembered by the client. That signature provides the authentication; the Diffie-Hellman then produces a shared secret that will be used to encrypt and protect all the data exchanges for that connection (using some symmetric encryption and MAC algorithms).

Thus, while Diffie-Hellman does not do everything you need by itself, it still provides a useful feature, namely a key exchange, that you would not obtain from digital signatures, and that provides the temporary shared secret needed to encrypt the actually exchanged data.
