Protecting a Left 4 Dead 2 server from DDoS attacks
Which ports a Left 4 Dead 2 server really needs, how to rate limit the A2S query on 27015/UDP without locking out your own players, what the lobby system achieves as an access filter, and at what attack size only filtering in the network in front of the server helps.
A Left 4 Dead 2 server rarely goes down at a convenient moment. It goes down in the last chapter of a campaign, in the second round of a versus match, or exactly when a banned player has been turned away for the third time. If you are being shot at right now, you do not need a discussion about networking theory, you need an order of operations. This article first shows how to protect a Left 4 Dead 2 server from DDoS attacks while that is still possible with on-board tools, then where those tools end physically, and finally what has to happen in the network in front of the server.
Everything here refers to a dedicated server (srcds) installed through SteamCMD under app ID 222860, running on Debian 12, Debian 13, Ubuntu 22.04 LTS or Ubuntu 24.04 LTS. The commands are written for root; as a regular user, put sudo in front. One point up front, because it sets the order: do not change anything blindly while an attack is running, and do not restart the server before you have captured the measurements. After the attack they are gone.
Why Left 4 Dead 2 servers are a rewarding DDoS target
The difference to a shooter with 64 slots is the size of the round. A co-op campaign has four survivor slots, a versus match has eight slots for both teams combined. An outage therefore never hits individual players, it always hits the entire session: whoever kills a campaign in the third of five chapters has ended the evening for everyone involved. That is exactly what makes an attack attractive to whoever triggers it, because it costs neither skill nor meaningful money while destroying an hour of play on the other side.
Then there is the architecture. Left 4 Dead 2 runs on the Source engine, and a Source server is publicly discoverable by IP address and port. That is a requirement, not an oversight: a server that answers no query appears in no list and is found by no lobby. So the question is never whether an attacker knows your address, only what happens when he shoots at it. Game traffic runs over UDP, UDP has no handshake you could demand, and source addresses can be forged. What happens technically is explained in What is a DDoS attack?.
A third point is specific to Left 4 Dead 2 and has no counterpart in Counter-Strike, Garry's Mod or Team Fortress 2: most players do not arrive through the server browser, they arrive through the lobby system. A lobby of up to four players is matched onto a dedicated server through Steam matchmaking, and that server receives a reservation for it. This mechanism is at once your most effective access filter and an additional attack surface. Both are covered in detail below.
The ports that actually matter
A Left 4 Dead 2 server occupies exactly one UDP port for everything the game does. The default is 27015, set with -port or +hostport on the command line:
./srcds_run -game left4dead2 -console -nohltv \
-port 27015 \
+ip 203.0.113.10 \
+maxplayers 4 \
+exec server.cfg \
+map c1m1_hotel
| Port and protocol | Purpose | Must be open to the internet |
|---|---|---|
| 27015/UDP | Game traffic and the A2S server query on the same port | Yes, without it there is no game |
| 27015/TCP | RCON, if rcon_password is set |
No, allow it only for your own address |
| 27005/UDP | Client port, originates from the player | No, it needs no rule on the server |
| 27020/UDP | SourceTV, only with -hltv or +tv_enable 1 |
Only if you actually broadcast |
| 27016, 27017 and up | Further instances on the same host | Per instance, never as a range |
| 80/TCP and 443/TCP | Fast download (sv_downloadurl) if it lives on the same host |
Only if the web server runs there |
| 22/TCP | SSH access | No, restrict it to your own address |
The first row of that table is the core of the problem. Game traffic and the server query share 27015/UDP; Left 4 Dead 2 has no separate query port. Anyone who blocks that port outright or rate limits it coarsely throws out their own players in the same move and finishes the attack on the attacker's behalf.
An A2S request is a packet of a few dozen bytes and the answer is a multiple of that. With UDP the source address can be forged, which turns your server from a victim into an amplifier: an attacker queries foreign game servers using his target's address and steers their answers there. In December 2020 Valve added a preceding challenge (S2C_CHALLENGE) to A2S_INFO, which the querying party has to echo back before it receives the answer. That defuses reflection but does not end it, because older query clients are still served.
What you can do yourself before spending money
The following section costs nothing and is worth doing regardless of where your server is hosted. It will not save you from a volumetric attack, but it makes small and medium attacks fizzle out, and it removes the outages that get reported as DDoS attacks but are not.
1. Take stock: what is actually listening
Before you write a single rule, find out which services are reachable. On a Left 4 Dead 2 server that has grown over time it is almost always more than expected, because next to srcds there is often a web server for the campaigns, a statistics database and sometimes a second instance for versus:
ss -lntup
Anything bound to 127.0.0.1 or ::1 needs no firewall rule. Anything listening on 0.0.0.0 or [::] is reachable from the internet. The attacker's view comes from an external port scan, and experience says it differs from your own expectation:
nmap -Pn -sU -sT -p 27000-27050,80,443,3306 YOUR.SERVER.IP.ADDRESS
If the base is freshly set up or you want to retrace it, Installing a game server with SteamCMD covers the path from SteamCMD to a running srcds.
2. Leave open only the ports srcds really needs
One UDP port to the internet, one TCP port for your own address, nothing else. RCON does not belong on the open internet, because whoever holds RCON can change the map, ban every player and stop the server:
ufw allow 27015/udp comment "L4D2 game port and A2S"
ufw allow from 203.0.113.10 to any port 27015 proto tcp comment "RCON"
ufw allow from 203.0.113.10 to any port 22 proto tcp comment "SSH"
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
Replace 203.0.113.10 with your own address. If yours changes regularly, use an SSH port forward instead of a permanent rule. The order in which you arm a firewall decides whether you lock yourself out; that order and the way back are in Setting up a UFW firewall without locking yourself out. If it happens anyway: KVM root servers and dedicated servers at KernelHost have no IPMI and no iDRAC, you reach the machine through the VNC console in the customer panel, and that console does not depend on the guest system's network stack.
3. Rate limit the A2S query without dropping out of the lobby search
This is where the most expensive mistake in this field is made. Because game traffic and the server query occupy the same port, the limiter has to distinguish between two classes of packets, not between ports.
Since the December 2020 changes, the Steam game server layer brings its own limiter, set as an environment variable before the process starts. STEAM_GAMESERVER_RATE_LIMIT_200MS=N drops connectionless packets (A2S_INFO, A2S_RULES, A2S_PLAYERS) from a given address once more than N of them arrive within a 200 millisecond window. Valve names 25 to 75 as a usable range; the limiter is off by default:
export STEAM_GAMESERVER_RATE_LIMIT_200MS=50
./srcds_run -game left4dead2 -console -port 27015 +exec server.cfg +map c1m1_hotel
In a systemd unit the same value belongs in the [Service] section as Environment=STEAM_GAMESERVER_RATE_LIMIT_200MS=50, otherwise it is gone after the next restart. This limiter only takes effect if your server build ships the current Steamworks layer, and it protects your server's processing time, not your uplink: the packets have already arrived.
One layer down, the same traffic can be separated in the kernel. All connectionless Source engine packets, meaning server queries and connection setup, begin with four set bytes (0xffffffff), while traffic from already connected players does not carry that header. A per source address rate limit can be built on exactly that with nftables:
table inet l4d2 {
chain input {
type filter hook input priority -10; policy accept;
udp dport 27015 @th,64,32 0xffffffff \
meter a2sflood { ip saddr limit rate over 10/second burst 20 packets } drop
}
}
Load the file with nft -f. Priority -10 makes the rule take effect before the UFW filter chain, and @th,64,32 reads the first four bytes behind the UDP header. Start generously and tighten the limit only once legitimate queries demonstrably get through: your own server list entry depends on it.
4. Use the lobby system as an access filter
This is the lever only Left 4 Dead 2 and its predecessor have. The server itself decides whether it accepts connections from outside matchmaking at all. Four directives in server.cfg govern that:
sv_allow_lobby_connect_only 1
sv_search_key "your-own-key"
sv_steamgroup "103582791400000000"
sv_steamgroup_exclusive 2
sv_allow_lobby_connect_only 1permits joins from a matchmaking lobby only. Aconnect 203.0.113.10:27015in the developer console and a Steam invite are both rejected. A value of 0 allows both.sv_search_keyis a freely chosen search key. Only a lobby with the same key set finds the server through matchmaking. Without the key it does not show up in the public search.sv_steamgroupties the server to a Steam group and lists it under that group's servers.sv_steamgroup_exclusivehas three levels: 0 lets anyone in, 1 behaves like 0 but requires the join to come from a lobby, and 2 lets in only group members and direct access by IP address.
For a fixed community, a search key combined with sv_steamgroup_exclusive 2 is the most effective free access filter the game has. A public server cannot use it, because a server nobody finds is just as empty as one that is offline.
And now the part marketing copy likes to leave out: these directives protect your game logic, not your uplink. An attacker flooding 27015/UDP does not want to join. His packets are rejected, but they arrived anyway, consumed bandwidth and cost one trip through the network stack. Against a join flood from throwaway accounts sv_allow_lobby_connect_only 1 works beautifully; against a booter it does nothing at all.
5. The lobby reservation and when sv_force_unreserved is the better choice
A lobby reservation is a time limited claim on your server by a matchmaking lobby. While it exists, the server counts as taken for other lobbies, and it only expires on its own after a while. For a server with four slots that is a scarce resource: unlike a shooter with 32 or 64 slots, very little is needed to block a session.
If you do not run your server through matchmaking, remove that surface entirely:
sv_force_unreserved 1
sv_allow_lobby_connect_only 0
sv_force_unreserved 1 makes the server stop answering reservation requests from the lobby system and reject joins that carry a reservation token. You need the same setting anyway if you run more than four co-op slots with L4DToolZ, because otherwise the lobby receives a reservation as soon as the first four slots are filled and the remaining slots stay unreachable. The downside is clear: your players can then only arrive through the server browser or through connect.
Pick one of the two modes deliberately. The mixture of half open matchmaking and half open direct joins is the variant that combines both drawbacks.
6. Secure RCON
An open RCON port with a weak password is not a DDoS problem, it is a takeover. Never leave rcon_password empty and never let it be guessable; a value from openssl rand -base64 32 is enough. The Source titles also ship a brake against login attempts:
rcon_password "A_RANDOM_VALUE_HERE"
sv_rcon_minfailures 3
sv_rcon_maxfailures 5
sv_rcon_minfailuretime 30
sv_rcon_banpenalty 1440
That bans an address for a day after three failed attempts within 30 seconds; find sv_rcon in the server console shows which of these variables your build knows. The firewall restriction from step 2 remains more effective, because it never lets the attempt reach the application. If you do not need RCON, leave the password empty: the TCP side of 27015 then does not listen at all.
7. Offload custom campaigns instead of serving them over the game port
Custom campaigns are the reason Left 4 Dead 2 is still played after fifteen years, and at the same time a source of load that Counter-Strike does not have in this form. A campaign is a VPK package with maps, models, textures and sounds, so it weighs a multiple of a single competitive map.
The comfortable route for players is the Steam Workshop: the package then comes from Steam, not from your server, and costs you no bandwidth. If you serve loose files yourself, that job belongs on a web server and not on the game port:
sv_allowdownload 1
sv_allowupload 0
sv_downloadurl "https://cdn.example.org/l4d2/"
sv_consistency 1
Files for sv_downloadurl go onto the web server as bzip2 archives, so mymap.bsp becomes mymap.bsp.bz2. Without sv_downloadurl, srcds sends the files itself over the game connection, and then every connection attempt by a new player costs you the full download, as does every abort halfway through. That is a remarkably cheap way to fill an uplink, and it looks like an attack in no statistic.
Three points on this that hurt in practice. Set sv_allowupload 0, because uploads from the client to the server are something you do not need. If the web server behind sv_downloadurl lives on the same host as the game, downloads and game traffic share the same uplink and the same IP address, and an attack on 443/TCP then also hits your running session. And sv_consistency 1 is not protection against attacks but against mismatched client files; turn it off only when a campaign demonstrably refuses to start otherwise.
8. SourceMod, Metamod and the extensions
A substantial share of outages reported as DDoS attacks are none. They are crashes and load spikes triggered by a single client, because a hole is open in the server binary or in an extension. Bandwidth does not help against that, maintenance does:
- Keep Metamod:Source and SourceMod matched to the engine version. Left 4 Dead 2 still receives updates, and a mismatched extension is the most common reason for crashes right after one.
- Use Left4DHooks instead of your own hooks. The L4D2 specific events are bundled in that extension. Patching the same functions yourself is the fastest route to a server binary that gives up on certain packet sequences.
- Deploy L4DToolZ deliberately. The extension raises the hard coded slot limits. Every additional slot is an additional player generating processing time, and in combination with the lobby system it requires
sv_force_unreserved 1. - Fewer extensions. Every plugin is code in the same process. Extensions with their own web services open additional ports and often publish exactly the address you are trying to protect.
Bans have to be written to disk, otherwise they are gone after a restart. The Source titles use banid with writeid and addip with writeip for that, and the resulting files are read back in through exec banned_user.cfg and exec banned_ip.cfg.
9. Take load off connection tracking and the receive buffers
This point is frequently overlooked and explains outages that look like a volumetric attack but are not. The kernel creates connection tracking (conntrack) entries for UDP traffic, and with forged source addresses every address means a new entry. Once the table is full, the kernel drops packets without distinction: the attack and your players go out together. A glance shows the current state and the ceiling:
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
The most effective step is to not track the game traffic in the first place, because the engine manages its own sessions:
table inet raw {
chain prerouting {
type filter hook prerouting priority raw; policy accept;
udp dport 27015 notrack
}
chain output {
type filter hook output priority raw; policy accept;
udp sport 27015 notrack
}
}
With iptables the equivalent is iptables -t raw -A PREROUTING -p udp --dport 27015 -j NOTRACK plus the same line for OUTPUT with --sport. After that the port needs an explicit rule, because without tracking no rule that checks an existing state applies any more. If packets arrive faster than srcds picks them up, the receive buffer overflows on top of that, and to players that looks like packet loss on an idle line:
net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.netdev_max_backlog = 16384
Put the file under /etc/sysctl.d/ and activate it with sysctl -p. Whether the values are needed at all is something the kernel tells you: if UdpRcvbufErrors in nstat -az climbs, they matter. If the counter stays at zero, the change does nothing. This is headroom, not protection.
10. Measure, so you do not have to guess during an attack
During an attack the important question is: how much is arriving, on which port, and is it query or game traffic. Four commands are enough:
ip -s link show eth0
nstat -az | grep -i udp
sar -n DEV 1 10
tcpdump -ni eth0 -c 200 "udp port 27015 and udp[8:4] = 0xffffffff"
Run the first command twice, ten seconds apart, and you have a rate instead of an absolute value. The last line shows only the connectionless packets, which is exactly the class a query flood abuses; if the counter fills up in seconds while barely anyone is connected, you have your answer. Keep the capture short, because under load it costs processing time of its own. How to interpret the values is covered in Detecting a DDoS attack on your server.
The most important step, though, is the one almost nobody takes beforehand: establish a baseline while everything is normal. Without a normal value you cannot say after an incident whether 40,000 packets per second was a lot or simply Friday evening with a full versus server.
Where these measures end
Now the honest part. Everything described so far only takes effect once the packets have reached your network card. A firewall rule decides about a packet that has already travelled down the wire. You can drop it, but you cannot un-send it.
Do the math once. A typical game server sits on 1 Gbps, which is 125 megabytes per second. At the smallest possible packet size that line carries around 1.49 million packets per second, a 10 Gbps line around 14.88 million. That is the physical ceiling, independent of CPU, kernel and firewall. A normal server kernel handles a few hundred thousand packets per second depending on processor and network card before it starts dropping. So an attack that does not even fill a third of your line can still take your server down, because the processing time goes into dropping. Operators experience this as "utilization was not even high and everything was gone anyway".
Against that stand real attacks. Two examples from operations at KernelHost, both filtered in real time: a UDP flood against a game server on 7777/UDP with more than 112.2 Gbps and more than 8.7 million packets per second, and a multi-vector attack against a voice server on 9987/UDP with more than 473.4 Gbps and more than 41.5 million packets per second. Measure that against your line: 473.4 Gbps is roughly 470 times a 1 Gbps uplink and still roughly 47 times a 10 Gbps uplink.
This is why the two common emergency brakes are unsatisfying. Null routing (blackholing) takes the attacked IP address off the network and does end the attack, but it ends your server too: for your players the result is identical to a successful attack. A reactive reroute costs, in its switchover time, exactly the minutes in which the campaign is decided. Only filtering that runs permanently in the network in front of the server is effective.
What KernelHost puts in front of it
The always-on protection included with every server
DDoS protection at KernelHost has two layers and is permanently active, without you switching on, ordering or configuring anything:
- Layer 1: 17 Tbps of mitigation capacity in the global scrubbing network. Volumetric attacks are cleaned close to their source, long before they reach the data center.
- Layer 2: Arbor real-time filtering with 3.2 Tbps in Frankfurt am Main. Directly in front of the server, protocol specific patterns on layers 3 to 7 are recognized and dropped, packet by packet.
Two properties are decisive. First, the filtering runs permanently, so there is no switchover window in which your players get thrown out. Second, no null routing is used: the attacked IP address stays on the network and only the malicious packets are dropped. The protection is included in every server package at no surcharge, with no separate protection product and no setup, and it is active from provisioning onwards. The servers are in the maincubes Premium Datacenter in Frankfurt am Main. Which games and protocols are covered is listed in Game server DDoS protection in real time.
Advanced DDoS Protection for projects under permanent fire
Some projects are attacked not occasionally but deliberately and for weeks, with changing patterns and always right on the agreed campaign night. For those cases there is Advanced DDoS Protection from €50.00 per month, PrePaid and with no minimum term. The difference is not more capacity, it is control:
- A dedicated protected IP. Your server is moved onto that address inside our network; no rebuild is needed on your side.
- Self-managed protection rules per port and protocol. In the customer panel you define which port is filtered with which profile, so 27015/UDP differently from the web server that delivers your campaigns.
- Changes take effect in real time, with no ticket and no waiting. You can therefore fine-tune while an attack is running.
- A protection profile matched to the game. For Left 4 Dead 2 and the other Source titles as well as for more than 40 further games and protocols, plus free TCP and UDP profiles for modified servers.
The PrePaid model applies here too: no minimum term, no notice period, no contract and no setup fee. Once the wave of attacks is over, you simply do not renew.
The two layers compared
| Feature | Included always-on protection | Advanced DDoS Protection |
|---|---|---|
| Price | included in every server package at no surcharge | from €50.00 per month, PrePaid with no minimum term |
| Activation | active from provisioning, nothing to set up | order it, receive the protected IP, server is moved over |
| Filtering capacity | 17 Tbps global scrubbing plus 3.2 Tbps Arbor real-time filtering in Frankfurt am Main | the same two-layer filtering, plus your own rules |
| IP address | your server's IP address | an additional dedicated protected IP |
| Changing rules | maintained by KernelHost, fine-tuning by ticket | yourself in the customer panel, effective in real time |
| Game profiles | more than 40 games and protocols, Source titles included | profile selectable per port, also for modified servers |
| Null routing during an attack | no | no |
| Suited for | every server, from the first campaign on | projects under permanent and targeted fire |
For most Left 4 Dead 2 projects the included always-on protection plus a clean server configuration is enough. Advanced DDoS Protection is the answer to somebody taking it personally.
Common mistakes and their fixes
The server has disappeared from the lobby search but is still running: usually 27015/UDP was blocked outright or rate limited too tightly, and because game traffic and query share the port, a coarse rule hits both. Match on the connectionless packets instead. If the port is reachable and the server is still invisible, check sv_search_key, sv_steamgroup_exclusive, sv_lan 0 and sv_region 255, and whether the process was started with -nomaster by accident.
The server console keeps printing "Invalid split packet length": that is not a volumetric attack, it is a malformed network packet sent in rapid succession. The traffic stays tiny and the server lags anyway. Check first whether the bandwidth is conspicuous at all, and bring the server binary and the extensions up to date. Bandwidth does not help here.
Every player has high ping but the line is not full: that points to packet rate rather than volume. Look at the dropped packets in ip -s link show and the UDP counters in nstat -az. If the system log says nf_conntrack: table full, take the game port out with notrack.
The firewall rule is correct and still does nothing: check with iptables -L INPUT -n -v whether the hit counters are rising. If they stay at zero, the rule is never reached, because it sits behind the UFW chains or was lost in the last reboot. If they rise and nothing changes, the line in front of the server is saturated, and from there only filtering in the network helps.
The server accepts no more players although slots are free: usually a lobby reservation is stuck. Either run the server consistently through matchmaking, or set sv_force_unreserved 1 and let your players join through the server browser. With more than four co-op slots under L4DToolZ that setting is mandatory anyway.
New players download forever and the line is full while they do: then srcds is serving the campaign files itself over the game port. Point sv_downloadurl at a web server and place the files there as bzip2 archives, or send your players to the Steam Workshop.
The attack pauses after an IP change and returns after one or two days: that is the normal case, because your server publishes the new address itself as soon as it is registered again, and a forgotten DNS record or a Discord bot with a status display does the rest. An IP change buys hours, not a solution.
Foreign administration commands are running on your server: not a DDoS attack but a compromised RCON access. Change the password immediately and restrict the TCP side of 27015 to your own address.
In short
- A Left 4 Dead 2 server needs exactly one port open to the internet: 27015/UDP. Game traffic and the A2S query share it, and there is no separate query port.
- 27015/TCP is RCON and belongs to your own address only. If you do not need RCON, leave
rcon_passwordempty. - The lobby system is the most effective free access filter the game has:
sv_allow_lobby_connect_only 1, your ownsv_search_keyandsv_steamgroup_exclusive 2shut out everything that does not come through matchmaking. It filters joins, not packets. - Custom campaigns belong in the Steam Workshop or behind
sv_downloadurl, never on the game port. Otherwise every aborted connection attempt is paid for with your bandwidth. - Rate limiting has to distinguish connectionless packets (starting with
0xffffffff) from game traffic. A coarse rule on 27015/UDP throws out your own players. - With 64 byte packets a 1 Gbps line carries around 1.49 million packets per second. Above that, only the network in front of the server decides, never a setting on the server itself.
- At KernelHost, 17 Tbps of global scrubbing and Arbor real-time filtering with 3.2 Tbps in Frankfurt am Main filter permanently and at no surcharge, with no null routing and no switchover window.
If your project already runs at KernelHost, the filtering is active without you doing anything. If you still notice something unusual, open a support ticket so our team can fine-tune the filter rules for your IP address. During an ongoing attack you can also reach us through the WhatsApp emergency chat at +43 650 8209883. Give us four details right away: IP address, port, time frame in your time zone, and what you are seeing (players being thrown out, server missing from the lobby search, high ping). That saves a round of follow-up questions, and those count while a campaign is running.
If you host elsewhere and get shot at regularly, moving to KernelHost is a shorter path than another rule on a server whose uplink ends first. The always-on protection is part of every server package, not an add-on you book once the trouble starts.
Frequently asked questions
Which ports do I have to leave open for a Left 4 Dead 2 server?
My L4D2 server lags but the line is free. Is that a DDoS attack?
Does sv_allow_lobby_connect_only 1 protect against DDoS attacks?
Can I simply rate limit port 27015 while the server is being attacked?
What is a lobby reservation and why does it block my server?
Do custom campaigns make my server vulnerable?
At what attack size does no firewall rule help any more?
Does my server at KernelHost go offline during an attack?
Does DDoS protection at KernelHost cost extra?
When do I additionally need Advanced DDoS Protection?
2026 KernelHost GmbH. All rights reserved. This guide is protected by copyright. Republishing it on other websites, in whole, in part or in edited form, is not permitted without our written consent. Quoting with a source credit and a link is expressly welcome.

