Protecting RAGE MP and alt:V servers from DDoS attacks

Published on 15 min read

RAGE MP listens on 22005 UDP and 22006 TCP, alt:V on 7788. This guide shows step by step what you can secure yourself and from which point on only filtering in the network in front of the server still helps.

A GTA multiplayer server is a rewarding target for attackers: it sits on a single IP address, its port is published in a public server list, and every outage is visible to all players at the same time. This article first shows what you can genuinely achieve on your own server, and then, just as plainly, where those options end.

If you are not yet sure whether an attack is running at all, measure that first: Detecting a DDoS attack walks through the diagnosis step by step. The technical background is covered in What is a DDoS attack.

Why RAGE MP and alt:V servers get hit so often

The roleplay scene around GTA V is small, public and fiercely competitive. A server lives off its regular players, and after a longer outage those players are in a different Discord very quickly. That makes attacks attractive: nobody needs to keep it up for hours, a few minutes during peak time are enough, on opening night or during an announced wipe.

On top of that, nobody has to search for long. Both platforms will announce your server to a public server list if you want them to, RAGE MP through announce in conf.json, alt:V through announce and token in server.toml. Being listed there means publishing your IP address and port. A freshly listed server therefore often sees the first automated connection attempts within the first hour, long before the first real player arrives.

The third reason is technical: game traffic runs over UDP. UDP has no handshake that a sender would have to complete, so the source address can be forged. Anyone who knows your port can hammer it without ever getting a reply and without showing their own address.

The ports involved

Before you write your first rule, you should know which port does what. Both platforms need more than one.

ServicePortProtocolPurpose
RAGE MP, game traffic22005UDPclient connections to the game server
RAGE MP, client files22006TCPbuilt-in HTTP server, always the game port plus 1
alt:V, game traffic7788UDPclient connections to the game server
alt:V, client files7788TCPresource delivery, unless a CDN is used
SSH22TCPyour own administration, not for players
MariaDB, Redis3306, 6379TCPbelong on 127.0.0.1, not on the internet

Two details matter here. With RAGE MP the HTTP port is tied to the game port and is always the next one up: move the game port to 22015 and the file port moves along to 22016. With alt:V, game traffic and file delivery share the same port number, once over UDP and once over TCP. If you have the client files delivered through a content delivery network (options useCdn and cdnUrl in server.toml), you take the TCP part off your own uplink. Game traffic over UDP is not affected by that.

What you can do yourself before spending money

The steps below will not stop a volumetric attack, no software on the server can do that. What they do clear away is everything below that level: port scans, connection floods from a handful of sources, attacks on the database instead of the game, and abuse of your own file port. That is most of what disrupts a small server day to day, and it costs you half an hour.

Step 1: take stock of what is listening

ss -tulnp

The interesting column is the local address. Anything bound to 0.0.0.0 or [::] is reachable from the internet, anything on 127.0.0.1 only locally. On a typical roleplay server you quickly find a database, a cache, a web panel and sometimes a voice server next to the game itself. Each of these services is an attack surface of its own, and none of them has to be open just because it is running.

Step 2: restrict the firewall to the ports you actually need

For a RAGE MP server that means three rules: SSH, game port and file port. Always allow your SSH port first, otherwise the last line locks you out of your own server:

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 22005/udp
ufw allow 22006/tcp
ufw enable

For alt:V the two game rules read as follows instead:

ufw allow 7788/udp
ufw allow 7788/tcp

Afterwards check with ufw status verbose that only these ports are really open, and run ss -tulnp again. The full setup including IPv6 and the classic lockout traps is described in Setting up the UFW firewall.

Step 3: take the database and the cache off the network

With most gamemodes, MariaDB and Redis run on the same machine as the game server and therefore need no address on the internet. The MariaDB configuration (on Debian and Ubuntu /etc/mysql/mariadb.conf.d/50-server.cnf) needs this line:

bind-address = 127.0.0.1

And /etc/redis/redis.conf needs these:

bind 127.0.0.1 ::1
protected-mode yes

Then restart both services and check the result with ss -tulnp. An open cache without a password is not a DDoS problem, it is a way in, and it gets scanned around the clock.

Step 4: limit connection rates on the file port

The TCP port for the client files is the one place where rate limiting on the server actually pays off, because there is a real handshake here and therefore a source address you can halfway trust. Two rules are enough, shown here for RAGE MP on port 22006:

