DDoS Protection for Linux Game Servers: fail2ban Guide | linuxrockstar.com
16463
wp-singular,post-template-default,single,single-post,postid-16463,single-format-standard,wp-theme-bridge,bridge-core-1.0.5,sfsi_actvite_theme_default,ajax_fade,page_not_loaded,,qode-theme-ver-18.1,qode-theme-bridge,disabled_footer_top,qode_header_in_grid,wpb-js-composer js-comp-ver-7.9,vc_responsive
 

DDoS Mitigation for Linux Game Servers: fail2ban, Rate Limiting & Network Namespaces

DDoS Mitigation for Linux Game Servers: fail2ban, Rate Limiting & Network Namespaces

DDoS Mitigation for Linux Game Servers: fail2ban, Rate Limiting & Network Namespaces

Your CS2 community server just went offline. tcpdump shows 400k UDP packets per second hammering port 27015, and your iptables ruleset — configured for SSH brute-force, not game traffic floods — is doing nothing useful. This guide builds a three-layer mitigation stack that addresses that exact scenario: iptables hashlimit rules tuned for UDP game traffic, custom fail2ban jails for your specific log format, and network namespace isolation to contain the blast radius when a volumetric attack hits.

TL;DR: DDoS Mitigation Stack at a Glance

  • This guide covers three host-level mitigation layers plus upstream provider guidance.
  • Layer 1: iptables hashlimit rate limiting for UDP/TCP game ports.
  • Layer 2: fail2ban custom jails for SSH and management interfaces.
  • Layer 3: network namespace isolation to limit per-service blast radius.
  • Estimated setup time: 2-3 hours. Prerequisites: root access, iptables, fail2ban installed.

Who this guide is for: Linux sysadmins and self-hosted game server operators who want layered DDoS protection without paying for upstream scrubbing. You should be comfortable at the command line and have basic familiarity with iptables or nftables.

Before layering DDoS-specific mitigations on top of your stack, you need a solid firewall foundation that handles the fundamentals — port whitelisting, stateful connection tracking, and rate-limiting inbound traffic to your game ports. A well-structured ruleset in either iptables or nftables lets you define exactly what traffic your server accepts and drops everything else by default. Our Linux game server firewall rule playbook walks you through building that baseline configuration, covering chain structure, UDP flood guards, and ICMP controls specific to game server environments.

Before diving into specific tools like fail2ban, it’s worth stepping back to understand the broader security posture your server should maintain from day one. Linux sysadmins running game servers face a unique threat landscape — public-facing ports, high-volume UDP traffic, and a player base that can attract bad actors fast. Establishing a baseline using frameworks like CIS Controls gives you a structured, proven foundation rather than a patchwork of reactive fixes. The CIS Controls guide for game server hardening covers exactly this kind of systematic approach across popular titles like Minecraft, Valheim, and CS2, making it a practical reference point before you layer on rate-limiting and intrusion prevention.

What fail2ban Actually Does — and Where It Stops

What is fail2ban in a DDoS context? fail2ban is a log-parsing daemon that reads application log files, matches lines against regex patterns (failregex), and issues iptables DROP rules for offending IPs after a configured threshold. It’s a reactive ban tool, not a traffic absorber.

That distinction matters enormously for game servers. Against a volumetric UDP flood targeting port 27015 on a Valheim or Minecraft server, fail2ban arrives too late. The upstream pipe saturates before fail2ban parses a single log line. By the time a ban fires, your NIC buffer has been overflowing for 30 seconds.

Where fail2ban genuinely earns its place in a game server stack:

  • SSH brute-force on port 22 (its original purpose, still valid)
  • Admin panel protection (RCON, web-based consoles on TCP ports)
  • Repeated TCP connection floods where log entries are produced per attempt
  • Application-layer attacks where the game server logs failed authentication

The core problem: most UDP-based game protocols don’t produce log entries that fail2ban can parse per packet. A 500k pps UDP flood generates no application log output. iptables hashlimit is your primary control for game ports. fail2ban handles everything else.

iptables Rate Limiting: hashlimit and connlimit for Game Traffic

Yes, you can rate limit UDP game traffic with iptables using the hashlimit module. Here’s exactly how it works and why each parameter is set as shown.

Understanding hashlimit vs connlimit

hashlimit tracks per-source-IP packet rates using a token bucket algorithm. When an IP exceeds the defined rate, subsequent packets are dropped until the bucket refills. This is the right tool for UDP flood mitigation because it operates at the packet level, not the connection level.

