18 Aug Locking Down Your Linux Game Server: iptables & nftables Firewall Playbook
Your game server goes live, and within minutes port scanners are probing it. UDP floods, RCON brute-force attempts, and connection exhaustion attacks are not theoretical — they hit self-hosted Minecraft, ARK, Valheim, and CS2 servers constantly. This playbook gives you a production-ready iptables and nftables ruleset, side-by-side, with per-rule explanations and the sysctl tuning that most firewall guides skip entirely.
Quick Summary: Use iptables or nftables to enforce a default-deny INPUT policy, restrict traffic to only your game ports, apply UDP rate limiting via the hashlimit module, and persist rules across reboots. The result is a locked-down server that handles legitimate player traffic while dropping floods and ban-listed IPs before they consume resources.
Why the Default iptables Policy Will Get Your Game Server Owned
The default iptables policy on most distros is ACCEPT on every chain. Every inbound packet passes without inspection. A freshly deployed VPS running a Minecraft server on port 25565 with default iptables is fully exposed — SSH, RCON, and any other listening service included.
This exposure problem doesn’t exist in a vacuum — your choice of operating system directly shapes how much control you have over closing those gaps. Linux’s netfilter stack gives you iptables, nftables, and ufw as native, zero-cost tools for locking down ports and filtering traffic at the kernel level, whereas Windows Server depends on a GUI-driven firewall that offers far less granularity for the kind of rule chaining game servers demand. If you haven’t settled on a platform yet, the Linux vs. Windows game server security comparison breaks down exactly how these architectural differences play out in practice, including performance trade-offs that matter once your server is under load.
Game servers attract specific abuse patterns. UDP amplification floods saturate your uplink. RCON ports left open on 0.0.0.0 get brute-forced within hours. Connection exhaustion attacks fill your conntrack table, causing legitimate players to see “connection timed out” during peak load. The fix is a default-deny INPUT chain with explicit allows, not a growing list of REJECT rules bolted onto an open policy.
Run this first to see your current state before touching anything:
iptables -L -v -n --line-numbers
iptables vs. nftables: Which Stack Should You Use
iptables and nftables are both Linux firewall frameworks built on netfilter, but they differ in syntax, performance, and toolchain compatibility. Use iptables if your stack depends on it — fail2ban, Docker, and LinuxGSM all work against iptables by default. Use nftables for new builds on kernel 3.13 or later where you want native set support and cleaner rule management.
| Feature | iptables | nftables |
|---|---|---|
| Syntax | Separate commands per table | Single nft command |
| Performance | Linear rule matching | Set-based O(1) lookups |
| Kernel support | All versions | 3.13+ |
| Persistence | iptables-save / netfilter-persistent | /etc/nftables.conf + systemd |
| ipset equivalent | External ipset tool | Native sets |
Building the Baseline iptables Ruleset
Set default policies to DROP on INPUT and FORWARD before adding any allow rules. This is the only safe starting position.
Common Game Server Port Reference
| Game | Port(s) | Protocol |
|---|---|---|
| Minecraft | 25565 | TCP |
| CS2 / Source | 27015 | TCP/UDP |
| Valheim | 2456-2458 | UDP |
| ARK | 7777, 27015 | UDP |
| Terraria | 7777 | TCP |
How to Open a Game Server Port in iptables
- Set default DROP policy on INPUT and FORWARD chains.
- Allow loopback traffic unconditionally.
- Allow established and related connections for stateful return traffic.
- Allow SSH on your chosen non-default port.
- Allow your specific game port(s) by protocol.
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow established/related (stateful tracking for return traffic)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Drop invalid state packets — these are common in flood traffic
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# SSH on non-default port (replace 2222 with your actual port)
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
# Minecraft example — TCP only, no RCON exposed publicly
iptables -A INPUT -p tcp --dport 25565 -j ACCEPT
# Valheim — UDP range
iptables -A INPUT -p udp --dport 2456:2458 -j ACCEPT
# CS2 — both protocols on 27015
iptables -A INPUT -p tcp --dport 27015 -j ACCEPT
iptables -A INPUT -p udp --dport 27015 -j ACCEPT
Never expose RCON on 0.0.0.0. Bind it to 127.0.0.1 in your game server config and access it via SSH tunnel. Leaving RCON public is how Source engine servers get hijacked within hours of going live.
Locking RCON to localhost is a solid first step, but it’s really just one layer in a much deeper hardening stack. A structured approach — covering everything from kernel parameter tuning and firewall rules to service isolation and audit logging — gives your server a far more resilient posture against the threats we’ll cover next. The CIS Controls guide for Linux game servers walks through that full framework specifically for Minecraft, Valheim, and CS2, so you can apply the same disciplined methodology to your own setup before DDoS vectors and network-layer attacks even become a concern.
Rate Limiting and DDoS Mitigation
UDP floods are the primary DDoS vector against game servers. A CS2 server under a UDP amplification attack will see its conntrack table fill completely, causing the kernel to drop legitimate player packets before the firewall even evaluates them. The hashlimit module rate-limits per source IP without blocking legitimate players during normal load.
How to Block an IP Address with iptables
Use ipset for dynamic ban lists. Static iptables rules can’t handle a growing list of cheater IPs efficiently — ipset does O(1) lookups against a hash table of thousands of entries.
# Create an ipset ban list
ipset create game_banlist hash:ip maxelem 65536
# Add a specific IP to the ban list
ipset add game_banlist 203.0.113.45
# Reference the ban list in iptables (place this BEFORE game port rules)
iptables -I INPUT 1 -m set --match-set game_banlist src -j DROP
# UDP rate limiting with hashlimit — 20 packets/second per source IP
# Burst of 50 allows normal connection spikes without dropping legit players
iptables -A INPUT -p udp --dport 27015 -m hashlimit \
--hashlimit-above 20/sec \
--hashlimit-burst 50 \
--hashlimit-mode srcip \
--hashlimit-name udp_game_limit \
-j LOG --log-prefix "UDP_FLOOD: "
iptables -A INPUT -p udp --dport 27015 -m hashlimit \
--hashlimit-above 20/sec \
--hashlimit-burst 50 \
--hashlimit-mode srcip \
--hashlimit-name udp_game_limit \
-j DROP
Log before you drop. The LOG rule gives you packet counters and source IPs you can feed directly into ipset ban list population. Aggressive hashlimit thresholds can drop legitimate players during connection spikes, so tune the burst value against your actual player count before going to production.
Once your ipset ban lists are dynamically populated with offending source IPs, the logical next step is to automate the detection-to-block pipeline using fail2ban alongside custom filters tuned for your traffic patterns. A complete fail2ban and automated DDoS mitigation workflow ties your firewall drop logs directly into rate-limiting rules and network namespace isolation, giving you a layered defense that reacts in seconds rather than requiring manual intervention. With that automated ban infrastructure in place, you can then shift focus to the kernel-level conntrack parameters that determine how well your system actually holds up under high connection volumes.
nf_conntrack Sysctl Tuning
High-concurrency UDP game servers fill the conntrack table fast. Tune these before your server goes live:
# Increase conntrack table size for high-concurrency game servers
echo "net.netfilter.nf_conntrack_max = 131072" >> /etc/sysctl.d/99-gameserver.conf
# Reduce UDP timeout — game clients reconnect quickly, no need for long tracking
echo "net.netfilter.nf_conntrack_udp_timeout = 30" >> /etc/sysctl.d/99-gameserver.conf
echo "net.netfilter.nf_conntrack_udp_timeout_stream = 60" >> /etc/sysctl.d/99-gameserver.conf
sysctl -p /etc/sysctl.d/99-gameserver.conf
Reducing Latency with DSCP Packet Marking
DSCP marking in the POSTROUTING chain tells upstream routers to prioritize game packets. This matters on managed networks and some VPS providers that honor DSCP EF (Expedited Forwarding) class.
# Mark outbound game UDP with DSCP EF (46) for priority queuing
iptables -t mangle -A POSTROUTING -p udp --sport 27015 -j DSCP --set-dscp-class EF
iptables -t mangle -A POSTROUTING -p udp --sport 2456:2458 -j DSCP --set-dscp-class EF
This doesn’t replace tc/HTB shaping on the host NIC. It’s a complement to QoS configuration, not a substitute. If your VPS provider doesn’t honor DSCP markings upstream, the benefit stays local.
Equivalent nftables Ruleset for Game Servers
nftables uses a single table/chain/rule hierarchy. Sets replace ipset natively — define your blocklist inline.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
# Native ban list — replaces ipset
set game_banlist {
type ipv4_addr
flags dynamic, timeout
timeout 7d
}
# Game ports set for clean rule references
set game_ports_udp {
type inet_service
elements = { 27015, 2456, 2457, 2458, 7777 }
}
chain input {
type filter hook input priority 0; policy drop;
# Drop ban-listed IPs immediately
ip saddr @game_banlist drop
# Allow loopback
iif lo accept
# Stateful tracking — allow established/related
ct state established,related accept
# Drop invalid state packets
ct state invalid drop
# SSH on non-default port
tcp dport 2222 accept
# Game ports with UDP rate limiting (20 packets/sec per source)
udp dport @game_ports_udp \
limit rate over 20/second burst 50 packets \
log prefix "UDP_FLOOD: " drop
udp dport @game_ports_udp accept
tcp dport 25565 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table ip mangle {
chain postrouting {
type route hook output priority mangle; policy accept;
# DSCP EF marking for game UDP traffic
udp sport { 27015, 2456-2458 } ip dscp set ef
}
}
Persisting Rules Across Reboots
iptables rules live in memory. They’re gone after a reboot unless you save them.
Debian and Ubuntu (iptables)
apt install netfilter-persistent iptables-persistent
iptables-save > /etc/iptables/rules.v4
systemctl enable netfilter-persistent
RHEL, CentOS, AlmaLinux (iptables)
iptables-save > /etc/sysconfig/iptables
systemctl enable iptables
systemctl start iptables
nftables (All Distros)
# Save your ruleset to the default config file
nft list ruleset > /etc/nftables.conf
systemctl enable nftables
systemctl start nftables
Verify persistence by rebooting and running iptables -L -v -n or nft list ruleset immediately after. If the DROP defaults aren’t there, your persistence method didn’t take.
Verification Checklist and Firewall Audit
Apply rules, then confirm they’re actually doing what you expect. Don’t assume.
- Run
iptables -L -v -nornft list rulesetand confirm DROP defaults on INPUT. - Check packet counters on DROP rules — non-zero counters confirm active filtering.
- Test from an external host:
nmap -sU -p 27015 YOUR_SERVER_IPshould show only your game port open. - Confirm RCON is not reachable externally:
nc -u YOUR_SERVER_IP 27020should time out. - Verify ipset ban list is loaded:
ipset list game_banlist. - Schedule a monthly audit: review DROP rule counters, rotate logs, and update the ban list from threat feeds.
FAQ: Linux Game Server Firewall
Does nftables replace iptables? Yes, nftables is the kernel-native successor. iptables is still widely supported, but new builds should use nftables for better performance and native set support.
What ports does a Minecraft server need open? TCP 25565 for gameplay. Never expose the RCON port (25575) publicly. Bind RCON to 127.0.0.1 and access it via SSH tunnel.
How do I protect a game server from DDoS with iptables? Use the hashlimit module to rate-limit UDP per source IP, create an ipset ban list for known bad actors, and tune nf_conntrack_max to prevent table exhaustion under flood conditions.
How do I make iptables rules persist after reboot? On Debian/Ubuntu, install netfilter-persistent and run iptables-save. On RHEL-based systems, save to /etc/sysconfig/iptables and enable the iptables service. For nftables, write rules to /etc/nftables.conf and enable the nftables systemd service.
Apply this ruleset, verify with nmap from an external host, then wire in fail2ban against your game server logs for dynamic ban list population. That’s the complete stack.

Clifford Robinson writes for Linux Rock Star, a blog dedicated to Linux and UNIX security. He specializes in creating high-quality content focused on system auditing, hardening, and compliance, aiming to make these topics accessible and actionable for system administrators, auditors, and developers. Clifford is passionate about providing valuable insights into Linux security, ensuring that the content is both informative and freely available to help readers secure their systems effectively.
Sorry, the comment form is closed at this time.