For the time window on your next-steps list, a collections.deque per IP keeps it simple: append each failure's timestamp, pop from the left while the oldest is outside the window, and alert when len() reaches 5. Then your three tests are just 4, 5 and 6 failures inside the window, plus 6 spread across two windows that should not alert.
Small heads-up for later: 203.0.113.0/24 is a documentation range (RFC 5737), so if you add a geolocation or reputation lookup in a future lab, those test IPs will come back empty. Use a few real public IPs in a separate test file for that step.