Before we can describe the solution, we must first adequately describe the problem Anti-Replay is trying to solve.
Imagine your local bank branch office. Imagine someone going to that branch location, and depositing $100 in cash into their account. At some point following the transaction, that branch location will send some packets to the bank headquarters which essentially state to increase their account balance by $100.
Those packets will cross the branch office’s Internet Service Provider (ISP) network on their route to the Bank Headquarters. If a malicious user (or even the depositor themselves) happens to work at the ISP, it would not be overly difficult to capture the packets going from the Branch to the Headquarters that day, and by time reference, narrow down the particular packet(s) that make up the deposit’s transaction.
If the packets were protected by Confidentiality, the malicious user would be prevented from reading into the data packet itself. If the packets were protected by an Integrity scheme, the malicious user would be unable to increase the deposit amount to $1000 or $10,000. But, despite those two protections, there would be nothing that would prevent the malicious user from simply duplicating those packets and putting them back on the wire in order to continually re-deposit $100 over and over again.
…nothing if not for Anti-Replay protection, that is.
Anti-Replay protection exists specifically to thwart the scenario described above. Anti-Replay injects what is known as a Sequence Number into the data packet. This number typically starts at 1, and increases with every packet sent, uniquely identifying one packet from the one prior.
On the receiving end, the last Sequence Number received is tracked. If a packet with a repeated sequence number is ever received, it can be discarded and presumed to be a Replayed packet. Take this example:
Notice, the packet with Sequence Number #3 is a replayed packet. The receiver can easily detect this because they have already received a packet with Sequence Number #3, and was expecting #5 next.
The sequence number, along with the data, will be protected by some sort of Message Integrity scheme to prevent a malicious user from tampering with the numbers in order to send a replayed packet. The sequence number should be included in the Hashing algorithm, along with the Message and the Secret Key. In this way, any illicit modification of any of these fields will be detected.
Sequence Number and Finite Fields
It is important to keep in mind that the Sequence Number is a finite field. Which is to say, it does not go on forever.
It has a pre-defined ranged based upon the number of bits allocated in the Data Packet. For example, if the data packet only allows a 16 bit field for the Sequence Number, you would have a total range of 1 – 65536.
It is important to consider this maximum so that it does not impose a limit on the number of packets that can be sent. Or worse, create a looped sequence number vulnerability when the sequence number rolls back to zero.
For example, using the banking transaction above, let us assume the packets only used a 16 bit Sequence Number field, and the captured packets included Sequence Numbers 10,000-10,099. The malicious user could simply wait for the Sequence number to loop past 65,536 and restart at 0, then count out 9,999 packets, and inject the replayed 10,000-10,099. Since the replayed packets would have arrived at the right time, they would have been accepted by the receiver.
This is addressed by forcing a rotation of the Secret Keys used in the Encryption and Integrity algorithms when the Sequence Number resets back to zero. This aids to ensure the continued, indefinite avoidance of replayed packets.
If an attacker attempts to replay a packet before the Sequence Number resets, then the repeated Sequence Number itself would identify the replayed packet. If an attacker attempts to replay a packet after the Sequence Number resets, then the old packet secured with the old keys will identify the packet was replayed.