{"id":416,"date":"2026-09-01T17:07:06","date_gmt":"2026-09-01T17:07:06","guid":{"rendered":"https:\/\/www.vps.tc\/blog\/?p=416"},"modified":"2026-09-01T09:30:37","modified_gmt":"2026-09-01T09:30:37","slug":"what-is-a-ddos-attack-vps-protection-guide","status":"publish","type":"post","link":"https:\/\/www.vps.tc\/blog\/en\/what-is-a-ddos-attack-vps-protection-guide\/","title":{"rendered":"What Is a DDoS Attack? A Practical VPS Protection Guide"},"content":{"rendered":"<div class=\"aiw-toc\" style=\"border:1px solid #dbe3ea;border-radius:8px;padding:16px 20px;margin:0 0 28px\"><strong>Table of Contents<\/strong><\/p>\n<ol style=\"margin:10px 0 0;padding-left:22px\">\n<li><a href=\"#what-is-a-ddos-attack-and-how-does-it-affect-a-vps\">What Is a DDoS Attack, and How Does It Affect a VPS?<\/a><\/li>\n<li><a href=\"#identify-the-attack-before-choosing-the-fix\">Identify the attack before choosing the fix<\/a><\/li>\n<li><a href=\"#the-first-five-minutes-collect-evidence-before-restarting\">The first five minutes: collect evidence before restarting<\/a><\/li>\n<li><a href=\"#defenses-you-can-apply-on-the-vps\">Defenses you can apply on the VPS<\/a><\/li>\n<li><a href=\"#why-the-provider-and-cdn-layers-matter\">Why the provider and CDN layers matter<\/a><\/li>\n<li><a href=\"#monitoring-logging-and-the-cleanup-after-an-attack\">Monitoring, logging, and the cleanup after an attack<\/a><\/li>\n<li><a href=\"#when-should-you-resize-the-vps-or-change-the-architecture\">When should you resize the VPS or change the architecture?<\/a><\/li>\n<li><a href=\"#shortcuts-that-cause-more-trouble\">Shortcuts that cause more trouble<\/a><\/li>\n<li><a href=\"#a-practical-ddos-checklist-for-your-vps\">A practical DDoS checklist for your VPS<\/a><\/li>\n<li><a href=\"#frequently-asked-questions\">Frequently asked questions<\/a><\/li>\n<\/ol>\n<\/div>\n<h2 id=\"what-is-a-ddos-attack-and-how-does-it-affect-a-vps\">What Is a DDoS Attack, and How Does It Affect a VPS?<\/h2>\n<p>When three monitoring alerts appear during a night shift, my hand does not go straight to <code>reboot<\/code>. I first check where the traffic is coming from, which port is filling up, and how much of the machine&#8217;s resources are actually being consumed. During a DDoS event, an impatient reboot may not stop anything. It can erase useful evidence and clear the active connection table.<\/p>\n<p>DDoS stands for Distributed Denial of Service. It describes an attempt to make a server or service unavailable by sending a large volume of requests or traffic from many sources. The target is not always a website. DNS, game servers, SSH, APIs, and the public IP address of a VPS can all be attacked.<\/p>\n<p>The word <em>distributed<\/em> matters. Because the traffic does not come from one computer, blocking a single IP address is rarely enough. Attackers may use botnets made up of compromised devices. Some attacks consume bandwidth, while others exhaust connection tables. HTTP-like attacks can use CPU and database capacity without producing an enormous amount of network traffic.<\/p>\n<p>I think about DDoS protection in two layers: reducing resource consumption inside the VPS, and filtering unwanted traffic at the data center or upstream provider. Your own configuration helps with the first layer. The second may require your hosting provider&#8217;s DDoS service, a scrubbing center, or a CDN.<\/p>\n<h2 id=\"identify-the-attack-before-choosing-the-fix\">Identify the attack before choosing the fix<\/h2>\n<p>Not every traffic spike is a DDoS attack. A newly published campaign, a search-engine crawl, a broken cron job, or a link shared by a customer can all create a short-lived increase. Calling it an attack without checking the evidence is expensive. So is treating a real attack as normal traffic.<\/p>\n<h3>Volumetric attacks fill the connection<\/h3>\n<p>These attacks aim to consume the capacity of your internet connection. UDP floods, ICMP floods, and large DNS response floods belong to this category. Even if you write an <code>nftables<\/code> rule on the VPS, the packets usually reach the data-center uplink first. Once the connection is full, rejecting packets on the server does not give bandwidth back to legitimate users.<\/p>\n<p>For volumetric attacks, the response usually starts with the provider. Traffic must be filtered before it reaches the VPS, or redirected to a scrubbing service. A local firewall can help during a small, short-lived burst, but it cannot create extra network capacity.<\/p>\n<h3>Protocol attacks consume connection resources<\/h3>\n<p>A SYN flood tries to exhaust resources during TCP connection setup. When large numbers of half-open connections accumulate, the backlog and conntrack tables can come under pressure. Ordinary users then struggle to establish connections as well.<\/p>\n<p>SYN cookies, connection limits, and provider-side filtering can help here. Randomly increasing <code>sysctl<\/code> values is not a complete fix. Larger tables can give an attacker a larger space to fill, while also increasing RAM consumption.<\/p>\n<p>Small changes matter. Blind changes do not.<\/p>\n<h3>Application-layer attacks can look ordinary<\/h3>\n<p>HTTP floods, slow requests, and expensive API calls may look like normal web traffic from the outside. Requests arrive on port 443, TLS completes successfully, and nginx or Apache passes them to the application. The traffic volume may not look enormous, but if every request starts a PHP worker, a MySQL query, or an external API call, the VPS can run out of breath quickly.<\/p>\n<p>This is where CDN filtering, web-server rate limits, caching, authentication, and application-level quotas need to work together. Blocking IP addresses alone is usually insufficient; a botnet may contain thousands of addresses.<\/p>\n<h2 id=\"the-first-five-minutes-collect-evidence-before-restarting\">The first five minutes: collect evidence before restarting<\/h2>\n<p>During an incident, I want the diagnostic phase to stay short and repeatable. I start with the provider&#8217;s traffic graph, resource usage, and any available DDoS alert. Then I connect over SSH and take a general snapshot of the system. If SSH is also affected, the provider&#8217;s console may be the safer route.<\/p>\n<pre><code>date\nhostname\nuptime\nfree -h\nip -s link\nss -s<\/code><\/pre>\n<p>Do not skip the <code>hostname<\/code> line. My production prompts are red for a reason: I want this check to be impossible to miss. <code>ip -s link<\/code> shows interface-level packet and error counters, while <code>ss -s<\/code> gives a rough summary of TCP states. None of these commands proves that a DDoS attack is happening on its own.<\/p>\n<p>To inspect a particular port, I use a narrower query:<\/p>\n<pre><code>ss -Htan state syn-recv | wc -l\nss -Htan '( sport = :80 or sport = :443 )' | head -20\nss -Huan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head<\/code><\/pre>\n<p>The first command counts half-open TCP connections. The second displays a sample of HTTP and HTTPS connections. The third roughly counts UDP endpoints; do not trust this short <code>awk<\/code> pipeline blindly when IPv6 addresses or different output formats are involved.<\/p>\n<p>During an incident, I also save the output:<\/p>\n<pre><code>ss -s &gt; \/root\/incident-ss-$(date +%F-%H%M).txt\njournalctl -k --since \"10 minutes ago\" &gt; \/root\/incident-kernel.log<\/code><\/pre>\n<p>Kernel logs may show drops, SYN-flood messages, conntrack warnings, or network-driver errors. The absence of a log message does not prove the absence of an attack; some counters rise without producing a log entry.<\/p>\n<p>I once changed a remote firewall without opening a second SSH session first. The existing connection stayed alive, fortunately, so I could correct the rule instead of using the provider console. Since then, I keep a second session open before touching a remote firewall. Boring is good during an incident.<\/p>\n<h2 id=\"defenses-you-can-apply-on-the-vps\">Defenses you can apply on the VPS<\/h2>\n<h3>Close ports you do not need<\/h3>\n<p>Every publicly exposed service is part of your attack surface. First, list the services that are listening:<\/p>\n<pre><code>sudo ss -lntup<\/code><\/pre>\n<p>I pay particular attention to services listening on <code>0.0.0.0<\/code> or <code>::<\/code>. In many setups, PostgreSQL, Redis, and MySQL have no reason to be reachable from the public internet. When installing and securing MySQL, check its bind address and firewall access together; a strong password by itself is not enough.<\/p>\n<p>At the firewall, allow only the ports you actually use. A simple <code>nftables<\/code> starting point for SSH, HTTP, and HTTPS could look like this:<\/p>\n<pre><code>table inet filter {\n  chain input {\n    type filter hook input priority filter; policy drop;\n\n    iifname \"lo\" accept\n    ct state established,related accept\n    ip protocol icmp accept\n    ip6 nexthdr ipv6-icmp accept\n    tcp dport 22 ct state new limit rate 15\/minute accept\n    tcp dport { 80, 443 } accept\n  }\n\n  chain forward { type filter hook forward priority filter; policy drop; }\n  chain output { type filter hook output priority filter; policy accept; }\n}<\/code><\/pre>\n<p>Adjust this example for your distribution, remote-access policy, and IPv6 setup. If you have a fixed administration IP, restrict the SSH rule to that address instead. The rate limit here applies to new SSH connections as a group, not separately to every source address.<\/p>\n<p>When changing a remote firewall, I open a second session first. That habit saved me once. A small omission can become a long walk to the provider console.<\/p>\n<h3>Move SSH away from the center of attention<\/h3>\n<p>Changing SSH from port 22 to another port is not security. It may reduce some automated scanning noise, but the controls that matter are key-based authentication, disabled root login, current OpenSSH packages, and firewall restrictions.<\/p>\n<pre><code>sudoedit \/etc\/ssh\/sshd_config<\/code><\/pre>\n<pre><code>PermitRootLogin no\nPasswordAuthentication no\nMaxAuthTries 3<\/code><\/pre>\n<p>Check the configuration before reloading it:<\/p>\n<pre><code>sudo sshd -t &amp;&amp; sudo systemctl reload ssh<\/code><\/pre>\n<p>On Ubuntu and Debian, the service is usually called <code>ssh<\/code>; some distributions use <code>sshd<\/code>. Test a new key-based login without closing the current session. If you use a fixed administration network, combine these settings with a firewall allowlist and a VPN such as WireGuard.<\/p>\n<h3>Use rate limits at the web server<\/h3>\n<p>At the HTTP layer, nginx&#8217;s <code>limit_req<\/code> and <code>limit_conn<\/code> modules can protect selected endpoints. Login, search, and expensive reporting APIs should not necessarily have the same limits as ordinary pages.<\/p>\n<pre><code>http {\n    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r\/m;\n    limit_conn_zone $binary_remote_addr zone=addr:10m;\n\n    server {\n        limit_conn addr 30;\n\n        location = \/wp-login.php {\n            limit_req zone=login_limit burst=3 nodelay;\n            include fastcgi_params;\n            # Keep your existing PHP-FPM settings here.\n        }\n    }\n}<\/code><\/pre>\n<p>This is not a WordPress recipe to copy into every installation. Many real users behind a NAT gateway may share one public IP, so an IP-based limit can affect them all. Quotas based on an API key, session, or user account may be more accurate at the application layer.<\/p>\n<p>After changing the configuration:<\/p>\n<pre><code>sudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n<p>Do not reload nginx until <code>nginx -t<\/code> succeeds. I have seen rate limits added while every anonymous request remained uncached. That wastes the protection you already paid for with CPU and database work. Serve anonymous, cacheable content from the edge or nginx whenever possible.<\/p>\n<h2 id=\"why-the-provider-and-cdn-layers-matter\">Why the provider and CDN layers matter<\/h2>\n<p>If your VPS is receiving hundreds of megabits per second, local firewall rules may still process the packets. But if the connection capacity assigned to the VPS is full, legitimate traffic cannot get in. At that point, a local rule has limited value; filtering must happen closer to the traffic source.<\/p>\n<p>When contacting your hosting provider, send measurable details instead of simply saying &#8220;the site is slow&#8221;:<\/p>\n<ul>\n<li>The time window when the attack started and intensified<\/li>\n<li>The targeted IPv4 or IPv6 address and port<\/li>\n<li>Whether the traffic is mainly TCP, UDP, ICMP, or HTTP<\/li>\n<li>Observed bandwidth, packet counts, and connection states<\/li>\n<li>Distinct URL or User-Agent patterns in the application logs<\/li>\n<li>Which service legitimate users cannot reach<\/li>\n<\/ul>\n<p>If your provider uses blackhole routing, it may temporarily discard traffic to the attacked IP. That protects the server, but it also makes the service unavailable. If scrubbing or upstream filtering is available, it may reduce the outage. A plan labelled &#8220;DDoS protected&#8221; does not mean these operational details are automatically solved.<\/p>\n<p>For a website, a reverse proxy or CDN can prevent clients from seeing the VPS&#8217;s origin IP. Moving a DNS record to a CDN is not enough by itself. If the origin IP was exposed before, an attacker can continue sending traffic directly to it. The origin firewall should allow only the proxy provider&#8217;s current IP ranges, and keeping those ranges updated is part of the job.<\/p>\n<p>DNS needs attention too. If an A record still reveals the old origin address, the proxy loses much of its value. I check externally visible addresses and forgotten subdomains with <code>dig +short<\/code> before I look at a hosting panel:<\/p>\n<pre><code>dig +short example.com A\ndig +short www.example.com A\ndig +short example.com AAAA<\/code><\/pre>\n<p>If this output does not show the proxy addresses you expect, review the DNS and origin design together. Forgetting IPv6 can bypass all the protection you configured for IPv4.<\/p>\n<h2 id=\"monitoring-logging-and-the-cleanup-after-an-attack\">Monitoring, logging, and the cleanup after an attack<\/h2>\n<p>DDoS protection for VPS workloads is not a handful of firewall rules written during an incident. If you do not know the normal pattern, you cannot recognize the abnormal one. In my home Proxmox lab, Uptime Kuma handles availability checks, Prometheus with <code>node_exporter<\/code> collects CPU, RAM, network, and disk metrics, and Grafana lets me see the changes over time. It is a safe place to test alert thresholds before I trust them on customer systems.<\/p>\n<p>Useful indicators include:<\/p>\n<ul>\n<li>Incoming and outgoing traffic, including packet rates<\/li>\n<li>TCP connection states and conntrack usage<\/li>\n<li>Web-server request counts, 4xx and 5xx rates, and response times<\/li>\n<li>Load average and iowait alongside CPU usage<\/li>\n<li>RAM, swap, and disk I\/O consumption<\/li>\n<li>Application worker counts, queue length, and database connections<\/li>\n<\/ul>\n<p>When RAM runs out, swap can make the machine appear to recover, but heavy swapping increases latency. My guide, <strong><a href=\"https:\/\/www.vps.tc\/blog\/en\/how-to-create-swap-space-on-a-vps-for-linux-memory-management\/\">How to Create Swap Space on a VPS for Linux Memory Management<\/a><\/strong>, explains why swap should not be treated as a replacement for physical RAM. Rising swap during a DDoS may also point to an application-layer HTTP attack.<\/p>\n<p>After the incident, record the temporary rules you added, the limits you tested, and any DNS changes you made. A remote log server or provider-side logging service helps preserve evidence during the attack. Turning the attacker&#8217;s IP list into a permanent firewall list usually creates maintenance work: addresses change, and legitimate users get blocked by accident.<\/p>\n<p>Review the web application as well. An old plugin or an expensive endpoint may not have caused the attack, but it can amplify its effect. The update, least-privilege, and log-monitoring checks in <strong><a href=\"https:\/\/www.vps.tc\/blog\/en\/10-essential-steps-to-secure-and-harden-your-linux-server\/\">10 Essential Steps to Secure and Harden Your Linux Server<\/a><\/strong> apply directly here.<\/p>\n<h2 id=\"when-should-you-resize-the-vps-or-change-the-architecture\">When should you resize the VPS or change the architecture?<\/h2>\n<p>Doubling the CPU can buy time during a small application-layer flood. It will not solve an attack that fills the network connection; a larger VPS may simply become a more expensive target. Find the bottleneck first.<\/p>\n<table>\n<thead>\n<tr>\n<th>Symptom<\/th>\n<th>Likely layer<\/th>\n<th>First place to investigate<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Connection capacity remains full<\/td>\n<td>Volumetric traffic<\/td>\n<td>Hosting provider and upstream filtering<\/td>\n<\/tr>\n<tr>\n<td>SYN-RECV count is unusually high<\/td>\n<td>TCP connection exhaustion<\/td>\n<td>Kernel counters, firewall, and provider protection<\/td>\n<\/tr>\n<tr>\n<td>CPU is high while requests look normal<\/td>\n<td>HTTP or application layer<\/td>\n<td>nginx logs, endpoints, and database queries<\/td>\n<\/tr>\n<tr>\n<td>RAM and worker capacity are exhausted<\/td>\n<td>Application resource consumption<\/td>\n<td>PHP-FPM, API limits, cache, and queues<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If your workload regularly receives high traffic, you may need a CDN, load balancer, separate database, rate-limit service, or multiple origins. Not every site needs all of them. For a small application running on one VPS, closing unnecessary ports, fixing expensive queries, and understanding the provider&#8217;s DDoS policy are usually better first steps.<\/p>\n<p>Do not leave backups out of the plan. A DDoS attack may not delete data, but panic can lead to a destructive command, a firewall change that breaks services, or a rushed rebuild afterward. An untested backup is only a collection of files. Restore it on a separate VPS and practise the procedure at least monthly if the service matters.<\/p>\n<h2 id=\"shortcuts-that-cause-more-trouble\">Shortcuts that cause more trouble<\/h2>\n<ul>\n<li><strong>Running everything as root:<\/strong> It increases the cost of a mistake during an incident. Use separate accounts and <code>sudo<\/code> for administrative work.<\/li>\n<li><strong>Changing the SSH port and assuming you are protected:<\/strong> It reduces noise, but does not replace authentication controls or firewall restrictions.<\/li>\n<li><strong>Blocking every incoming IP by hand:<\/strong> A distributed attack makes the list grow quickly and creates false positives.<\/li>\n<li><strong>Disabling the firewall completely:<\/strong> Even a short diagnostic test can leave an access window forgotten.<\/li>\n<li><strong>Rebooting without reading the logs:<\/strong> It hides the root cause and resets connection tables.<\/li>\n<li><strong>Applying unlimited rate limits:<\/strong> You can block real users, including customers behind NAT.<\/li>\n<\/ul>\n<p>Most of my expensive mistakes did not come from missing technical knowledge. They came from having no written plan when something was already burning. Write down who to contact, which IP is the origin, which ports are required, and how to recover before the next attack. A small runbook is more reliable than memory during a night shift.<\/p>\n<h2 id=\"a-practical-ddos-checklist-for-your-vps\">A practical DDoS checklist for your VPS<\/h2>\n<ol>\n<li>List your VPS&#8217;s public IPv4 and IPv6 addresses, open ports, and critical services.<\/li>\n<li>Ask your hosting provider about volumetric attack thresholds, automatic filtering, and emergency contact procedures.<\/li>\n<li>Protect SSH with key authentication and, where practical, an administration-IP allowlist.<\/li>\n<li>Disable unnecessary services; do not expose MySQL, Redis, or administration panels directly to the internet.<\/li>\n<li>Set sensible quotas for login, search, and API endpoints at the nginx or application layer.<\/li>\n<li>If you use a CDN, hide the origin IP and restrict the origin firewall to the proxy networks.<\/li>\n<li>Create alerts for network traffic, connection states, CPU, RAM, and error rates in Prometheus, Grafana, or your existing monitoring system.<\/li>\n<li>Document the commands to run during an attack and the information to send to your provider.<\/li>\n<li>Keep backups in a separate location and test restoring them regularly.<\/li>\n<\/ol>\n<p>The short answer to &#8220;what is a DDoS attack?&#8221; is traffic or requests generated from distributed sources to make a service unavailable. Protecting a VPS does not come down to one firewall rule. You need a provider that can filter capacity-consuming traffic in the right place, measured local controls, caching, application limits, and a calm response plan.<\/p>\n<p>Run <code>ss -lntup<\/code> on your own server now and mark the services that genuinely need to be reachable from outside. When I started doing this regularly, I found two &#8220;temporary&#8221; management ports that had been open for months. Temporary becomes permanent surprisingly easily when nobody writes it down.<\/p>\n<h2 id=\"frequently-asked-questions\">Frequently asked questions<\/h2>\n<h3>How can I tell a DDoS attack from a normal traffic spike?<\/h3>\n<p>Do not use a sudden graph increase as the only signal. Check the source-IP distribution, request paths, User-Agent values, HTTP error rates, and application resource usage together. Campaign traffic often contains meaningful URLs and consistent client behaviour, while an attack may show many abnormal patterns.<\/p>\n<h3>Can a VPS firewall completely stop a DDoS attack?<\/h3>\n<p>No. A firewall can reduce smaller connection or application-layer floods, but it cannot stop a volumetric attack after the traffic has already filled the connection to your VPS. Data-center or upstream filtering is needed in that situation.<\/p>\n<h3>Is using a CDN enough for DDoS protection for VPS hosting?<\/h3>\n<p>A CDN adds a significant layer for web traffic, but an exposed origin IP allows an attacker to bypass it. Check DNS records, old subdomains, email and other services, then restrict the origin firewall to the proxy networks.<\/p>\n<h3>Should I restart the server during a DDoS attack?<\/h3>\n<p>Usually, that should not be the first step. Collect evidence from traffic graphs, connection states, kernel logs, and the provider&#8217;s monitoring first. A reboot may temporarily clear resources, but it does not address the cause of the attack.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A practical guide to DDoS protection for VPS servers, covering attack types, first-response commands, firewall rules, nginx limits, provider filtering, and monitoring.<\/p>\n","protected":false},"author":2,"featured_media":414,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[1496,1490,441,1499,1493,1289,409],"class_list":["post-416","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datacenter","tag-cdn","tag-ddos-protection-for-vps","tag-linux-server-security","tag-network-monitoring","tag-nftables-en","tag-nginx-en","tag-vps-security"],"lang":"en","translations":{"en":416,"tr":415},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/comments?post=416"}],"version-history":[{"count":1,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/416\/revisions"}],"predecessor-version":[{"id":418,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/posts\/416\/revisions\/418"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/media\/414"}],"wp:attachment":[{"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/media?parent=416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/categories?post=416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vps.tc\/blog\/wp-json\/wp\/v2\/tags?post=416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}