TCP gives the filter a handshake to lean on. Half-open connections are obvious. Bad sources can be parked and forgotten.
UDP gives the filter nothing. A single packet arrives and the filter has to decide, in microseconds, whether it's a player input or part of a 12-Mpps flood. There's no protocol-level state to lean on.
What actually works
Per-engine signatures. Each game protocol has its own packet shape — header bytes, payload structure, sequence semantics. Generic 'allow valid UDP' is not a profile.
Per-source budgets. Real players don't send 50,000 pps. Attackers do. Budgets that look at packet rate, payload variance and timing — not just source IP — survive longer.
Connection migration awareness. Modern games drop and re-establish sessions. Filters that treat that as suspicious lose actual players.
What doesn't
Captcha challenges. Real-time gameplay doesn't pause for a checkbox.
Generic rate limits. They eat legitimate burst traffic during big team fights.