connlimit limits simultaneous TCP connections per source IP. It’s useless for UDP (UDP is connectionless) but works well for TCP game protocols and RCON admin interfaces where you want to cap concurrent sessions.

How to Rate Limit UDP Traffic with iptables (Step by Step)

  1. Flush existing game-port rules to avoid conflicts:
    iptables -F INPUT

  2. Accept established and related connections first — this prevents dropping legitimate return traffic:
    iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

  3. Accept loopback traffic unconditionally:
    iptables -A INPUT -i lo -j ACCEPT

  4. Apply hashlimit rate limiting to your game server UDP port (adjust port to match your game):
    iptables -A INPUT -p udp --dport 27015 \
    -m hashlimit \
    --hashlimit-name game_udp \
    --hashlimit-above 100/sec \
    --hashlimit-burst 200 \
    --hashlimit-mode srcip \
    --hashlimit-srcmask 32 \
    -j DROP

  5. Apply connlimit for TCP game ports and RCON:
    iptables -A INPUT -p tcp --dport 27015 \
    -m connlimit --connlimit-above 10 --connlimit-mask 32 \
    -j DROP

  6. Accept legitimate game traffic that passed rate limiting:
    iptables -A INPUT -p udp --dport 27015 -j ACCEPT
    iptables -A INPUT -p tcp --dport 27015 -j ACCEPT

  7. Set default DROP policy on INPUT chain:
    iptables -P INPUT DROP

The --hashlimit-above 100/sec parameter drops packets from any single IP sending more than 100 UDP packets per second. The burst value of 200 allows brief legitimate spikes (player connecting, loading assets) without triggering a false positive. For Minecraft or Valheim, 100/sec per IP is generous — a legitimate player generates a modest number of UDP packets per second during normal gameplay, well below this threshold.

Verify your rules are active and counting packets:

iptables -L INPUT -n -v

Watch the packet and byte counters increment. If the DROP rule for hashlimit shows zero packets, either no traffic is hitting the threshold or the rule ordering is wrong.

iptables vs nftables: Which Should You Use?

Featureiptablesnftables
Syntax stylePer-rule flags, verboseTable/chain/rule blocks, concise
Performance at high ppsDegrades with large rulesetsBetter scaling, JIT compilation
UDP rate limitinghashlimit modulemeter/limit statements
Persistence methodiptables-save / iptables-restorenft ruleset files, systemd service
Recommended forExisting deployments, familiarityNew deployments, high packet rates
Learning curveLower for existing adminsSteeper but more consistent

Writing a Custom fail2ban Jail for Your Game Server

What is a fail2ban custom jail? A fail2ban jail is a configuration block that monitors a specific log file for attack patterns and automatically bans offending IPs using iptables. Generic jails target sshd and apache. Your game server produces a completely different log format that requires a custom filter regex.

The Three Components You Need

A working game server jail requires exactly three things: a filter file with failregex, a jail.local stanza, and a verified log path. Missing any one of them produces a jail that appears active but silently matches nothing.

Create the filter file at /etc/fail2ban/filter.d/gameserver.conf:

[Definition]
failregex = ^.*\[WARN\].*Failed connection attempt from <HOST>.*$
            ^.*\[AUTH\].*Invalid password from <HOST>.*$
            ^.*\[RCON\].*Bad password from <HOST>.*$
ignoreregex =

Adjust the regex patterns to match your specific game server log format. A Minecraft server running Paper produces different output than a CS2 dedicated server. Pull 50 lines from your actual log and build the regex against real data.

Add the jail stanza to /etc/fail2ban/jail.local:

[gameserver]
enabled  = true
filter   = gameserver
logpath  = /var/log/gameserver/server.log
maxretry = 5
findtime = 60
bantime  = 3600
action   = iptables-multiport[name=gameserver, port="27015,27016", protocol=tcp]

Test your filter before activating the jail. A broken regex silently matches nothing, and you won’t know until you’re under attack:

fail2ban-regex /var/log/gameserver/server.log /etc/fail2ban/filter.d/gameserver.conf

The output shows how many lines matched. Zero matches means your regex is wrong, not that your server is clean. Fix the regex first.

Reload fail2ban and verify the jail is running:

fail2ban-client reload
fail2ban-client status gameserver

The status output shows active bans, total banned IPs, and the monitored log path. If the jail shows as inactive, check /var/log/fail2ban.log for parsing errors.

Firewall Rule Ordering: Building the Chain Correctly

