Roger Needham’s work has warned us of the potential damage of Denial-of-Service attacks. Since, protocol designers try to minimize the storage committed to unauthenticated partners, as well as prevent ‘amplification effects’ that could help DoS adversaries: a single unit of network communication should only lead to at most one unit of network communication. This way an adversary cannot use network services to amplify his or her ability to flood other nodes. The key question that arises is: what is the unit of network communication?
My favorite authentication protocol, that incorporates state-of-the-art DoS prevention features, is JFKr (Just Fast Keying with responder anonymity.) An RFC of it is also available for those keen to implement it. JFKr implements a signed ephemeral Diffie-Hellman exchange, with DoS prevention cookies being used by the responder to thwart storage exhaustion DoS attacks directed against him.
The protocol goes a bit like this (full details in section 2.3 of the RFC):
Message 1, I->R: Ni, g^i
Message 2, R->I: Ni, Nr, g^r, GRPINFOr, HMAC{HKr}(Ni, Nr, g^r)
Message 3, I->R: Ni, Nr, g^i, g^r, HMAC{HKr}(Ni, Nr, g^r),
E{Ke}(IDi, sa, SIG{i}(Ni, Nr, g^i, g^r, GRPINFO)),
HMAC{Ka}(‘I’, E{Ke}(IDi, sa, SIG{i}(Ni, Nr, g^i, g^r, GRPINFO)))Message 4, R->I: E{Ke}(IDr, sa’, SIG{r}(Ni, Nr, g^i, g^r)),
HMAC{Ka}(‘R’, E{Ke}(IDr, sa’, SIG{r}(Ni, Nr, g^i, g^r)))
Note that after message 2. is sent, ‘R’ (the responder) does not need to store anything, since all the data necessary to perform authentication will be sent back by ‘I’ in Message 3. One is also inclined to think that there is no amplification effect that ‘I’ could benefit from for DoS, since the single message 1. generates a single reply i.e. message 2. Is this the case?
We are implementing (at K.U.Leuven) a traffic analysis prevention system, where all data is transported in UDP packets of fixed length 140 bytes. As it happens message 1. is slightly shorter than message 2., since it only carries a single nonce and no cookie. (The JFKi version of the protocol has a message 2. that is even longer.) This means that we have to split the reply in message 2. over two packets carrying 280 bytes in total.
A vanilla implementation of JFKr would allow for the following DoS attack. The adversary sends many message 1. UDP packets pretending to be initiating an authentication session with an unsuspecting server ‘R’ using JFKr. Furthermore the adversary forges the source IP of the UDP packets to make them appear as if they are sent by the victim’s IP address. This costs the adversary a UDP packet of 140 bytes. The server ‘R’ follows the protocol and replies with two UDP packets of 140 bytes each, sent to the victim’s IP address. The adversary can of course perform this attack with many sessions or servers in parallel, and end up with double the number of packets and data being sent to the victim.
What went wrong here? The assumption that one message (1.) is replied with one message (2.) is not sufficient (in our case, but also in general) to guarantee the adversary cannot amplify a DoS attack. One has to count the actual bits and bytes on the wire before making this judgment.
How do we fix this? It is really easy: The responder ‘R’ requires the first message (1.) to be at least as long (in bytes) as the reply message (2.) This can be done by appending a Nonce (J) at the end of the message.
Message 1, I->R: Ni, g^i, J
This forces the attacker to spend to send, byte for byte, as much traffic as will hit the victim’s computer.
An Internet Draft is not an RFC: they only last for six months, they are likely to contain errors and unfinished work, and there’s no quality control – any idiot can get their wacko idea published as an I-D.
But is there any particular magic to the 1:1 relationship here, other than as a rule of thumb?
@George,
The history of the internet is littered with such problems (Secure HTTP is the wrong way around for instance) based on the assumptions of the time.
If you realy wanted to reduce DoS you need to minimise the load on the Responder as much as possible. To do this you will need to split the communication up into seperate stages “Open connection”, “data transfer”, “Close connection” etc. So for opening a connection you would make,
1, All Responder State precomputable.
2, All messages conectionless.
3, The Initiator path more expensive than for the Responder.
4, All “expensive” state storage by the Initiator.
5, All non data Responder acks/replies limited in cost both in packet size and computational load.
Oh and secure would be nice providing it does not conflict with the above requirments 😉
Having made the “Open Connection” expensive for the Initiator, and having (probably) forced them into giving you a valid IP address you would move onto the next stage. This is a different problem which can be addressed in another way but similar in principle. When you get to the “Data Transfer” stage you obviously want this to be secure and balanced to reduce network overhead
From what you have shown above JFKr does not meet all of the above requirments in the setup as message 2 (from the Responder) shows. It is neither computationaly cheep or pre-computable and happens at a time when you have not achived a level of confidence about the Initiator.