The first time I dealt with a serious flood was in 1999 on a small Italian IRC network. Someone joined #roma and started pasting the entire text of Dante's Inferno, one line every 100 milliseconds. The server slowed to a crawl. Users started timing out. My co-admin panicked and restarted the daemon, which made everything worse because 200 users reconnected simultaneously and flooded the server with registration traffic. We learned two lessons that night: floods are not just about volume, they're about timing. And the worst thing you can do during a flood is restart the server.
Anatomy of an IRC Flood
An IRC flood is any attempt to send more data or commands than the server or other clients can process in a reasonable time. Floods come in several forms, each targeting different bottlenecks:
- Message flood — Rapid PRIVMSG or NOTICE commands to a channel or user. Saturates the channel with text, making conversation impossible.
- CTCP flood — Rapid CTCP VERSION, PING, or other requests. Each CTCP triggers a response from the target client, creating amplification.
- Join/part flood — Rapidly joining and leaving a channel. Each join/part generates a notification to every user in the channel, multiplying the load.
- Nick flood — Rapidly changing nicknames. Each change is broadcast to every channel the user is in.
- Connection flood — Opening many TCP connections simultaneously. Exhausts the server's connection slots and file descriptors.
- DCC flood — Sending many DCC requests. Each request generates a CTCP message that the target must parse.
The underlying problem is amplification. When a user sends PRIVMSG #channel :text to a channel with 500 users, the server must deliver that message to 499 other connections. One inbound message becomes 499 outbound messages. A flood of 10 messages per second becomes 4,990 outbound messages per second. At scale, this saturates the server's outbound bandwidth and CPU long before the inbound traffic alone would be a problem.
# The amplification math
# Channel with N users, flood rate of R messages/second
#
# Inbound: R messages/sec × ~512 bytes = R × 512 bytes/sec
# Outbound: R × (N-1) messages/sec × ~512 bytes
#
# Example: 10 msg/s into a channel of 500 users
# Inbound: 10 × 512 = 5,120 bytes/sec (5 KB/s — trivial)
# Outbound: 10 × 499 × 512 = 2,554,880 bytes/sec (2.4 MB/s — not trivial)
#
# With 50 msg/s: 12.2 MB/s outbound from one flooder.
# With 5 flooders at 50 msg/s: 61 MB/s outbound.
The Penalty System: ircu's Approach
Undernet's ircu daemon introduced one of the most elegant anti-flood mechanisms: the penalty system. Every command a client sends costs a certain number of penalty points. Points are deducted from a bucket that refills at a fixed rate. When the bucket is empty, the server stops processing commands from that client until enough points accumulate.
The penalty costs are calibrated to the server load each command generates:
# ircu penalty costs (approximate, varies by version)
# Command Penalty (seconds of delay)
# PRIVMSG/NOTICE 2 + (message_length / 120)
# JOIN 2
# PART 4
# KICK 2
# MODE 2 per mode change
# NICK 3
# WHO varies (expensive for large channels)
# WHOIS 2
# LIST heavily penalized or rate-limited separately
# TOPIC 2
# INVITE 2
# AWAY 3
#
# Bucket refills at 1 point per second
# Typical bucket size: 10 seconds
#
# A user sending 5 PRIVMSG in rapid succession:
# Total penalty: 5 × ~2.5 = 12.5 seconds
# After the 4th message, the bucket is empty.
# The 5th message is queued until enough penalty drains.
This system is transparent to normal users. Typing at human speed — a message every few seconds — never empties the bucket. But automated flooding hits the penalty ceiling almost immediately. A bot trying to send 10 messages per second will find that after 3-4 messages, its commands are silently delayed, then eventually it gets disconnected for "excess flood" when the queue exceeds a threshold.
The penalty system's elegance is that it's self-calibrating. Commands that generate more server-side work (like WHO on a large channel) cost more. Commands that are cheap (like PONG) cost almost nothing. The server's anti-flood mechanism is proportional to the actual load each command imposes.
UnrealIRCd's Anti-Flood Modules
UnrealIRCd takes a layered approach with multiple anti-flood mechanisms operating simultaneously. The configuration is granular but also complex — there are many knobs to turn.
# unrealircd.conf — Anti-flood configuration block
set {
anti-flood {
# Connection flood: limit new connections per IP
connect-flood 3:60; /* 3 connections per 60 seconds per IP */
# Unknown flood: data from unregistered connections
unknown-flood-amount 4k;
unknown-flood-bantime 5m;
# Target flood: limit the number of different targets
# a user can message in a time window
max-concurrent-conversations {
users 10:60; /* max 10 different users per 60 seconds */
new-user-every 15; /* at least 15 seconds between new targets */
};
};
# Per-channel flood settings
# Users can also set these via channel mode +f
default-floodcount 10:5; /* 10 lines per 5 seconds */
};
# Channel mode +f — per-channel flood protection
# Syntax: +f [lines:seconds]
# Example: /MODE #channel +f 5:10
# Kick any user sending more than 5 lines in 10 seconds
#
# Extended syntax: +f [lines:seconds]{action}
# Actions: m (mute), d (auto-deaf), b (ban), k (kick)
# Example: /MODE #channel +f [5:10]{kb}
# Kick and ban users exceeding 5 lines in 10 seconds
UnrealIRCd's max-concurrent-conversations setting is particularly effective against spambots. A bot trying to send the same message to 50 different users will hit the target limit after 10 and get throttled or killed. Legitimate users rarely message more than a few different people per minute.
The channel mode +f is powerful because it puts flood control in the hands of channel operators. Different channels have different needs: a busy discussion channel might tolerate 10 lines per 5 seconds, while a support channel might set 3 lines per 10 seconds. The server provides the mechanism; the channel ops set the policy.
# UnrealIRCd throttle block — connection-level protection
set {
throttle {
connections 3; /* max 3 connections */
period 60; /* in 60 seconds */
};
};
# This prevents a single IP from opening many connections rapidly.
# Combined with the anti-flood block, it handles both connection-level
# and message-level flooding.
# Exception for trusted hosts (bouncers, bots)
except throttle {
mask { ip 198.51.100.0/24; };
};
InspIRCd's Modular Flood Protection
InspIRCd's modular architecture means flood protection is split across several loadable modules. You enable exactly what you need.
# inspircd.conf — Loading flood protection modules
# Ban IPs with too many failed connections
# Throttle rapid connections globally
# Channel message flood detection (+f mode)
# Extended ban to mute users (+b m:nick!user@host)
# Detect repeated messages in channels
# Block ALL-CAPS messages (configurable threshold)
# Block channel CTCPs (+C mode)
# ConnectBan configuration
# ConnFlood configuration — global connection rate limit
# MessageFlood — channel mode +f
# Usage: /MODE #channel +f 5:10
# Kicks user sending more than 5 messages in 10 seconds
# Repeat detection — channel mode +E
# Usage: /MODE #channel +E 3:10
# Kicks user repeating the same message 3 times in 10 seconds
# AntiCaps — channel mode +B
# Usage: /MODE #channel +B 70:5
# Block messages with >70% uppercase and >5 characters
InspIRCd's repeat module is something I wish every IRCd had had in 1999. It detects not just raw volume but identical content. A spammer sending the same URL 50 times triggers +E mode instantly, even if the rate is below the +f threshold. The anticaps module is a small quality-of-life feature that prevents the ALL CAPS SHOUTING that plagues many channels.
connflood module triggers globally — when the threshold is hit, ALL new connections are rejected, not just the flooding source. Set the bootwait parameter high enough to avoid triggering on server restart when all users reconnect simultaneously. I've seen networks lock themselves out for 10 minutes because the connflood threshold was set too aggressively.Client-Side Protection: What Bots and Scripts Do
Server-side flood protection handles the macro problem. Client-side protection handles the micro problem: protecting individual users and channels from floods that stay below server thresholds.
Eggdrop and other channel bots implement their own flood detection. A typical Eggdrop flood configuration:
# eggdrop.conf — Flood protection settings
set flood-msg 5:30 ;# 5 messages in 30 seconds = flood
set flood-ctcp 3:60 ;# 3 CTCPs in 60 seconds = flood
set flood-join 3:10 ;# 3 joins in 10 seconds = flood (join-part cycling)
set flood-kick 3:10 ;# 3 kicks in 10 seconds = bot flood war prevention
set flood-deop 3:10 ;# 3 deops in 10 seconds = takeover attempt
set flood-nick 5:30 ;# 5 nick changes in 30 seconds = nick flood
# Channel-specific settings
channel set #mychannel flood-chan 5:30
channel set #mychannel flood-ctcp 3:60
# What the bot does when it detects a flood:
# - flood-msg: kicks the flooder, optionally bans
# - flood-join: sets channel +i temporarily
# - flood-ctcp: sets channel +C if supported
# - flood-deop: reops legitimate ops, bans the attacker
mIRC scripts provide client-side flood protection for individual users. The classic approach is to ignore CTCP requests from unknown sources and auto-ignore users who trigger too many notifications:
; mIRC flood protection script
; Auto-ignore users who flood you with CTCP
ctcp *:*:?:{
if ($ctcp != PING && $ctcp != VERSION && $ctcp != TIME) { halt }
inc -u60 %ctcp. $+ $address 1
if ($var(%ctcp. $+ $address,1).value >= 3) {
ignore -pu30 $address 7
echo -a Ignoring $nick ( $+ $address $+ ) for CTCP flood (30 seconds).
halt
}
}
; Ignore join/part spam (toggle channel mode in display)
on *:JOIN:#:{
inc -u10 %joinflood. $+ $chan 1
if ($var(%joinflood. $+ $chan,1).value >= 10) {
echo -a Join flood detected in $chan — suppressing join/part display.
; Could auto-set +R if the bot has ops
}
}
The combination of server-side rate limiting, channel mode protection, and client/bot-level detection creates a layered defense. No single layer catches everything. Together, they handle most practical flooding scenarios without being so aggressive that normal users get caught in false positives.
Tuning for Real Networks
The default anti-flood settings in most IRC daemons are conservative. They're designed not to annoy legitimate users, which means they're also lenient enough for persistent attackers to cause disruption.
Tuning requires understanding your network's traffic patterns. A small private network with 50 users needs different settings than a public network with 5,000. Here are the principles I follow:
Connection throttling should be your first line of defense. Limit connections per IP to 3 per minute for regular users. Exempt known bouncers, web clients, and trusted CIDR blocks. This alone stops 80% of flood attempts because most attackers use a small number of source IPs.
Message rate limiting at the server level should be lenient enough for active conversations — 10 lines per 5 seconds is reasonable. Channel-level settings (via +f mode) should be tighter for channels that want calm discussion.
DNS blacklists (DNSBLs) are effective for connection-time filtering. Both UnrealIRCd and InspIRCd support querying DNSBLs during the connection handshake:
# UnrealIRCd DNSBL configuration
blacklist dronebl {
dns {
name dnsbl.dronebl.org;
type record;
reply { 2; 3; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; };
};
action zline;
ban-time 1h;
reason "Your IP is listed in DroneBL. Visit https://dronebl.org/lookup?ip=$ip";
};
blacklist efnetrbl {
dns {
name rbl.efnetrbl.org;
type record;
reply { 1; 4; 5; };
};
action gzline;
ban-time 1h;
reason "Your IP is listed in EFnet RBL.";
};
Registration requirements — requiring SASL authentication or email verification before allowing channel access — are the most effective anti-flood measure for persistent attackers. Libera.Chat's requirement of SASL for Tor users is an example of this approach. The barrier to entry is low for legitimate users and high for automated flooding tools.
Monitor your server logs during flood events. The pattern of the attack tells you which setting needs adjustment. If you see thousands of connections from a few IPs, tighten connection throttling. If you see a few connections generating massive channel traffic, tighten message rate limits. If you see distributed low-rate spam across many channels, you need DNSBL filtering and possibly require authentication for channel access.
FAQ
What does "Excess Flood" mean when I get disconnected?
It means you sent data faster than the server's anti-flood system allows. The server's receive buffer for your connection filled up and it disconnected you. Common causes: pasting multiple lines at once, a script sending rapid automated messages, or a bot without output rate limiting. Add a send queue with delays between messages to prevent this.
Can channel operators stop floods without server-level settings?
Partially. Channel modes like +f (message flood), +R (registered users only), +m (moderated — only voiced users can speak), and +i (invite only) give operators tools to restrict channel access during a flood. A bot like Eggdrop adds automated detection and response. But server-level protection is always the primary defense — channel ops can only manage what the server lets through.
How do I test my flood protection settings without attacking my own network?
Use a test server with no real users. Connect multiple clients (a simple Python script that opens N connections works) and generate synthetic traffic at controlled rates. Gradually increase the rate until the anti-flood system triggers. Measure the threshold, compare it to your target, and adjust. Never test flood protection on a production server — even controlled floods disrupt service.
Do IRCv3 features help with flood prevention?
Indirectly. The labeled-response capability helps servers batch responses efficiently. The account-tag capability lets servers identify authenticated users without extra lookups, enabling faster trust decisions. The message-tags specification allows servers to add metadata (like flood scores) to messages for client-side filtering. But the core anti-flood work remains at the server level — IRCv3 extensions provide better tooling, not fundamentally different flood protection.