iptables -A INPUT -p tcp --dport 22006 --syn -m connlimit --connlimit-above 20 --connlimit-mask 32 -j DROP
iptables -A INPUT -p tcp --dport 22006 --syn -m hashlimit --hashlimit-name gtahttp --hashlimit-mode srcip --hashlimit-above 30/sec --hashlimit-burst 60 -j DROP

The first rule caps the connections open at the same time per source address, the second one caps the connection attempts per second. For alt:V, put 7788 in both places. Three notes on this: ufw limit is too coarse here and only knows TCP, you adjust the numbers to the size of your client files, and the rules only survive a reboot with iptables-persistent or as an entry in /etc/ufw/before.rules.

On the UDP game port the same technique achieves little, because the senders there are forged: a block by source address then hits nobody except, by chance, a real player. What you should keep an eye on instead is the connection tracking in the kernel:

cat /proc/sys/net/netfilter/nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

Once the first value approaches the second, the kernel drops packets regardless of whether they belong to an attack or to a player. The system log then shows nf_conntrack: table full, dropping packet.

Step 5: use what the two platforms already provide

Both server cores ship settings that are meant precisely for connection abuse, and out of the box they sit at their loosest value. With RAGE MP this concerns three keys in conf.json:

{
    "bind": "0.0.0.0",
    "port": 22005,
    "announce": true,
    "maxplayers": 200,
    "disallow-multiple-connections-per-ip": true,
    "limit-time-of-connections-per-ip": 1000,
    "enable-http-security": true
}

That is an excerpt, the remaining keys stay as they are. disallow-multiple-connections-per-ip prevents several simultaneous connections from the same address, limit-time-of-connections-per-ip enforces a minimum gap between two connection attempts (0 turns the limit off), and enable-http-security switches on the additional checks in the built-in HTTP server. Compare the time unit of the middle value with the documentation for your server version before you raise it. And expect the first option to lock out players who share one connection, so flatshares, families and company networks.

With alt:V the matching options live in server.toml:

host = '0.0.0.0'
port = 7788
players = 200
announce = true
duplicatePlayers = 4
connectionQueue = true
useEarlyAuth = true

duplicatePlayers limits how many players may be connected from the same IP address at once. The default value is 4096, which makes it no limit in practice. connectionQueue puts connection attempts into a queue instead of handling them all at once. useEarlyAuth places a login in front of the game server: the client has to log in before it reaches your game world, which sorts out simple connection floods from the start. The address of the login page goes in earlyAuthUrl.

Step 6: a whitelist as an emergency measure

If an attack runs through the game mechanics, meaning mass connection attempts rather than raw bandwidth, a whitelist is the most effective short-term measure. With alt:V, a password in server.toml is already enough for closed operation. In code, the simplest form looks like this, here for RAGE MP:

const whitelist = new Set(['PlayerOne', 'PlayerTwo']);

mp.events.add('playerJoin', (player) => {
    if (!whitelist.has(player.name)) {
        player.kick('The server is currently closed.');
    }
});

And the same logic for alt:V:

import * as alt from 'alt-server';

const whitelist = new Set(['PlayerOne', 'PlayerTwo']);

alt.on('playerConnect', (player) => {
    if (!whitelist.has(player.name)) {
        player.kick('The server is currently closed.');
    }
});

Both are deliberately kept simple and have one clear limit: the display name is not a strong identifier. If you run a whitelist permanently, check against the identifier from the upstream login or against your own account management instead. Above all: a kick only happens after the connection has reached the server. It does nothing against packets that are already filling the uplink.

Step 7: server list entry and IP hygiene

Turning off the server list entry (announce set to false) sounds like a quick fix and usually is not one. Anyone who already has your IP address still reaches you, and your players no longer find you. The step only makes sense together with a change of IP address, because only then does the attacker lose the target.

What pays off in the long run is tidiness in the places where the address becomes known in passing: run website and forum on a different machine, delete old DNS records (including mail, ftp and test names from the early days), do not run Discord bots and status displays from the game server, and separate the voice server. The address of a game server cannot be hidden completely, though: game traffic over UDP has to arrive directly at your machine, and a content delivery network in front of your website changes nothing about that. What helps here is not obfuscation, it is an address with filtering behind it.

