Protecting a Terraria server from DDoS attacks
Why Terraria speaks TCP only, which ports the server really needs, how to harden serverconfig.txt, TShock and the REST API on 7878, and from which attack size on only upstream filtering helps.
If you want to protect a Terraria server from DDoS attacks, you are dealing with a special case: Terraria speaks TCP only. The game traffic runs over exactly one port, 7777 TCP, and the game opens no UDP port at all. Almost every piece of game server protection advice you find online is written for UDP games, so it either does nothing here or works on the wrong layer.
This article starts with what you can secure yourself at no extra cost, then shows where those measures technically end, and finally explains what has to happen in the network in front of the server. Everything here refers to a Terraria dedicated server (vanilla, TShock or tModLoader) on Debian 12, Debian 13, Ubuntu 22.04 LTS or Ubuntu 24.04 LTS. The commands are written for root. As a normal user, put sudo in front of them. If the attack is running right now, change nothing in the configuration and do not reboot the server: capture the measurements first (see the "Logging" section), because once the attack is over they are gone.
Why Terraria servers get hit by DDoS attacks so often
Terraria servers are a convenient target because their address is inevitably public. Vanilla Terraria has no built-in server browser: players connect through "Multiplayer" and "Join via IP", so through an address that somebody had to publish first. If you want new players, you list the server on directories such as terraria-servers.com, tserverweb.com or topg.org, or you hand the address out through Discord. Every one of those routes gives an attacker exactly what it gives a player: the IP address and the port in plain text.
So if a Terraria server keeps going offline although nothing changed about the hardware, the world or the mod list, an attack is the most likely explanation. On top of that comes the usual situation of a project: fixed playing hours, competing servers, banned players and community disputes. An attack costs whoever orders it neither skill nor any serious amount of money, and a Terraria server booter is sold as a subscription for a few euros a month. For the details of what a DDoS attack actually is and how it is assembled, read What is a DDoS attack?.
Terraria runs over TCP, not over UDP
This is the most important difference from practically every other game server. The Terraria dedicated server accepts connections through a TCP listener (in the engine, the class Terraria.Net.Sockets.TcpSocket) and opens no UDP socket. That has four consequences, and they shape your entire defense:
- A fully established TCP connection cannot be spoofed. The attacker has to receive the server's SYN-ACK to complete the handshake. So anyone who is actually connected comes from a real address. IP bans and connection limits work considerably better on Terraria than on a UDP game.
- A SYN flood can be spoofed, because it never completes the handshake. No IP ban helps against that kind, only SYN cookies and filtering upstream.
- Every accepted TCP connection to port 7777 consumes resources inside the game process, not just in the kernel. That makes slot exhaustion the most effective attack with the least bandwidth.
- A UDP flood still hits your server. The packets do not have to be accepted in order to fill your uplink. The fact that Terraria does not speak UDP protects the application, not the line.
There is one exception: if you start the dedicated server with -steam and -lobby friends or -lobby private, the connection runs through the Steam network and therefore over UDP ports in the 27000 to 27100 range. That is a different operating mode and not the classic server reachable by IP address.
The ports that actually matter
A Terraria server needs exactly one port on the open internet: 7777 TCP. Everything else in this table either has no business on the internet at all or belongs behind a rule that allows only your own address.
| Purpose | Port | Protocol | Where it is set | Open to the internet? |
|---|---|---|---|---|
| Terraria game traffic | 7777 | TCP | serverconfig.txt: port=7777 |
yes, the only one |
| Terraria over UDP | none | none | the game opens no UDP socket | no |
| Query / status port | none | none | vanilla Terraria has no query protocol of its own | no |
| RCON | none | none | Terraria has no RCON, remote control only through TShock | no |
| TShock REST API | 7878 | TCP | tshock/config.json: RestApiPort |
no |
| tModLoader server | 7777 | TCP | the same serverconfig.txt |
yes, the only one |
Steam mode (-steam -lobby) |
27000 to 27100 | UDP | only in Steam operating mode | no |
| Pterodactyl Wings | 8080 | TCP | panel daemon | no, your own address only |
| Pterodactyl SFTP | 2022 | TCP | panel SFTP | no, your own address only |
| SSH | 22 | TCP | /etc/ssh/sshd_config |
your own address only |
The fact that Terraria has neither a query port nor RCON is good news for hardening it: the two endpoints that are regularly abused for reflection attacks on Counter-Strike, Rust or ARK simply do not exist here. In exchange, the attack surface is concentrated on port 7777 all the more, and anyone running TShock adds a second surface on port 7878.
What you can do yourself before spending money
This section is the longest one, and that is deliberate. A cleanly configured Terraria server survives small and medium attacks under its own power, no matter who hosts it.
1. Take stock: what is listening at all?
Before you write a single rule, check what your server actually offers to the outside. Do not guess, look:
ss -lntup
The interesting column is the local address. 0.0.0.0:7777 means "reachable from the entire internet", 127.0.0.1:7878 means "local only" and needs no firewall rule. If a UDP entry shows up for your Terraria process in that list, the server is running in Steam mode. A port scan from outside gives you the attacker's view:
nmap -Pn -p- --min-rate 1000 YOUR.SERVER.IP.ADDRESS
2. Leave 7777 TCP open and close everything else
A single rule facing the outside is enough for Terraria. You do not need a UDP rule, and a UDP rule for 7777 would simply be wrong: it lets traffic through to a port where nothing is listening. With UFW it looks like this, and in exactly this order so that you do not lock yourself out:
ufw allow 22/tcp comment 'SSH'
ufw allow 7777/tcp comment 'Terraria'
ufw allow from 203.0.113.10 to any port 7878 proto tcp comment 'TShock REST'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose
Replace 203.0.113.10 with your own address. The full guide including the escape route is in Setting up the UFW firewall without locking yourself out. If you run a panel, restrict 8080 and 2022 to your own address as well.
3. serverconfig.txt: set password, maxplayers and secure correctly
The central configuration file of a Terraria server is called serverconfig.txt and is handed over at startup with -config serverconfig.txt. Four directives decide how well the server holds up:
port=7777
maxplayers=16
password=ALongRandomPassword
secure=1
upnp=0
banlist=banlist.txt
password= is the most effective free measure against join floods that use the regular path. The reason lies in the protocol: a client first sends message 1 with its version identifier (for example Terraria279), the server answers with message 37 if a password is set, the client has to answer correctly with message 38, and only then does the server send message 3 with the approval and the player slot. So without the correct password an attacker never reaches the world transfer, which is the expensive part of a join.
maxplayers takes values from 1 to 255, and the default is 16 (it was 8 before version 1.4.0.1). The upper limit of 255 is not an arbitrary number: Terraria addresses players with a single byte. Do not set maxplayers higher than you really need, because every slot is a resource an attacker can occupy. secure=1 enables the built-in cheat protection (on the command line -secure), and upnp=0 stops the server from opening ports on a router by itself.
4. Harden TShock: the REST API on 7878 and login floods
TShock is the most widely used server extension for Terraria, and its REST API adds a second, fully featured attack surface. It sits on port 7878 TCP by default and is configured in tshock/config.json, not in serverconfig.txt. Out of the box it is switched off ("RestApiEnabled": false), and that is exactly how it should stay as long as you do not need it.
If you do need it, these values matter:
"RestApiEnabled": true,
"RestApiPort": 7878,
"EnableTokenEndpointAuthentication": true,
"LogRest": true,
"RESTMaximumRequestsPerInterval": 5,
"RESTRequestBucketDecreaseIntervalMinutes": 1
Two things about this are important. First, the /status endpoint serves the server name, the port, the player count and the player names without a token as long as EnableTokenEndpointAuthentication is false. That is convenient for status pages and Discord bots, and it is free reconnaissance for anyone who wants to know when an attack is worth the effort. Second, the /v2/token/create endpoint turns a username and a password into an access token, and it is reachable from outside as soon as port 7878 is open: a password guessing attack against your admin account that costs processing time on the side. The bucket built from RESTMaximumRequestsPerInterval and RESTRequestBucketDecreaseIntervalMinutes slows that down, but it does not replace a firewall rule.
Further TShock values apply to the game access itself. MaximumLoginAttempts is 3 and kicks a player after three failed attempts. RequireLogin (default false) requires an account for every player. EnableIPBans (default true) and KickProxyUsers (default true) are particularly effective on a TCP game, because the source address of an established connection genuinely cannot be spoofed. Against griefing, which often gets reported as an attack, the thresholds TileKillThreshold (60), TilePlaceThreshold (20), TileLiquidThreshold (15) and ProjectileThreshold (50) apply, each of them actions per second.
5. Limit connections per source address and check SYN cookies
Because Terraria runs on TCP, the most effective local rule is a cap on simultaneous connections per source address. A real player needs exactly one:
iptables -I INPUT -p tcp --dport 7777 --syn -m connlimit --connlimit-above 3 --connlimit-mask 32 -j DROP
iptables -I INPUT -p tcp --dport 7777 --syn -m hashlimit --hashlimit-name terraria_syn --hashlimit-mode srcip --hashlimit-above 10/min --hashlimit-burst 20 -j DROP
The first rule drops new connections as soon as one address holds more than three of them open at the same time. The second caps the rate of connection attempts from the same source at ten per minute with a burst of 20. Both numbers are starting points, not truths: a server behind a shared connection (a flat share, a school network, a mobile carrier) sees several legitimate players under the same address. Measure a week of normal operation first.
Plain iptables rules are gone after a reboot, and on Debian and Ubuntu you save them like this:
apt-get install -y iptables-persistent
netfilter-persistent save
Under UFW, such rules belong in /etc/ufw/before.rules, because otherwise they disappear with the next ufw reload. None of these rules help against spoofed SYN packets that never complete the handshake: that is the kernel's job. Check three values:
sysctl net.ipv4.tcp_syncookies net.ipv4.tcp_max_syn_backlog net.core.somaxconn
net.ipv4.tcp_syncookies has to be 1, which is usually already the case on Debian and Ubuntu. SYN cookies do away with the queue of half-open connections and reconstruct the state from the client's answer, so a SYN flood runs into nothing as long as the uplink is not full. net.core.somaxconn has been 4096 since Linux 5.4 and was 128 before that: if the value is small, the kernel drops finished connections before the game process can even accept them.
6. Prevent slot exhaustion: why a port scan fills your server
Slot exhaustion is the cheapest effective attack on a Terraria server: the attacker opens as many TCP connections to port 7777 as the server has player slots and holds them open. That costs almost no bandwidth, yet it fills the server. Real players see "Server is full" and cannot get in, even though nothing unusual is happening on your uplink. This is precisely why Terraria operators often do not notice that they are under attack.
The cause lies in the way slots are counted: a connection is accepted before the client has even sent its version identifier. Historically such ghost connections stayed occupied until the TCP session timed out. The 1.4.5 line eased that, and servers no longer reserve slots for clients that connect and immediately disconnect. In the initial builds of 1.4.5.7 and 1.4.5.8, however, the dedicated server crashed with an unhandled ObjectDisposedException as soon as a TCP connection was opened without completing the handshake. An nc -z or a reachability check from a monitoring system was enough. The bug was quietly fixed within a couple of weeks, but older container images still carry it. Keep your server version current, because here that is not a platitude, it is a concrete availability question.
Two settings help on top. If you run TShock, set MaxSlots to the player count you want and set maxplayers in serverconfig.txt two slots higher: TShock then rejects surplus connections with a clean message instead of letting the game process squeeze them into the last gap. And the connection cap from the previous section is exactly the rule that stops a single address from occupying every slot at once.
7. Switch off UPnP and do not publish the address yourself
By default the Terraria server tries to open its port on a router through UPnP. On a rented server that has no effect, and on a home network it opens ports you will have forgotten about later. Switch it off with upnp=0 in serverconfig.txt or with -noupnp on the command line.
Honesty also beats wishful thinking here: your IP address cannot be kept secret. Every player who has connected once knows it, and a directory entry publishes it anyway. Two habits are effective. Never publish the raw IP address yourself, and connect your players through a hostname instead: the Terraria client resolves a hostname, so you can change the address if it comes to that without breaking every reference. And clean up old DNS records, because a forgotten A record pointing at the previous address makes any change pointless.
8. Cache status queries instead of passing them through
Because Terraria has no query protocol, status pages, Discord bots and directory sites determine the state of your server in one of two ways: they open a real TCP connection to 7777 and pretend to be a client, or they query the TShock REST API. Both cost your server work, and both scale with the number of people asking.
The countermeasure costs nothing: never query from the visitor's browser. Let a single service fetch the status at fixed intervals (30 or 60 seconds is plenty), cache the result and serve every visitor the cached state. That way a busy status page produces one query per interval instead of one per visitor. If you use the REST API for it, restrict port 7878 to the address of that one service.
9. Logging, so that you have data when it counts
The most important step is the one almost nobody takes beforehand: build a baseline while everything is still normal. Without a normal value you cannot say after an incident whether 40,000 packets per second was a lot or simply a Saturday evening. With apt-get install -y vnstat sysstat the measurement runs permanently in the background. During an incident five commands are enough:
sar -n DEV 1 10
ss -s
ss -tn state syn-recv | wc -l
ip -s link show eth0
tcpdump -ni eth0 tcp port 7777 -c 200 -q
The third command is the Terraria-specific one: it counts the half-open connections. A two-digit value is normal, a four or five-digit one is a SYN flood. ss -s shows the total number of TCP connections next to it, and if that number roughly matches your maxplayers while nobody is in the game, you are looking at slot exhaustion. One rule for tcpdump: always cap it with -c, because a capture under full load puts extra strain on a server that is already overloaded. How to read the numbers is covered in Detecting a DDoS attack.
Where these measures stop
Now the part that no configuration file can solve. Everything so far runs on your server, which means at the far end of the uplink. A firewall rule decides about a packet that has already traveled down the wire. You can drop it, but you cannot un-send it.
Do the math once. A typical game server sits on 1 Gbps, which is 125 megabytes per second, and the uplink is full as soon as somebody sends more. Attacks against game server projects of this size usually range between 5 and 50 Gbps, so five to fifty times your uplink. Whether your connlimit rule behind it is any good no longer matters, because the packets of your players stop getting through before that. This is exactly how Terraria server lag spikes arise while the CPU utilization looks perfectly normal.
The second figure is the packet rate, and it often hits earlier than the bandwidth does. With small packets of 64 bytes, around 1.49 million packets per second fit into an uplink of 1 Gbps. Depending on CPU and network card, a normal server kernel handles a few hundred thousand of them before it starts dropping. With a SYN flood the limit is lower still, because every SYN packet triggers a state decision: a few tens of thousands of SYN packets per second are enough to paralyze connection acceptance on a stock Linux, long before the uplink is full. Operators experience this as "the utilization was not even high, and yet everything was gone".
And the third point is the one most often overlooked on Terraria: an attacker does not care about your protocol. He sends UDP floods and reflection traffic at your address even though nothing is listening on any UDP port. Your server drops those packets correctly, but they have already taken up your uplink, and your Terraria server goes offline without a single packet ever reaching the game process. For a sense of the magnitudes that really occur: on KernelHost servers we have filtered, among others, an attack of over 473.4 Gbps at over 41.5 million packets per second, and a UDP flood of over 112.2 Gbps against a game server. There is no local setting for that. Volumetric attacks have to end in the network in front of the server.
What KernelHost puts up against it
The always-on protection included with every server
DDoS protection at KernelHost is built in two layers and permanently active, with nothing for you to switch on, order or configure:
- Layer 1: 17 Tbps of mitigation capacity in the global scrubbing network. Volumetric attacks are scrubbed close to their source, before they reach the datacenter.
- Layer 2: Arbor real-time filtering with 3.2 Tbps in Frankfurt am Main. Directly in front of the server, protocol-specific patterns are detected and dropped, packet by packet. For Terraria that means SYN floods and connection floods against 7777 TCP end there, not on your network card.
Two properties make the difference. The protection runs permanently and does not have to react to an attack first, so there are no opening minutes in which the server is gone. And no null-routing is used: your IP address stays on the network, only the malicious packets are dropped. Whoever takes the IP address off the network achieves the same result for you as the attacker does. The location is Frankfurt am Main. Which games and protocols are covered is listed in Game server DDoS protection with real-time filtering.
Advanced DDoS Protection for projects under constant fire
Some projects are attacked not occasionally, but deliberately and for weeks on end. For those there is Advanced DDoS Protection from EUR 50.00 per month, PrePaid, with no minimum term and no setup fee. The difference is not more capacity, it is control:
- A dedicated protected IP from the Frankfurt core, which your server is switched over to inside our own network. Nothing has to be rebuilt on your side.
- Self-managed protection rules per port and protocol in the customer panel: you define what is allowed on 7777 TCP and you can close everything else, without writing a ticket for it.
- Changes take effect in real time, so you can fine-tune while an attack is running, for example by tightening the permitted connection rate per source address.
- A protection profile that matches the application. There are profiles for TCP games such as Terraria and for custom or modified applications on any TCP or UDP port.
The two tiers compared
| Feature | Included always-on DDoS protection | Advanced DDoS Protection |
|---|---|---|
| Price | included in every server package, at no surcharge | from EUR 50.00 per month, PrePaid |
| Filtering capacity | 17 Tbps of global scrubbing plus Arbor real-time filtering with 3.2 Tbps in Frankfurt am Main | the same two-layer filtering |
| IP address | the IP address of your server | an additional dedicated protected IP |
| Rule set | automatic profiles, no configuration needed | your own rules per port and protocol in the customer panel |
| Changes | are applied automatically | take effect in real time, even during an attack |
| Profile for Terraria | automatic profile for TCP game servers | your own rule set for 7777 TCP, also for tModLoader and TShock |
| Null-routing | no | no |
| Term | tied to the server package | PrePaid, no minimum term, no notice period, no setup fee |
For most Terraria projects the included always-on protection together with a clean server configuration is enough. Advanced DDoS Protection is the answer to somebody taking it personally. If your server currently runs somewhere else, the protection cannot be retrofitted onto it: the filtering is part of the network, not an add-on on the server. In that case the recommendation is to move to KernelHost.
Common mistakes and how to fix them
"The server is full, but nobody is in there": that is slot exhaustion. Use ss -tn dst :7777 | wc -l to check how many connections are actually open and compare it with the player list (server console: playing). If the numbers do not match, foreign connections are occupying the slots. The remedies are a connection cap per source address, a server password and a current server version.
"I opened 7777 UDP and nothing changed": correct, because nothing is listening on 7777 UDP. Terraria uses TCP exclusively. The UDP rule does no direct harm, but it is an unnecessary opening and a reliable sign that a guide for a different game was copied.
"My iptables rules have no effect": three causes are common. The rules sit behind the UFW chains and are never reached, they were gone after the last reboot (then netfilter-persistent save or an entry in /etc/ufw/before.rules helps), or the attack is volumetric and the rule works correctly on an uplink that is already full. Use iptables -L INPUT -n -v to check whether the hit counters are rising. If they stay at zero, the rule is never reached.
"Players get dropped even though no attack is running": if you set your connlimit threshold too tight, it hits players behind shared connections. On TCP that happens faster than on UDP games, because a reconnect after a hiccup immediately creates a new connection while the old one is still sitting in TIME_WAIT. Raise the value step by step and watch the hit counters.
"The server stutters while the uplink is quiet": that is more often a mod or a plugin than an attack. Under tModLoader every additional mod costs processing time in the same process, and a world with many entities can saturate a single core without a single excess packet arriving. If sar -n DEV 1 10 stays unremarkable, it was not a DDoS attack.
"My previous provider blocked my IP address": that is null-routing. The provider protects its own network with it, and for you the result is identical to a successful attack, usually for hours afterwards. If in doubt, ask whether traffic is filtered or null-routed. The answer says more about your availability than any hardware spec.
"I do not see anything unusual in tcpdump": if the traffic is already filtered in the network upstream, nothing arrives on the server, exactly as expected. That is the normal case when the filtering works. The other way round applies as well: once the uplink is saturated, even the SSH session you wanted to measure with may no longer reach you. Use the VNC console in the customer panel then, which works independently of the network of the guest system.
In short
- A Terraria server needs exactly one open port: 7777 TCP. The game opens no UDP socket, has no query protocol and no RCON.
- The TShock REST API on port 7878 TCP is the second attack surface. Leave
RestApiEnabledatfalseor restrict the port to your own address. - A server password in
serverconfig.txtis the most effective free measure, because without a correct answer to message 37 an attacker never reaches the world transfer. - Slot exhaustion is the cheapest attack on Terraria: every accepted TCP connection to 7777 takes a slot, with no meaningful bandwidth involved. A cap per source address, a password and a current server version work against it.
- Because Terraria uses TCP, the source address of an established connection cannot be spoofed, so IP bans work better here than on UDP games. Against spoofed SYN floods only SYN cookies and upstream filtering help.
- A UDP flood takes your Terraria server down even though it speaks no UDP, because it fills the uplink before the game process sees anything at all.
- From roughly the size of your uplink bandwidth onwards, only the network in front of the server decides the outcome. At KernelHost that filtering is two-layered, permanently active and included in every server package at no surcharge.
If your project already runs at KernelHost, the filtering is active without you having to do anything. If you still notice something unusual, open a support ticket so that we can fine-tune the filter rules for your IP address. During an ongoing attack you can also reach us through the WhatsApp emergency chat at +43 650 8209883.
Frequently asked questions
Which port and which protocol does a Terraria server need?
Why does it matter that Terraria uses TCP instead of UDP?
My Terraria server says Server is full although nobody is playing. What is that?
Does a server password help against attacks?
How do I secure the TShock REST API on port 7878?
How many players should I set in maxplayers?
Can I defend myself against a DDoS attack with iptables or UFW?
At what attack size can my Terraria server no longer handle it alone?
Why does a UDP attack hit me although Terraria does not use UDP?
Does my server at KernelHost go offline during an attack?
Does DDoS protection at KernelHost cost extra?
When do I additionally need Advanced DDoS Protection?
2026 KernelHost GmbH. All rights reserved. This guide is protected by copyright. Republishing it on other websites, in whole, in part or in edited form, is not permitted without our written consent. Quoting with a source credit and a link is expressly welcome.

