<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zerlo.net</title>
    <description>The latest articles on DEV Community by Zerlo.net (@zerlo).</description>
    <link>https://dev.to/zerlo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3873649%2F1a15c026-91f0-4b38-85e4-d9f9c1e05357.png</url>
      <title>DEV Community: Zerlo.net</title>
      <link>https://dev.to/zerlo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zerlo"/>
    <language>en</language>
    <item>
      <title>What To Do When Your Website Is Under a DDoS Attack</title>
      <dc:creator>Zerlo.net</dc:creator>
      <pubDate>Sat, 11 Apr 2026 15:53:03 +0000</pubDate>
      <link>https://dev.to/zerlo/what-to-do-when-your-website-is-under-a-ddos-attack-3g6</link>
      <guid>https://dev.to/zerlo/what-to-do-when-your-website-is-under-a-ddos-attack-3g6</guid>
      <description>&lt;p&gt;A little while ago, &lt;a href="https://zerlo.net/" rel="noopener noreferrer"&gt;Zerlo.net&lt;/a&gt; was hit by a DDoS attack.&lt;/p&gt;

&lt;p&gt;At first, I assumed it was just a technical issue. But after checking our traffic and infrastructure, it became clear that this was not normal user activity. In this post, I’ll show how we identified the attack, how Cloudflare helped reduce the impact, and what actions are worth taking when your website suddenly starts collapsing under artificial load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mlfdlh2rhcxhpiuzwzs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mlfdlh2rhcxhpiuzwzs.jpg" alt="DDoS attack banner" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a DDoS attack?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Distributed Denial of Service (DDoS)&lt;/strong&gt; attack tries to make a website or service unavailable by overwhelming it with traffic from many different sources at the same time.&lt;/p&gt;

&lt;p&gt;In practice, this often means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;huge spikes in requests&lt;/li&gt;
&lt;li&gt;abnormal load on the origin server&lt;/li&gt;
&lt;li&gt;suspicious user agents&lt;/li&gt;
&lt;li&gt;repeated hits on expensive endpoints like login pages, APIs, search, or forms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are different forms of DDoS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;network-level attacks&lt;/strong&gt; such as UDP or ICMP floods&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;application-layer attacks (Layer 7)&lt;/strong&gt; such as HTTP floods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer 7 attacks are especially annoying because they can look more like “normal” traffic at first glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you recognize it?
&lt;/h2&gt;

&lt;p&gt;A single metric is usually not enough.&lt;/p&gt;

&lt;p&gt;Typical warning signs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sharply rising server load without a corresponding rise in real users&lt;/li&gt;
&lt;li&gt;many requests hitting expensive endpoints&lt;/li&gt;
&lt;li&gt;strange or empty user agents&lt;/li&gt;
&lt;li&gt;unexpected request peaks from unfamiliar ASNs or regions&lt;/li&gt;
&lt;li&gt;high CPU or I/O load even though you didn’t deploy anything new&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the biggest clues in our case was this:&lt;/p&gt;

&lt;p&gt;our own counter tracks &lt;strong&gt;human interactions through JavaScript&lt;/strong&gt;, and those numbers were almost identical to the previous day — while the infrastructure load was massively higher.&lt;/p&gt;

&lt;p&gt;That mismatch is a huge red flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our first practical test
&lt;/h2&gt;

&lt;p&gt;The classic test was simple:&lt;/p&gt;

&lt;p&gt;run everything locally.&lt;/p&gt;

&lt;p&gt;If the application itself is broken, you usually see the problem locally as well.&lt;br&gt;&lt;br&gt;
In our case, local load was basically &lt;strong&gt;0%&lt;/strong&gt;, while the public system was struggling hard.&lt;/p&gt;

&lt;p&gt;That was the moment it became obvious that the pressure was external.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cloudflare showed us
&lt;/h2&gt;

&lt;p&gt;Once we checked Cloudflare, the pattern became much clearer.&lt;/p&gt;

