EZ LearnEZ Learn
Courses
EZ Board
Dashboard
All articles
python-for-cyber-securitypythonddosdeque

Identifying a DDoS in Progress

A turnstile that only ever counts the last few minutes catches a surge the moment it happens. The same idea, a sliding window instead of a running total, is what survived the largest DDoS attack ever recorded.

Ashish Revar18 October 20267 min read
1 video lesson 6:24 total
Sign in to track your progress

Video lesson

Everything built so far in this unit reads a capture after the fact. This article is different: the same logic, pointed at a live interface instead of a saved file, becomes an early warning system, because it watches the rate of traffic, not the total.

Analogy: The turnstile

Catching an attack while it is still happening, rather than reconstructing it later, means watching the rate of traffic rather than its total. Picture a turnstile that only ever counts the last few minutes: as new packets arrive they are added, and as old ones age past the window they are dropped, so the count always reflects a recent rate, not everything that has ever passed through.

The algorithm

Python concept: Sliding-window flood detection

Input: a stream of packets, a window length, and an alert threshold. Output: an alert whenever one destination is flooded.

  1. For each packet, read its destination address and arrival time.
  2. Add this arrival time to that destination's window.
  3. Remove from the window every time older than the window length.
  4. Count the times remaining in the window: this is the recent packet rate.
  5. If the count exceeds the threshold, raise an alert for that destination.
  6. Continue with the next packet.
sliding window (last 10 seconds)timeolder packets, dropped from the count
Figure 4.5. A sliding window counts only recent packets. When the count inside the window crosses a threshold, an alert fires, catching an attack while it is live.

Building the detector

detect_in_progress.py

# detect_in_progress.py: a sliding-window flood detector
from collections import defaultdict, deque
import dpkt, socket
from open_capture import read_packets

WINDOW_SECONDS = 10
THRESHOLD = 500

packet_times = defaultdict(deque)

def record_and_check(dst_ip, timestamp):
    window = packet_times[dst_ip]
    window.append(timestamp)
    while window and window[0] < timestamp - WINDOW_SECONDS:
        window.popleft()
    if len(window) > THRESHOLD:
        print(f"ALERT: {dst_ip} received {len(window)} packets "
              f"in the last {WINDOW_SECONDS} seconds")

for ts, raw in read_packets("capture.pcap"):
    try:
        ip = dpkt.ethernet.Ethernet(raw).data
        record_and_check(socket.inet_ntoa(ip.dst), ts)
    except AttributeError:
        continue

Run against the same flood capture from two articles ago:

Sample output (first few lines of many)

ALERT: 10.0.0.5 received 501 packets in the last 10 seconds
ALERT: 10.0.0.5 received 502 packets in the last 10 seconds
ALERT: 10.0.0.5 received 503 packets in the last 10 seconds
...
ALERT: 10.0.0.5 received 1805 packets in the last 10 seconds

Python concept: deque as a sliding window

A deque (double-ended queue) can add and remove from either end cheaply. Here it holds only the packet timestamps inside the last ten seconds: new ones are appended on the right, and popleft() trims old ones from the left. The length of the deque is therefore always the recent packet rate, which is what the threshold is compared against.

An alert that never stops is a problem of its own

The output above keeps climbing: 501, then 502, then every single packet after that for as long as the flood lasts, because the condition len(window) > THRESHOLD is true for every one of them. A real deployment of this detector would drown an operator in alerts within seconds.

Caution: A deployed detector needs to rate-limit itself, not just the window

The fix is not to the window logic, which is correct; it is to add a second, separate rule about alerting, such as firing once when the threshold is first crossed and staying quiet until the count drops back below it, or sending at most one alert per destination per minute. This is a common, easy-to-miss step: a detection rule and an alerting policy are two different decisions, and conflating them is how a genuinely useful detector becomes one everyone learns to ignore.

Because the detector watches a ten-second window rather than a running total, each alert reflects the rate right now, which is exactly what a real defence acts on when it decides to route the traffic away.

Real incident: The GitHub attack, 2018: 1.35 terabits in one spike

On 28 February 2018, the software-hosting site GitHub was hit by what was then the largest denial-of-service attack ever recorded, peaking at 1.35 terabits per second. The attackers used a technique called memcached amplification: they sent small forged requests to thousands of misconfigured memcached servers, each of which replied to the victim with a response many times larger, multiplying the attackers' bandwidth. The spike was detected almost immediately by exactly the kind of rate monitoring this article builds, traffic to GitHub crossing a threshold no legitimate load could explain, and mitigation routed the flood away within about ten minutes.