iptables evaluates rules top-to-bottom and stops at the first match. Get the order wrong and you’ll drop legitimate player traffic or, worse, allow flood traffic through a gap between rules.

The Correct Chain Order

The correct ordering for a game server INPUT chain:

  1. ACCEPT ESTABLISHED/RELATED (conntrack) — prevents dropping return traffic
  2. ACCEPT loopback (lo interface)
  3. hashlimit DROP rules for game UDP ports
  4. connlimit DROP rules for game TCP ports
  5. fail2ban chain jump (fail2ban inserts its own chain automatically)
  6. ACCEPT rules for SSH, game ports, and management interfaces
  7. Default DROP policy

Save this as a shell script you can source on boot. Place it at /usr/local/bin/gameserver-firewall.sh and add it to your systemd startup or /etc/rc.local:

#!/bin/bash
# Game Server Firewall — source on boot
iptables -F INPUT
iptables -F FORWARD

# Established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT

# UDP rate limiting — game port
iptables -A INPUT -p udp --dport 27015 \
  -m hashlimit --hashlimit-name game_udp \
  --hashlimit-above 100/sec --hashlimit-burst 200 \
  --hashlimit-mode srcip --hashlimit-srcmask 32 -j DROP

# TCP connection limiting — game port and RCON
iptables -A INPUT -p tcp --dport 27015 \
  -m connlimit --connlimit-above 10 --connlimit-mask 32 -j DROP
iptables -A INPUT -p tcp --dport 27020 \
  -m connlimit --connlimit-above 3 --connlimit-mask 32 -j DROP

# SSH — rate limit to prevent brute force
iptables -A INPUT -p tcp --dport 22 \
  -m hashlimit --hashlimit-name ssh \
  --hashlimit-above 5/min --hashlimit-burst 10 \
  --hashlimit-mode srcip -j DROP

# Accept game and management traffic that passed rate limiting
iptables -A INPUT -p udp --dport 27015 -j ACCEPT
iptables -A INPUT -p tcp --dport 27015 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Default policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

Network Namespaces for Game Server Traffic Isolation

Network namespaces give a process its own isolated network stack — its own interfaces, routing table, and firewall rules. A DDoS targeting your game server port doesn’t affect SSH or web services running in the default namespace. This is not a traffic absorber. It’s a blast radius limiter.

Creating an Isolated Namespace for Your Game Server

Create the namespace and a virtual ethernet pair connecting it to the host:

# Create the namespace
ip netns add gameserver

# Create a veth pair
ip link add veth0 type veth peer name veth1

# Move veth1 into the namespace
ip link set veth1 netns gameserver

# Configure host-side interface
ip addr add 10.0.1.1/24 dev veth0
ip link set veth0 up

# Configure namespace-side interface
ip netns exec gameserver ip addr add 10.0.1.2/24 dev veth1
ip netns exec gameserver ip link set veth1 up
ip netns exec gameserver ip link set lo up
ip netns exec gameserver ip route add default via 10.0.1.1

Enable NAT so the game server namespace can reach the internet:

iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Launch your game server process inside the namespace:

ip netns exec gameserver sudo -u gameuser /opt/gameserver/start.sh

Verify the namespace is active and the game server is isolated:

ip netns list
ip netns exec gameserver ip addr show
ip netns exec gameserver ss -tulnp

The ss -tulnp output inside the namespace should show only your game server listening on its port. SSH and other host services won’t appear because they’re running in the default namespace.

Can a volumetric DDoS still saturate your upstream bandwidth even with namespace isolation? Yes. Namespace isolation prevents cross-service interference on the host, but it doesn’t filter traffic before it hits your NIC. That’s what upstream scrubbing handles.

When Host-Level Controls Stop Being Enough

Volumetric attacks that exceed your host’s upstream bandwidth capacity cannot be mitigated at the host level. The pipe fills before your iptables rules fire. A 10 Gbps attack against a server with a 1 Gbps uplink means your rules never see the traffic — the upstream router is already dropping it.

Upstream Options and Their Tradeoffs

Cloudflare Spectrum proxies TCP game traffic and provides upstream scrubbing. It does not support UDP, which rules it out for most UDP-based game protocols (CS2, Valheim, most Source engine games). If your game runs on TCP, Spectrum is worth evaluating. If it runs on UDP, look elsewhere.

DDoS-aware VPS providers — Hetzner, OVH, and Path.net are commonly used in the self-hosted gaming community — offer upstream scrubbing that filters traffic before it reaches your server. Hetzner’s DDoS protection activates automatically for attacks above their detection threshold. OVH’s Game DDoS protection is tuned specifically for game server traffic patterns, including UDP amplification and reflection attacks. Evaluate based on your game protocol, your geographic player base, and your attack history.

