Protecting a FiveM server from attacks

Which ports a FiveM server needs, tuning the FiveM preset to your traffic, trimming /info.json, and stopping RCON and resource abuse.

Game servers12 min read

On this page
  1. Why FiveM servers are attacked so often
  2. The two things attackers actually go for
  3. The UDP game port
  4. Your CPU, through connection floods
  5. What to open, and what to leave closed
  6. Applying the FiveM preset
  7. Fit the limits to your own traffic
  8. Protocol validation on the FiveM rules
  9. What your server publishes, and why its size matters
  10. Response size is the part you control
  11. Abuse that no network filter can see
  12. RCON, and why a weak password is total compromise
  13. Malicious resources
  14. Your admin surfaces
  15. While you are under attack
  16. When to open a ticket
  17. 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.

PortProtocolOpen it?What it carries
30120UDPYesGame traffic. Every connected player.
30120TCPYesThe HTTP endpoints the server list reads, and the resource files a client downloads while joining.
40120TCPNotxAdmin's web interface. Reach it over an SSH tunnel instead.
3306TCPNoMySQL or MariaDB. The database belongs on localhost.
22 or 3389TCPAdministration onlySSH 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:

Shell
sudo ss -lntup | grep -E '30120|40120'

The ports come from the two endpoint lines in your server.cfg:

Config
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.

Servicesyour serverFirewallInbound rules

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:

Shell
sudo timeout 10 tcpdump -ni any 'udp dst port 30120' -w /dev/null

tcpdump 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.

Above your peak, with headroomThe busiest hour passes under it.Packets per second, relativeWhole port ceilingA day, your busy hour on the rightYour trafficBelow your real peakYour busiest hour runs into it.Packets per second, relativePlayers dropWhole port ceilingA day, your busy hour on the rightYour traffic
Where the ceiling belongs. Set above your own busiest hour, with room to grow, it never meets your players; set below it, the busiest hour runs into it, and that is when players drop out and new ones cannot join. Illustration: relative, not measured.

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:

Shell
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.json

Treat 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:

Shell
curl -s -o /dev/null -w '%{size_download} bytes\n' http://203.0.113.10:30120/info.json

Two things usually make that number larger than it needs to be:

  • An oversized server icon. FiveM expects icon.png in the server root to be a 96x96 PNG, and it is returned encoded inside every /info.json response. 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.
The requestsmall, and the same every timeReply, trimmedA 96x96 PNG icon, only the resources you runReply, untrimmedA full-size logo, and resources you do not runServer variables: name, descriptionEvery resource the server has startedThe server icon, embedded
The same small request, two replies. The reply carries your server variables, every resource you have started and the icon itself, so a full-size logo and a long resource list make every answer larger, while the request costs the sender the same. Illustration: proportions are not measured.

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:

Shell
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.
Shell
openssl rand -base64 24

Malicious 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 load or loadstring.
  • 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.lua refers to.

A first pass over a resource you are about to install:

Shell
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:

Shell
ssh -L 40120:127.0.0.1:40120 root@203.0.113.10

Then open http://127.0.0.1:40120 locally while that session is running.

Your computerBrowserhttp://127.0.0.1:40120SSH, listening on local port 40120ssh -L 40120:127.0.0.1:40120 root@203.0.113.10SSH, TCP 22Your server203.0.113.10SSHhands the connection to 127.0.0.1:40120txAdminon 127.0.0.1:40120The tunnel lasts as long as the SSH session that holdsit.
What the tunnel does. Your browser talks to port 40120 on your own computer; SSH carries that over to the server and hands it to txAdmin there, so 40120 never has to face the internet. Illustration.

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Need a server, or a hand with one?

Pick a plan to deploy a server, or open a ticket in the panel. Support runs 24/7/365.