What this teaches: the GitHub attack was survived not because anyone read every packet, which at 1.35 terabits per second is impossible, but because a rate-based detector noticed the window count cross a threshold and acted. The sliding-window detector in this article is a scaled-down version of the real defence, and it teaches the central lesson of DDoS response: watch the rate, not the total, and act on the slope.

Try it yourself: From a file to a live feed

Point this same logic at a live interface instead of a saved file, by swapping dpkt.pcap.Reader for a live capture source, and it becomes an early warning system watching traffic in real time. The record_and_check() function itself would not need to change at all; only where ts and raw come from does.

Check your understanding

Question 1: Using the turnstile analogy, explain why a sliding window detects an attack in progress better than a counter that only ever increases. Relate your answer to how the GitHub attack was mitigated.

A plain counter that only ever grows would eventually cross any threshold on normal traffic too, given enough time, and tells you nothing about whether traffic is high right now versus simply having accumulated over a long period. A sliding window only counts the last few seconds, so it directly reflects the current rate, which is what crossed GitHub's threshold and triggered mitigation within minutes rather than after the fact.

Question 2: Why does detect_in_progress.py keep alerting on almost every packet once the flood starts, and what is the correct fix?

Because the condition len(window) > THRESHOLD stays true for every packet arriving while the flood continues, so each one triggers its own alert. The fix is not to change the detection logic, which is correctly measuring the rate, but to add a separate alerting policy, such as firing once per crossing or rate-limiting alerts per destination, so the detection and the notification are treated as two different decisions.

Question 3: What would need to change to turn detect_in_progress.py from an offline analysis tool into a live early-warning system?

Only the source of ts and raw: instead of dpkt.pcap.Reader reading a saved .pcap file, a live capture source feeding packets as they arrive on an interface. The record_and_check() function, which does the actual sliding-window detection, needs no change at all.

Key takeaway: Key takeaway

A sliding window, built from a deque, turns a stream of packets into a rate that always reflects right now, not the whole history. That rate is what caught the largest DDoS attack ever recorded within minutes, and the same logic, pointed at a live feed instead of a file, is an early warning system.

Assessments

Unit Assessment

Network Traffic Analysis with Python

20 questions30 minPass: 60%

Start exam →

Comprehensive Assessment

Python for Cyber Security: Complete Assessment

100 questions120 minPass: 60%

Start final exam →

Related to this topic

Continue learning

Reference material

Cheatsheet

Python for Cyber Security — Cheatsheet

v1.0

Open resource

MCQ Bank

Python for Cyber Security — MCQ Bank

v1.0

Open resource

Question Bank

Python for Cyber Security — Question Bank

v1.0

Open resource

eBook

Python for Cyber Security — eBook

v1.0

Open resource

Discussion

Loading comments…
More articlesTest your knowledge
EZ MentorAI · Free

Identifying a DDoS in Progress

Hi! I'm EZ Mentor

Your AI tutor for
Identifying a DDoS in Progress

Sign in to ask, it's free.

EZ Mentor is AI-powered · Answers may not be perfect · 10 free questions / day

EZ LearnEZ Learn

Structured learning across Reverse Engineering, Cloud Security, and Research Methodology, plus games and practice tools in EZ Arena. Free, and open to anyone.

EZ Learn

  • Courses
  • EZ Articles
  • EZ Watch
  • EZ Talks
  • EZ Bytes
  • Cyber Hygiene

EZ Library

  • All Resources
  • eBooks & PDFs
  • Question Banks
  • MCQ Banks
  • Cheatsheets

EZ Exams

  • All Exams
  • REMA
  • Cloud Security
  • Research Methodology
  • Python for Cyber Security
  • Cyber Law & IPR
  • Community
  • EZ Board

EZ Arena

  • EZ Games
  • Live Quiz
  • ML Challenges
  • दिशा - Hygiene
  • सजग - Awareness
  • अभ्यास - Practice

Platform

  • About
  • Contact
  • Terms of Use
  • Disclaimer
  • Verify Certificate
  • Events

© 2026 EZ Learn by EpochZero. Educational content for learning purposes.

Platform Lead: Ashish Revar