Severe DDoS attack: what to do now
Record the measurements, close ports, limit the query port and packet rates: what really helps during a sustained DDoS attack. And from which size onwards only the filtering in front of the server works.
An attack that is over after ten minutes is annoying. One that has been coming back every evening at the same time for days is something else: at that point your server is no longer a random target. This article shows what to do now, what you can secure yourself at no extra cost, and where those measures stop.
All commands refer to Debian 12, Debian 13, Ubuntu 22.04 LTS and Ubuntu 24.04 LTS and are written for root; as a regular user, put sudo in front of them. What a DDoS attack is in technical terms is explained in What is a DDoS attack?.
While the attack is running: do not reboot and do not rebuild half of your configuration. A reboot wipes exactly the counters you need for the report to your provider, and the attack comes back unchanged afterwards.
Why your server in particular is attacked so persistently
Servers that get hit for weeks on end almost always share the same three traits. First, they publish their address themselves: in a server list, in a Discord, through a DNS record. Second, their usage is tied to fixed hours, so an outage at 8 in the evening is as visible as it gets. Third, there is someone to whom that outage is worth something: a competing project, a banned player, an unhappy customer.
On top of that, many of the affected services run over UDP. UDP has no handshake you could insist on, and source addresses can be forged. An attacker therefore does not have to enter your service or even address it correctly in order to create load. With TCP services, half-open connections tie up resources instead, without ever being completed.
The ports this is actually about
An attack does not hit "the server", it hits a port. The overview below lists the default ports of the most frequently targeted services and doubles as your checklist: anything that does not appear here and is open anyway should be closed.
| Service | Default port |
|---|---|
| Minecraft Java Edition | 25565 TCP |
| Minecraft Bedrock Edition | 19132 UDP |
| FiveM and RedM | 30120 TCP and UDP |
| ARK: Survival Evolved | 7777 and 7778 UDP, Ascended only 7777 UDP |
| Rust | 28015 UDP, RCON 28016 TCP |
| Steam query port | 27015 UDP |
| TeamSpeak 3 | 9987 UDP, ServerQuery 10011 TCP |
| Web server | 80 and 443 TCP |
| Pterodactyl Wings | 8080 TCP, SFTP 2022 TCP |
| Remote access | SSH 22 TCP, RDP 3389 TCP |
| Database | MariaDB 3306 TCP, PostgreSQL 5432 TCP |
| VPN | OpenVPN 1194 UDP, WireGuard 51820 UDP |
A second group does not show up as a target but as a source: 53 (DNS), 123 (NTP), 389 (CLDAP), 1900 (SSDP), 11211 (memcached) and 27015 as well. If these source ports dominate, you are dealing with a reflection and amplification attack. The senders are then uninvolved, badly configured servers, which is why blocking individual addresses leads nowhere.
What you can do yourself before spending money
This section is the longest one, and deliberately so: a properly configured server withstands small and medium attacks on its own and delivers the measurements for the next stage when things get serious.
1. The first minutes: measure instead of tinker
Before you change anything, record what is happening right now. Four values are enough: the incoming packet rate, the state distribution of the connections, kernel messages, and the question of whether the service still responds locally.
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 -Htan | awk '{print $1}' | sort | uniq -c | sort -rn
dmesg -T | tail -50
curl -o /dev/null -s -w '%{time_total}\n' http://127.0.0.1/
The interface name comes from the default route, because eth0 does not exist at all on many KVM servers (there it is called ens3 or enp1s0), and a wrongly entered name will happily report zero packets. A large block in SYN-RECV is the signature of a SYN flood. If the service responds quickly over 127.0.0.1 while it fails from the outside, the problem sits in the network. And note: on the server you only measure what got through, behind a filtering layer you see just a fraction of the volume. The systematic approach is covered in Detecting a DDoS attack.
If you can no longer get through over SSH, that is not a reason to reboot, it is the consequence of a saturated uplink. Access then runs through the VNC console in the customer panel, which works independently of the network connection.
2. Taking stock: what is listening to the outside?
ss -lntup
nmap -Pn -p- --min-rate 1000 YOUR.SERVER.IP.ADDRESS
The first command shows your own view, the second one, run from another machine, shows the view of the attacker. What matters is the local address: 0.0.0.0:3306 means "reachable from the entire internet", 127.0.0.1:3306 means "local only" and needs no firewall rule. Forgotten services turn up regularly in the process: a test instance, an admin panel, a database without a local binding.
3. Leave open only what the service really needs
The order matters, otherwise you lock yourself out: first the allow rules, then the default policy, then switch it on.
ufw allow 22/tcp comment 'SSH'
ufw allow 80,443/tcp comment 'Web'
ufw allow 25565/tcp comment 'Game port'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose
Afterwards, use a second, freshly opened session to check whether you still get in: existing connections survive the activation even when the matching rule is missing. The full guide, including how to get back in, is in Setting up the UFW firewall without locking yourself out.
The database does not belong on the open internet, so /etc/mysql/mariadb.conf.d/50-server.cnf has to contain bind-address = 127.0.0.1. Admin interfaces do not belong there either: without a fixed IP address for a targeted allow rule, leave the port closed and reach it through an SSH tunnel.
ssh -N -L 8443:127.0.0.1:8443 root@YOUR.SERVER.IP.ADDRESS
Published container ports bypass the UFW chains. Bind them locally, so -p 127.0.0.1:8080:80 instead of -p 8080:80, and route access through a reverse proxy.
4. Securing the query port without closing it
Besides the actual port, many services have a second one that hands out status information: 27015 UDP for Steam-based games, the query port for Minecraft, the ServerQuery interface on 10011 TCP for TeamSpeak. They answer without a login, and the answer is larger than the request, which makes them usable for amplification against third parties. Closing them is usually not an option, because your server then disappears from the server list. Limit them per source address instead:
iptables -I INPUT -p udp --dport 27015 -m hashlimit --hashlimit-name query --hashlimit-mode srcip --hashlimit-above 10/sec --hashlimit-burst 20 -j DROP
Ten queries per second per address are enough for real players and for your monitoring, while a source with thousands of requests per second gets dropped. With Minecraft, enable-query=false in server.properties switches the query port off entirely without the server disappearing from the list. enable-status=false additionally suppresses the reply to the list ping, but then your server shows up as offline. Bind the TeamSpeak ServerQuery interface to 127.0.0.1.
5. Limiting connection and packet rates
iptables -I INPUT -p tcp --dport 443 --syn -m connlimit --connlimit-above 40 --connlimit-mask 32 -j DROP
iptables -I INPUT -p udp --dport 7777 -m hashlimit --hashlimit-name game_udp --hashlimit-mode srcip --hashlimit-above 600/sec --hashlimit-burst 900 -j DROP
The first rule drops new TCP connections as soon as one address has more than forty of them open at the same time, the second drops UDP packets once the same source sustains more than 600 packets per second. Both figures are starting points, not truths: set them too tightly and you throw out your own users. Use iptables -L INPUT -n -v to check whether the hit counters are rising. If they stay at zero, the rule is never reached.
Plain iptables rules are gone after a reboot; you persist them with apt-get install -y iptables-persistent and netfilter-persistent save. Under UFW they belong in /etc/ufw/before.rules, otherwise they disappear on the next ufw reload. And then there is the fundamental limit: limits per source address only work as long as there are conspicuous sources. If each of the 200,000 addresses involved sends exactly one packet, none of them stands out.
6. Preparing the kernel for many small packets
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.core.somaxconn=4096
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
SYN cookies answer the handshake without allocating memory and are active out of the box. The two queues are the first to overflow when many connection attempts arrive at once. For a permanent setting, such values belong in a file under /etc/sysctl.d/ and are applied with sysctl --system. The last line shows connection tracking, which only exists with an active firewall: once its table fills up, the server drops legitimate packets as well and logs nf_conntrack: table full, dropping packet.
7. Application level: rate limits, whitelist, plugins and anti-cheat
Attacks that overload the application instead of the uplink look different: few packets, but expensive ones. An HTTP flood against the search function of a shop does not need a gigabit. On a web server, a limit per address is therefore the most effective measure, in nginx in the http block and afterwards in the server or location block:
limit_req_zone $binary_remote_addr zone=web:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=webconn:10m;
limit_req zone=web burst=20 nodelay;
limit_conn webconn 20;
Against repeated login attempts, Fail2ban is a sensible addition; the setup is described in Set up fail2ban. On game servers, three things work against everything that uses the regular way in: a whitelist (with Minecraft whitelist=true together with enforce-whitelist=true), a realistic cap on concurrent players, and network events validated on the server side.
What plugins and anti-cheat systems cannot do deserves to be said just as plainly: both run in the same process as the game and only check once a packet is already being processed. If the process stalls, the protection logic stalls with it. The same applies to the whitelist, because whoever floods your server does not want to join at all.
8. Server list, DNS and your own IP address
Honesty beats wishful thinking here: your IP address cannot be kept secret. Everyone who has connected once knows it, and a list entry publishes it anyway. Two habits still help: never publish the raw address yourself, not in a Discord channel and not through a status bot, and let your users connect through a hostname so that an address change does not break every reference.
During the change itself, old DNS records are the classic mistake: a forgotten A record, a subdomain left over from a status page, an MX record pointing at the same server. And even then, an address change buys time rather than solving anything.
9. Logging while the incident is running
Without a baseline you cannot say afterwards whether 40,000 packets per second was a lot or simply a Tuesday evening. With apt-get install -y vnstat sysstat the measurement keeps running in the background. During the incident, collect the following:
mkdir -p /root/incident && cd /root/incident
date -u > 01-time.txt
ss -s > 02-sockets.txt
ip -s link > 03-interfaces.txt
sar -n DEV 1 10 > 04-packetrate.txt
dmesg -T | tail -100 > 05-kernel.txt
tcpdump -ni "$IF" -s 96 -c 500 -q > 06-sample.txt
Always limit tcpdump with -c, because an unlimited capture on a saturated uplink puts additional load on the server. The ticket should then contain the time with the time zone, the affected IP address together with the port, the measured packet rate with the direction, the protocol distribution and the conspicuous source ports. With that information a report is acted on immediately; with "the server was slow" you get follow-up questions.
Where these measures stop
Now for the part that no configuration file solves. Every measure so far operates at the far end of the uplink. A firewall rule decides the fate of a packet that has already crossed the wire: you can drop it, but you cannot unsend it.
Do the math once. An uplink of 1 Gbps carries 125 megabytes per second and is full as soon as somebody sends more. With the smallest possible packets that corresponds to roughly 1.49 million packets per second, and at 10 Gbps to roughly 14.9 million. Depending on CPU and network card, a server kernel processes a few hundred thousand of them before it starts dropping. So an attack that does not even fill a third of your uplink still takes you down, because the processing time goes into the dropping.
For a sense of the magnitudes that really occur: on KernelHost servers we have filtered in real time, among others, an attack of over 473.4 Gbps at over 41.5 million packets per second against a voice server (9987 UDP), and a UDP flood of over 112.2 Gbps against a game server (7777 UDP). The first case is roughly 473 times what an uplink of 1 Gbps can carry at all. Volumetric attacks have to end in the network in front of the server, otherwise they end in your uplink.
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 order, switch on 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 on site in Frankfurt am Main. Directly in front of the server, protocol-specific patterns are detected and dropped, packet by packet.
Two properties make the difference when it counts. 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. If a provider instead takes the attacked address off the network, the result for you is identical to a successful attack. The datacenter is maincubes in Frankfurt am Main, Germany, and the operator is KernelHost GmbH, based in Vienna, Austria. The protection is included in every server package at no surcharge, from the KVM root server to the dedicated server.
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 €50.00 per month, PrePaid and with no minimum term. 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, without a ticket: the game port gets different rules than the query port.
- Changes take effect in real time, so you can fine-tune in the middle of an ongoing attack.
- A protection profile that matches the game, plus profiles for custom and 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 €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 |
| Term | tied to the server package | PrePaid, no minimum term, no notice period, no setup fee |
For most 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.
Common mistakes and how to fix them
"I rebooted the server and it ran again for a short while": that was the attack arriving in waves, not the reboot. Reboots wipe the counters you would have needed for the report.
"I changed the IP address and was offline again two hours later": the new address came from the same source as the old one, usually a list entry, a status bot or an old DNS record.
"I block the conspicuous addresses and new ones keep coming": in a distributed attack there are tens of thousands of them, and with reflection attacks you are only blocking uninvolved third parties anyway.
"My firewall rules have no effect": three causes are common: the rules sit behind the UFW chains, they were gone after the last reboot, or the attack is volumetric and the rule works correctly on an uplink that is already full.
"The utilization was low and the service was gone anyway": a typical packet-rate attack. The bandwidth looks harmless, the number of packets does not. Measure packets per second, not megabits.
"I do not see anything unusual in tcpdump": if the traffic is filtered in the network upstream, nothing arrives on the server, exactly as expected. If the uplink is saturated, on the other hand, even the SSH session may no longer reach you. Use the VNC console in the customer panel then.
In short
Measure first, rebuild afterwards. Close everything the service does not need, limit the query port, the connections and the packet rates per source address, and collect measurements while the incident is running. That covers you against everything that gets by without serious bandwidth. Beyond that, only the network in front of the server decides the outcome.
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
My server has been unreachable for hours. What do I check first?
Should I reboot the server or change the IP address?
I can no longer reach the server over SSH. How do I still get in?
Why does my firewall no longer help against a large attack?
Can a plugin or an anti-cheat stop the attack?
Is my IP address taken 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.