Step 8: collect measurements before it gets serious

When it counts, what counts is what you can prove. Prepare the commands in advance that capture the incoming packet rate and the connection situation within seconds:

IF=$(ip -o route get 1.1.1.1 | awk '{print $5}')
A=$(cat /sys/class/net/$IF/statistics/rx_packets) || exit 1; sleep 1; B=$(cat /sys/class/net/$IF/statistics/rx_packets); echo "$((B-A)) packets/s incoming on $IF"
ss -s

Write these values down once during normal operation at peak time, because without a baseline every number during an attack is worthless. If your game server runs as a systemd service, journalctl -u <service-name> -n 200 belongs in the set as well: connection floods usually leave a clear trace there. One limitation you have to know about: on the server you only measure what got through. If filtering sits in front of it, the reliable number is in the traffic graph in the customer panel and not in /proc.

Where these measures end

Every rule on the server only takes effect after the packet has arrived. That is the decisive sentence. A firewall decides about packets that have already passed through your uplink, and that uplink is exactly what a volumetric attack targets.

The orders of magnitude behind this: a single server typically sits on 1 Gbps. With the smallest packets that works out to roughly 1.5 million packets per second, and physically nothing more fits through. Saturating that uplink takes no record attack, 2 to 5 Gbps are enough for it. For comparison, an attack actually measured in the KernelHost network in Frankfurt: more than 473.4 Gbps and more than 41.5 million packets per second against a single service. That is roughly 470 times a gigabit uplink, and even a 10 Gbps uplink is a factor of 47 away from it.

Once the uplink is full, the router in front of it already drops traffic, without regard for the individual packet. Your players then sit in the same queue as the attack. No iptables, no plugin and no stronger CPU changes that, because the bottleneck is in front of the server. On top of that, the source addresses in UDP floods are forged: there is simply nobody you could usefully block.

The only effective answer is therefore filtering that sits in the network in front of your uplink and has enough capacity there that the attack cannot saturate it.

What KernelHost puts up against this

The always-on protection that already runs on every server

At KernelHost (KernelHost GmbH, based in Vienna, Austria) two-layer DDoS protection is permanently active on every server, with no order, no configuration and no surcharge:

  • Layer 1: a global scrubbing network with 17 Tbps of mitigation capacity. Volumetric attacks are caught close to their source, before they even reach the datacenter.
  • Layer 2: Arbor real-time filtering with 3.2 Tbps. It sits on-premise in the maincubes datacenter in Frankfurt am Main (Germany) and does the fine-grained work directly in front of your server, packet by packet.

Just as important is what does not happen: there is no null-routing. Your IP address stays in the network during an attack, only the malicious packets are dropped. For a roleplay server that difference is considerable, because to your players a null-routed address is indistinguishable from a successful attack. If SSH no longer gets through during an incident, you can still reach the system through the VNC console in the customer panel, which works independently of the network connection of the server.

Advanced DDoS Protection for projects under constant attack

Some projects are not hit once, they are hit for weeks. For that case there is Advanced DDoS Protection from €50.00 a month, PrePaid and with no minimum term, no notice period, no contract and no setup fee. It includes:

  • a dedicated protected IP address from the Frankfurt core, which your server is switched to without any rebuild on your side,
  • protection rules that you manage yourself, per port and protocol, directly in the customer panel,
  • changes that take effect in real time, with no ticket and no waiting,
  • a protection profile matching the game in question, from more than 40 profiles for games, services and protocols, among them RageMP and alt:V, plus generic profiles for your own TCP and UDP applications.

The practical difference is control: you decide yourself which profile runs on 22005 UDP and which rule applies to 22006 TCP, even in the middle of an attack.

The two layers compared

FeatureIncluded always-on protectionAdvanced DDoS Protection
Activationactive out of the box, nothing to orderavailable as an add-on, protected IP right after ordering
Capacity17 Tbps global scrubbing plus 3.2 Tbps Arbor real-time filtering in Frankfurt am Mainthe same filtering infrastructure, plus a dedicated protected IP address from the Frankfurt core
Rule setmaintained by KernelHost, automaticadditionally manageable by you, per port and protocol in the customer panel
Protection profilesautomatic, optimized for gamesselectable by you, more than 40 profiles including RageMP and alt:V
How quickly changes take effectnot applicablein real time, with no ticket
Null-routing during an attacknono
Costincluded in every server package at no extra chargefrom €50.00 a month, PrePaid with no minimum term
Suitable forall projectsprojects under constant, targeted attack

