On this page
- Why FiveM servers are attacked so often
- The two things attackers actually go for
- The UDP game port
- Your CPU, through connection floods
- What to open, and what to leave closed
- Applying the FiveM preset
- Fit the limits to your own traffic
- Protocol validation on the FiveM rules
- What your server publishes, and why its size matters
- Response size is the part you control
- Abuse that no network filter can see
- RCON, and why a weak password is total compromise
- Malicious resources
- Your admin surfaces
- While you are under attack
- When to open a ticket
- Related
A FiveM server is a public UDP endpoint with a name attached to it, which is why attacks on one are routine rather than remarkable. Two things get aimed at: the UDP game port, and your server's CPU through floods of connection attempts and HTTP requests. This page covers what to open, how to size the protection settings around your own traffic, and the abuse that arrives on ports you opened deliberately and no packet filter can see.
If you have not set your server up yet, start at Installing FiveM and come back.
Why FiveM servers are attacked so often
Nothing about it is personal or sophisticated.
- Your address is published on purpose. The server list exists so players can find you. Anyone reading it has your IP and your port, so keeping the address quiet is not a defence you have.
- The target is small and the effect is immediate. A roleplay community notices a few seconds of packet loss during an event. An attacker does not need to take the machine offline to empty your server, only to make it feel bad for long enough that people leave.
- Attacks are bought, not built. Booter services sell UDP floods by the minute. The people using them against a FiveM server are usually a rival community, someone who was banned, or someone running an extortion attempt, and none of them need any skill.
- The port answers unauthenticated traffic. It has to. A player who has never connected before must be able to send the first packet, so "only let known players in" is not available at the network layer.
The two things attackers actually go for
The UDP game port
FiveM's game traffic is UDP, on port 30120 by default. UDP has no handshake, so a source address in a packet header proves nothing, and a flood aimed at that port arrives looking broadly like players: same protocol, same port, plausible packet sizes. Volume alone does not separate the two.
This is why every ceiling in the protection settings is counted in packets per second rather than bandwidth, and why what really separates a player from an attacker is whether the traffic behaves like the game's protocol. How protection works explains both layers and the vocabulary the rest of this page uses.
Your CPU, through connection floods
The second target does not need much bandwidth at all. FXServer runs your game logic on a main thread, and work that arrives faster than that thread retires it becomes hitch: rubber-banding, delayed events, players timing out on join.
Connection establishment is the expensive part. Every join attempt costs a
handshake, requests to your server's HTTP endpoints, and resource files sent to
the client. A flood of joins that never complete costs the attacker almost
nothing and costs you real CPU, and it never has to look volumetric. The same is
true of repeated requests to /info.json, which is covered below.
When the symptom is the server itself falling behind rather than traffic being dropped, the fix is on the server: Server thread hitch warnings and Optimising a FiveM server.
What to open, and what to leave closed
A default FiveM install needs two ports, both numbered 30120. Rules are per protocol, so that is two rules, not one.
| Port | Protocol | Open it? | What it carries |
|---|---|---|---|
| 30120 | UDP | Yes | Game traffic. Every connected player. |
| 30120 | TCP | Yes | The HTTP endpoints the server list reads, and the resource files a client downloads while joining. |
| 40120 | TCP | No | txAdmin's web interface. Reach it over an SSH tunnel instead. |
| 3306 | TCP | No | MySQL or MariaDB. The database belongs on localhost. |
| 22 or 3389 | TCP | Administration only | SSH or RDP. See Connecting to your server. |
"No" in that table means "do not add a rule opening it", which is not the same
as closing it. Inbound rules are an allow-list, and what happens to a port with
no rule of its own is decided by Default for unlisted ports on the Firewall
tab: under Allow it stays reachable and is filtered by the always-on
protections, and under Deny all it is dropped. See
The Firewall tab. So the controls that
actually keep those two ports off the internet are on the server itself: bind
MySQL to 127.0.0.1 and reach txAdmin through the SSH tunnel described below.
Confirm what your server actually listens on rather than trusting the defaults. On Linux:
sudo ss -lntup | grep -E '30120|40120'The ports come from the two endpoint lines in your server.cfg:
endpoint_add_tcp "0.0.0.0:30120"
endpoint_add_udp "0.0.0.0:30120"If you changed them, every rule below applies to your numbers, not to 30120. See The server.cfg file.
Adding the rules themselves, the 15-rule cap, and what happens when you edit or delete one are on Port rules.
Applying the FiveM preset
The panel ships a FiveM preset so you do not have to build the two rules by hand.
It writes a TCP 30120 rule and a UDP 30120 rule. The UDP rule arrives with an aggregate packet-rate ceiling on it and the TCP rule arrives with none. The exact values it ships with, and what applying it does and does not change, are on Game presets. Three things from that page are worth carrying in your head before you press the button:
- Applying a preset adds rules. It never replaces or resets anything, and applying it twice writes a second copy of each rule.
- The preset's rules are for port 30120. If your server runs somewhere else, edit the rules after applying rather than leaving two rules pointed at a port nothing is listening on.
- Read your rules table afterwards. What is in the table is what is in force.
Fit the limits to your own traffic
A preset is sized for a typical FiveM server. Yours is not typical: player count, the size of your resource set, and how much your scripts talk all move the numbers. The ceiling that matters is the one that sits comfortably above your own busy hour, and only you can measure that.
Sample the inbound packet rate on the game port during your busiest period, on the server itself:
sudo timeout 10 tcpdump -ni any 'udp dst port 30120' -w /dev/nulltcpdump prints the number of packets captured when it stops. Divide by 10 for
packets per second inbound. Run it more than once, at your peak rather than at
3am, and take the highest figure you see as your floor.
Then open the rule and set Whole port, packets/sec (pps_limit) above that
peak with headroom for growth. The per-connection ceiling, Per connection,
packets/sec (estab_flow_pps), applies to one established connection and only
takes effect when an aggregate limit is also set. What each field bounds, and
what a value of 0 means in each of them, is on
Rate limits.
Protocol validation on the FiveM rules
Most preset rules arrive with Protocol validation (L7) (l7_validation)
switched on, and a rule you add by hand has it off whichever service you pick.
Two FiveM servers can therefore end up with the protocol layer on or off purely
by which route created the rule, so check the switch on any rule you added
yourself. What it catches, what it costs you when an unusual client trips it, and
the three engine switches next to it are on
Protocol validation.
What your server publishes, and why its size matters
FXServer answers HTTP on the TCP side of the game port. Those endpoints are unauthenticated by design, because the server browser needs to read them without being a player. Look at your own:
curl -s http://203.0.113.10:30120/info.json | head -c 500
curl -s http://203.0.113.10:30120/players.json
curl -s http://203.0.113.10:30120/dynamic.jsonTreat everything those return as public. /info.json carries your server
variables, including the name and description you set, your list of running
resources, and your server icon embedded in the response. /players.json carries
who is connected and the identifiers your build exposes for them. /dynamic.json
carries the short summary the server list shows.
Response size is the part you control
A request for /info.json is a few hundred bytes and costs whoever sends it
almost nothing. The response is whatever you have made it, and you pay for it
every time, in CPU to assemble it and in bandwidth to send it. That asymmetry is
the point: a small request that pulls a large response is worth repeating, and an
attacker repeating it is spending far less than you are.
Measure what one request costs you:
curl -s -o /dev/null -w '%{size_download} bytes\n' http://203.0.113.10:30120/info.jsonTwo things usually make that number larger than it needs to be:
- An oversized server icon. FiveM expects
icon.pngin the server root to be a 96x96 PNG, and it is returned encoded inside every/info.jsonresponse. People routinely drop a full-size logo in instead, and then send that logo to everything that asks. Re-export it at 96x96 and keep the file small. - A long resource list. Every resource your server has started is named in the response. Stopping resources you do not actually run shortens it, and it saves memory and CPU too. See Optimising a FiveM server.
Keeping the description short helps for the same reason. None of this stops a determined attack on its own, and it is not a substitute for the port rules. It lowers what each request costs you, which lowers what an attacker gets back for each one they send, and it makes the endpoint cheaper to serve to the legitimate server browsers hitting it all day.
Abuse that no network filter can see
Everything above is about packets. The attacks below arrive inside traffic that is valid for the protocol, on a port you opened deliberately, from a source that looks like a player. Prism judges packets, so it cannot judge these, and what "protected" means is worth reading with that in mind.
RCON, and why a weak password is total compromise
rcon_password in your server.cfg turns on remote console access. RCON runs
server console commands, which is the same power as sitting at the console: start
and stop any resource, read every convar including your database credentials and
your license key, execute config files, hand out admin, and shut the server down.
There is no partial version of it. Guessing that password is owning the server.
There is no separate administrative port to firewall off here, and an attempt against RCON arrives inside traffic your server is meant to answer. The password is the whole boundary.
Check what yours is set to:
grep -in 'rcon_password' server.cfg- If you do not use RCON, do not set a password. A commented-out line is nothing to brute force.
- If a tool needs it, generate one that will not be guessed, use it nowhere else, and change it if it has ever been shared.
openssl rand -base64 24Malicious resources
The most common way a FiveM server is taken over is not a flood. It is a script the owner installed. A server-side resource runs with the same rights as every other server script, so a backdoored one can read your convars, wipe your database, trigger any event, grant in-game power to whoever it answers to, and report your server to a drop point so somebody knows it is worth coming back to.
Leaked or reuploaded paid scripts are where this overwhelmingly comes from. What to look for before you start one:
- Obfuscated Lua, long base64 or hex blobs, and code assembled at runtime with
loadorloadstring. - HTTP calls to a host you do not recognise. Legitimate resources do use
PerformHttpRequest, for Discord webhooks among other things, so this needs reading rather than a verdict. - Files that no line in
fxmanifest.luarefers to.
A first pass over a resource you are about to install:
grep -rniE 'loadstring|PerformHttpRequest|base64|assert\(load' resources/Expect false positives and read what it finds. The panel also publishes a hosts file of known backdoor callback domains you can apply on the server itself; what it blocks, what it cannot block, and how to apply it are on Backdoor sinkhole. That tab appears only once the server has an active FiveM inbound rule.
Your admin surfaces
txAdmin exposed to the internet with a weak password is the same total compromise as a guessed RCON password, reached through a browser. Keep it off the public internet and reach it through an SSH tunnel from your own machine:
ssh -L 40120:127.0.0.1:40120 root@203.0.113.10Then open http://127.0.0.1:40120 locally while that session is running.
In-game admin commands need the same care in the other direction: a command that checks permission on the client is not a permission check at all. Gate them server side. Developing on a FiveM server covers where that line sits.
While you are under attack
Players failing to connect during an attack has two possible causes, and they need opposite responses: the attack is reaching your server, or your own settings are dropping your players. Find out which before you change anything.
Check whether your own settings are the cause
Take the public IP of one affected player and run Address lookup on the Attacks tab. It reads the exact drop ledger and names what dropped that address. The full ordered checklist, cause by cause, is When players cannot connect.
Allow for the mid-attack blind spot
During a wave the drop ledger has not published yet, so a lookup run while the attack is in progress can come back empty. A was not filtered result mid-attack is not conclusive. Run it again once the attack ends.
Change one thing at a time
Every change applies to live traffic and takes a moment to reach the filter. Make one change, retest with a real player, then make the next. Panic-lowering three ceilings at once means you will not know which one mattered, and a ceiling below your real peak drops the players you still have.
Check the server itself, not only the traffic
If the console is hitching and CPU is pinned, the problem may be work your server is doing rather than traffic being dropped. See Server thread hitch warnings.
Write down what you saw
The incident ID from the Attacks tab, the affected source address, the port and protocol, the time it happened, and the exact line Address lookup returned. Those five things are what a ticket needs to become an answer.
When to open a ticket
Open one when the lookup says a player who had completed a valid session was dropped, when it names a check that has no control on the Firewall tab, or when it keeps returning was not filtered while players still cannot reach a server you have confirmed is running. The lines "Country is blocked" and "Network (ASN) is blocked" always belong in a ticket, because no control on your side produces them.
Include the five things from the step above. See Opening a ticket.
Related
What the FiveM preset writes, and what applying it twice does.
Rate limitsChoosing a ceiling from your own peak rather than from an attack.
When players cannot connectThe ordered checklist for finding which setting is dropping real players.
Optimising a FiveM serverReducing the work your server does, which is half of surviving a flood.