An experimental DoS attack on TCP (brief draft only)
G. D. McCullagh, D.W. Malone, D.J.Leith
TCP senders commonly trust that the receiver will acknowledge data honestly, ie. that the receiver will only send acknowledgements for a continuous sequence of packets which it has received. If a packet arrives out of order (before some packet earlier in the sequence), the receiver is expected to send a duplicate acknowledgement, with the sequence number of the last sequential packet received. If three duplicate acknowledgements are sent back, the sender concludes that the next unacknowledged packet has been lost, that it must resend it and that it should reduce the send window (assuming it is using standard loss-based congestion control).
Acknowledgements are cumulative. If a sender acknowledges byte n in the sequence, it is implied that all bytes earlier in the sequence have been received. A receiver often acknowledges only every second packet (called "delayed acking") or even fewer packets. This works fine so long as it acknowledges often enough to keep the number of unacknowledged packets below the sender's congestion window.
A simple attack on this scheme is to omit duplicate ACKs (see end of §2.4 in , "Lazy Opt-ACK" in ) and continue to acknowledge all packets which arrive as though they were received in order, with no holes in the sequence. This could cause the attacked machine to flood its own uplink as it will indefinitely increase the send window and never reduce it.
We modify a receiver's TCP stack so that it never sends duplicate acknowledgements -- instead it just acknowledges the new out of order packet. We download large files over http from a standard debian linux host using the modified host as client with tcpdump running at both ends to capture the traffic. Because duplicate ACKs never get sent, and the cumulative acknowledgements continue to move the sequence number forward, the sender keeps increasing his send window oblivious of the flooded bottleneck.
Sender and receiver kernels are linux v2.6.18. Using a FreeBSD dummynet router machine in between, we emulate common network topologies.
DSL Link -- 512kbps downlink, 128kbps uplink, 20ms RTT
In this figure you can see how the number of packets sent increases. The sender is in fact in slow start mode. However, the increase function is linear because the number of acknowledgements it receives is constricted by the number of packets the receiver gets. The attacker could divide the ACKs to achieve an exponential increase function. The difference between the number of packets sent and the number of ACKs received is the number dropped at the router.
In under 5 minutes, the sender is sending 1500 packets per second, at 17.5Mbps over a line which is 512Kbps.
Note: I'm unclear at the minute why the packets sent becomes constant around 1500 packets but I suspect this is some measurement error (linux libpcap related?). The FreeBSD router continues to show an increasing number of packets being dropped per second so they are presumably being sent.
The number of data packets received and number of ACKs sent at the attacking host.