DNSSec is normal DNS, but with signatures. It absolutely prevents DNS Spoofing; that's what it's for, and that's what it does.
Registrars can still theoretically abuse their position because they're responsible for communicating your intentions to the root servers. This includes information about your DNSSec keys. This relationship will never change; if you can't trust your registrar, then get a new registrar.
DNSSec doesn't prevent MITM attacks. It absolutely prevents DNS spoofing. But there are other ways of inserting yourself into a traffic flow than just DNS spoofing.
How it works
In essence, you tell your registrar your signing key's fingerprint by creating a
DS record, and that information will be available from your TLD signed by an upstream key which chains in a like manner all the way to a single globally trusted key.
With this set up, your key is now considered to be the trusted authority for your domain, and is allowed to sign your DNS records. So now for each record in your zone, you create a corresponding
RRSIG record which contains the associated digital signature.
Now, when someone looks up a domain in your zone, you can send not only the response, you can also send the corresponding
RRSIG record as well which shows that the response was signed by you. To verify the signature, the client fetches your DNSKEY record which contains your full public key, and then just follows normal cryptographic signature verification techniques.
DNSKEY record also has its own corresponding
RRSIG record so that you can verify that it hasn't been tampered with. But more importantly, there is a
DS record available from your parent zone (remember, you gave it to your registrar in the first paragraph) which contains enough information about your public key to verify that your
DNSKEY record is actually authorized for your zone.
That DS record is, in turn, singed by your parent's DNSKEY, for which there is a corresponding DS record in the root zone. This way, all key signatures can be traced back to a single trusted source.
The complication comes when you need to tell someone that a record doesn't exist. Obviously that response needs to be signed, but generally the DNS server itself doesn't have access to your signing key and can't sign the response on-the-fly; the signatures are all created "offline" ahead of time. This keeps your key from being exposed if your DNS server gets compromised.
So instead, you alphabetize your subdomains and say "for every name between
pop.example.com, no other subdomains exist" and sign that assertion. Then when someone asks for
nachos.example.com you can just give them that response (which has already been signed) and the client knows that because
nachos.example.com falls alphabetically between
pop.example.com, then the "this domain doesn't exist" response is considered to be correctly signed and actually came from you.
The place where this becomes problematic is that by having a set of these negative responses which explicitly state that "no responses exist between
Y, you can easily map out exactly which domains exist for the entire zone. You know that "X" exists, and you know that "Y" exists, and you know there is nothing else between them. Just do a little more poking at random and you'll quickly be able to compile a list of all the records that do exist.
There are two camps in the DNS world with respect to whether or not this is a problem. The first group says:
"So what if people know what zones exist; DNS is public information. It was never meant to be a secret anyway."
To which the second group says:
"This is a security risk. If I have a server named
accounting.example.com, then someone who intrudes on my network can quickly tell which machine has the juicy information on it and therefore which one to attack."
To which the first group then replies:
"Then don't call it that! If your entire security model is based on the concept of keeping public information secret, then you, sir, are an idiot."
To which the second group replies:
"It's not about keeping secrets, it's about not revealing more information than you have to."
And so on, ad nauseam.
DNS (and DNSSec) was designed largely by folks in the first camp; DNS is public, therefore being able to map out which subdomains exist in a domain isn't a significant security concern. And anyway, you can't really do signed negative responses any other way.
On the other hand, the servers tend to be run by people in the second camp. They're concerned about the safety of their own network, and they don't want to be giving away any more information than necessary, since they know that all information will eventually be used against them.
So you have a protocol is cryptographically sound and perfectly functional, but which real-world admins tend to be hesitant to implement.
We'll all get there eventually, I imagine. After all, DNS spoofing is more of a real-world concern than any dangers raised by mapping out subdomains. But change takes convincing. So here we are... still.