Common mistakes and how to fix them

All ports open, because otherwise something does not work: that is almost always a misdiagnosis. Use ss -tulnp to note down which service needs which port, and open exactly those. If something is missing afterwards, it is usually a service that is bound locally anyway.

Blocking the attacker IP addresses: in a UDP flood the senders are forged. You end up blocking uninvolved addresses and, in the worst case, your own players. It only makes sense for TCP connections with a complete handshake, so on the file port.

Only setting announce to false: the server disappears from the list, but the IP address stays the same. A running attack continues unchanged, your players simply no longer find the server. Without a change of address the step achieves nothing.

Rate limiting on the UDP game port: mobile networks and company connections put many players behind a single address. A limit per source address throws real players out there, while the forged senders of the flood remain untouched.

More CPU and more RAM as an answer to DDoS: both help against an overloaded gamemode, not against a saturated uplink. The bottleneck is in front of the server, and stronger hardware changes nothing there.

Rebooting in the middle of an attack: it wipes every counter you would have needed for a solid report, and the attack simply continues afterwards. Collect the measurements first, then act.

Database open to the internet because the web panel runs on another machine: route the connection through an SSH tunnel or a private network. If that is not possible, at least restrict access to the one source address that really needs it.

If it is happening right now

Collect the measurements from step 8 first so that your report holds up: the time with time zone, the affected IP address and port, and the measured packet rate with the direction. Then open a support ticket. During a running attack you can also reach us on the WhatsApp emergency chat at +43 650 8209883. For the vendor-neutral overview of the further steps, see Protecting a server from DDoS attacks.

Frequently asked questions

Which ports do RAGE MP and alt:V really need?
RAGE MP uses 22005 UDP for the game traffic and 22006 TCP for the client files, and the HTTP port is always the game port plus 1. alt:V uses 7788 for both, once over UDP and once over TCP, unless the resources are delivered through a CDN. Everything else, above all the database and the cache, belongs on 127.0.0.1 and not on the internet.
My server is under attack right now, what helps immediately?
If the uplink is full, little helps on the server itself. First capture the incoming packet rate and the connection situation with ss -s, note the time with time zone, the affected IP address and the affected port, and report the incident with those values. If the attack runs through the game mechanics, meaning mass connection attempts, a whitelist or a password on the server helps in the short term.
Does it help to block the IP addresses of the attackers?
Not with UDP floods, because the source addresses are forged. You end up blocking uninvolved parties and, in the worst case, your own players. Blocks and rate limits only make sense where a connection is established completely, so on the TCP port for the client files.
Does it help to take the server out of the server list?
Only together with a change of IP address. announce set to false removes the entry, but the address stays the same, and anyone who already has it still reaches you. Your players then no longer find the server, while the attack continues unchanged.
Can I hide the IP address of my game server behind a CDN?
No. Game traffic over UDP has to arrive directly at the server, and a content delivery network can only sit in front of websites and files. What works instead is an address with filtering behind it, for example a dedicated protected IP address. It still makes sense to run website, forum, Discord bot and voice server on a different machine.
Why is a firewall on the server not enough against DDoS?
Because every rule only takes effect after the packet has arrived. With the smallest packets an uplink of 1 Gbps is full after roughly 1.5 million packets per second, and 2 to 5 Gbps are already enough to saturate it. Once the uplink is saturated, the router in front of it drops the packets from your players as well.
I can no longer reach the server over SSH, how do I get to it?
Through the VNC console in the customer panel. It works independently of the network connection of the server and keeps working when the uplink is saturated and no SSH connection is established any more.
What does DDoS protection cost at KernelHost?
The two-layer always-on protection is included in every server package at no extra charge: 17 Tbps of mitigation capacity in the global scrubbing network and 3.2 Tbps of Arbor real-time filtering in Frankfurt am Main. For projects under constant attack there is additionally Advanced DDoS Protection with a dedicated protected IP address and self-managed rules from €50.00 a month, PrePaid with no minimum term.

RAGE MP alt:V GTA multiplayer Game server DDoS protection UDP flood Firewall Real-time filtering Advanced DDoS Protection