&lt;p&gt;Useful places to look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security Events / Security Analytics&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traffic Analytics&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WAF activity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting and challenge data&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Cloudflare, you can break traffic down by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;path&lt;/li&gt;
&lt;li&gt;country&lt;/li&gt;
&lt;li&gt;ASN&lt;/li&gt;
&lt;li&gt;method&lt;/li&gt;
&lt;li&gt;user agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it much easier to distinguish real traffic from garbage.&lt;/p&gt;

&lt;p&gt;When we enabled &lt;strong&gt;Under Attack Mode&lt;/strong&gt;, the average server load dropped to around &lt;strong&gt;5%&lt;/strong&gt;. That was the clearest confirmation we needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxoqspcujookrfxi1wcao.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxoqspcujookrfxi1wcao.jpg" alt="Cloudflare statistics showing abnormal traffic spike" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cloudflare is actually doing here
&lt;/h2&gt;

&lt;p&gt;This is the simple version:&lt;/p&gt;

&lt;p&gt;Cloudflare sits in front of your origin and can challenge suspicious traffic before it ever reaches your infrastructure.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bots have to solve extra work&lt;/li&gt;
&lt;li&gt;cheap flood traffic becomes more expensive&lt;/li&gt;
&lt;li&gt;real users usually pass with minimal friction&lt;/li&gt;
&lt;li&gt;your backend gets breathing room immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not “prevent DDoS forever”, but it buys time and drastically reduces the damage.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you do immediately?
&lt;/h2&gt;

&lt;p&gt;You can’t stop people on the internet from sending packets to your system.&lt;/p&gt;

&lt;p&gt;So the goal is not “prevent everything forever”.&lt;/p&gt;

&lt;p&gt;The real goal is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;reduce the impact enough so that real users can still use the site.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Short-term actions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;enable &lt;strong&gt;Under Attack Mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;challenge suspicious requests&lt;/li&gt;
&lt;li&gt;put &lt;strong&gt;rate limiting&lt;/strong&gt; on sensitive paths&lt;/li&gt;
&lt;li&gt;protect forms and login-like endpoints&lt;/li&gt;
&lt;li&gt;increase caching where possible&lt;/li&gt;
&lt;li&gt;monitor security analytics closely&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Good candidates for immediate protection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/api/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;form endpoints&lt;/li&gt;
&lt;li&gt;login pages&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;li&gt;mail handlers&lt;/li&gt;
&lt;li&gt;expensive POST requests&lt;/li&gt;
&lt;li&gt;dynamic pages with heavy backend processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What should you do long term?
&lt;/h2&gt;

&lt;p&gt;Short-term mitigation is not enough.&lt;/p&gt;

&lt;p&gt;After the incident, hardening should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;proper &lt;strong&gt;WAF rules&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Challenge&lt;/strong&gt; for suspicious traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt; per IP and per path&lt;/li&gt;
&lt;li&gt;caching public pages aggressively&lt;/li&gt;
&lt;li&gt;bypassing cache only where needed&lt;/li&gt;
&lt;li&gt;protecting forms with &lt;strong&gt;Turnstile&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;collecting and reviewing logs&lt;/li&gt;
&lt;li&gt;setting alerts for unusual spikes&lt;/li&gt;
&lt;li&gt;identifying “expensive” endpoints before the next attack&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A practical rule approach
&lt;/h2&gt;

&lt;p&gt;Here is a simple example of the type of logic that makes sense:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
txt
(len(http.user_agent) = 0
 or lower(http.user_agent) contains "python"
 or lower(http.user_agent) contains "curl"
 or lower(http.user_agent) contains "bot"
 or lower(http.user_agent) contains "crawler")
=&amp;gt; Action: Managed Challenge

(http.request.method eq "POST"
 or starts_with(http.request.uri.path, "/api/")
 or http.request.uri.path contains "/sendMail.php")
=&amp;gt; Action: Managed Challenge

# Rate Limiting example
(http.request.method eq "POST" and starts_with(http.request.uri.path, "/api/"))
Threshold: 10 requests in 10 seconds per IP
Action: Challenge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>cloudflarechallenge</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