The decision point: if you’re seeing attacks that saturate your link (check with vnstat -l or iftop), host-level controls are insufficient and you need an upstream provider. If attacks are below your link capacity but overwhelming your application, the iptables and fail2ban layers described above are your primary defense.

Monitoring: Knowing When You’re Under Attack

Three signals indicate an active attack: iptables DROP counter spikes on rate-limiting rules, connection count spikes from ss -s, and system load increases from packet processing overhead.

Watch DROP counters in real time:

watch -n 1 'iptables -L INPUT -n -v | grep DROP'

Configure fail2ban to send webhook alerts on ban events. Silent banning means zero visibility into attack frequency. Add an action to your jail.local:

action = iptables-multiport[name=gameserver, port="27015", protocol=udp]
         sendmail-whois[name=gameserver, [email protected]]

For real-time bandwidth visibility, iftop -i eth0 shows per-connection bandwidth usage. A sudden spike on port 27015 from a single source IP is the first indicator of a targeted attack. vnstat gives you historical bandwidth data to compare against baseline traffic.

DDoS Mitigation Checklist for Linux Game Servers

  • iptables hashlimit rules active: Verify with iptables -L INPUT -n -v and confirm DROP counters increment during test traffic.
  • connlimit rules on TCP ports: Confirm RCON and admin ports have connection limits set.
  • fail2ban gameserver jail running: Confirm with fail2ban-client status gameserver — jail status must show “active.”
  • fail2ban filter tested: Run fail2ban-regex against your actual log file and confirm non-zero matches.
  • Firewall script on boot: Confirm your iptables script runs at startup via systemd or rc.local.
  • Network namespace configured: Verify with ip netns list and ip netns exec gameserver ss -tulnp.
  • Monitoring active: iftop, vnstat, and fail2ban alerts configured — not silent.
  • Upstream provider evaluated: Determine whether your uplink capacity matches your threat model.

Start with the iptables ruleset. Rate limiting gaps are the most common vulnerability in game server deployments, and they’re the most fixable in under an hour. Get the hashlimit rules in place first, verify the DROP counters are working, then layer in the fail2ban jail and namespace isolation.

Frequently Asked Questions

Does fail2ban work with UDP traffic?

fail2ban cannot parse UDP game traffic directly because UDP packets don’t produce application log entries per packet. fail2ban reads log files — if your game server doesn’t log UDP connection attempts, fail2ban has nothing to act on. Use iptables hashlimit for UDP port rate limiting and reserve fail2ban for SSH and TCP-based admin interfaces.

Can iptables rate limiting stop a volumetric DDoS attack?

iptables hashlimit can stop attacks where the flood originates from a small number of source IPs and your upstream link isn’t saturated. Against a distributed volumetric attack with thousands of source IPs and traffic exceeding your uplink capacity, iptables rules fire too late. Upstream scrubbing from your hosting provider is required for true volumetric mitigation.

What is the difference between hashlimit and connlimit in iptables?

hashlimit tracks packet rates per source IP using a token bucket — it works for both UDP and TCP. connlimit tracks simultaneous TCP connections per source IP — it only applies to TCP because UDP has no connection state. Use hashlimit for game server UDP ports and connlimit for TCP admin interfaces.

What is the difference between network namespaces and containers for game server isolation?

Network namespaces provide network stack isolation only — the game server process still shares the host kernel, filesystem, and PID namespace. Containers (Docker, LXC) combine network namespaces with additional isolation layers (filesystem, process). For DDoS blast radius limiting, a network namespace is sufficient and lighter than a full container.

How do I know if my iptables rules are actually dropping attack traffic?

Run iptables -L INPUT -n -v and watch the packet counter on your hashlimit DROP rule. During an attack, that counter should increment rapidly. If it stays at zero while you’re seeing high traffic on the interface, your rule ordering is wrong — the traffic is matching an earlier ACCEPT rule before reaching the rate limit.

When should I use Cloudflare Spectrum for a game server?

Use Cloudflare Spectrum only if your game server runs on TCP. Spectrum proxies TCP traffic and provides upstream DDoS scrubbing, but it has no UDP support. Most Source engine games (CS2, TF2), Valheim, and Minecraft (Java edition) use UDP for game traffic, making Spectrum unsuitable as a primary mitigation layer for those protocols.

No Comments

Sorry, the comment form is closed at this time.