DDoS: The Complete Guide For Founders (2024)
If you’ve spent any time in developer circles, you’ve probably stumbled upon horror stories involving serverless hosting providers like Vercel, Cloudflare, or AWS facing accusations of excessive fees.
In many occurrences, these situations result from Distributed Denial of Service (DDoS) attacks―a malicious attempt to disrupt normal traffic to a server, service, or network traffic by overwhelming it with a flood of internet traffic.
Some are accidental, like self-DDoS, where a website’s own content triggers excessive traffic. Others are intentional, like attacks provoked by competitors or hackers.
In any case, it’s important to understand how DDoS attacks work and how to protect your business from them.
As a cybersecurity company, we are familiar with the threat, so we decided to write this article to share our know-how. We hope you enjoy it!
Why You Need To Understand How DDoS Work
As the name suggests, a Denial of Service attack makes it impossible to serve your customers or acquire new ones, making financial repercussions substantial.
According to Security Magazine, businesses can expect to lose an average of $6,130 per minute of downtime:
- Every minute of downtime represents potential lost sales and diminished business opportunities.
- Staff overtime, crisis management, and IT support are often required to mitigate the attack and restore services.
- DDoS attacks can necessitate additional hardware or cloud resources to handle the increased traffic and prevent future attacks.
Beyond the immediate financial impact, DDoS attacks can inflict long-term damage to a company’s reputation: customers rely on businesses to provide uninterrupted services, and a DDoS attack can erode trust and loyalty.
For enterprise deals with service-level agreements, DoS can result in breaches of contract. Rebuilding a damaged reputation is a challenging and time-consuming process that requires significant PR efforts.
For all these reasons, it’s essential to establish a plan to protect yourself from DDoS attacks. That’s where we come in.
How Does DDoS Work
DDoS attacks typically involve a botnet―a network of compromised devices controlled remotely by attackers. These devices send massive traffic to the target, overwhelming its resources. Common attack strategies include:
- Volumetric attacks overwhelm network bandwidth (for example, by spam-requesting large image files)
- Protocol attacks exploiting vulnerabilities in network protocols (e.g, ping of death or TCP SYN flood)
- Application-layer attacks targeting specific applications (by flooding a long-running API endpoint with requests)
To defend against DDoS attacks, a multi-layered approach taking into account the complete OSI model is essential. This article explores various techniques and tips to mitigate risks.
1. Watch Out For What You Do
One often-overlooked threat is self-DDoS, which occurs when a website’s own content inadvertently triggers excessive traffic. This can happen with resource-intensive elements like videos or long-running serverless functions.
To prevent self-DDoS, it’s essential to respect resource constraints established by your hosting provider. Additionally, closely monitoring usage patterns, even during development, is a proactive step that will keep you vigilant and ahead of any potential issues.
In a typical example from a Twitter user, an uncaught exception in a serverless function triggered requests to fail and restart, causing an absurd amount of bandwidth usage costing, $500 per hour. Even though it all happened in a dev environment, Vercel billed the user like in production settings until customer support was contacted.
Untested code can lead to unexpected consequences in any environment. Always be mindful of the potential impact of your code on server resources.
2. Caching Policies
Caching involves storing copies of data in a temporary storage area, typically closer to the end user, to improve performance.
When a request for a resource is made, the cache is checked first. If the requested data is found in the cache, it is served directly, bypassing the origin server.
The effectiveness of caching depends on implementing appropriate policies (such as how often to invalidate the cache) for different types of content. This is notoriously hard to do as it depends on use cases and production usage, but for the sake of simplicity, we can distinguish between two main types of cached content.
Static content like static assets, such as images, CSS files, and JavaScript files, are ideal candidates for aggressive caching. These resources rarely change, so they can be cached for extended periods, minimizing the need to fetch them from the server.
Dynamic content that changes frequently, like product listings or user-specific data, requires more nuanced caching strategies depending on the trade-off between performance and data freshness. In an app like Instagram, you probably want to cache the outer HTML shell, not the JSON requests that populate the news feed.
Here is a caching example in an Express.js server:
import express from "express";
import expressCache from "cache-express";
const app = express();
app.get(
"/api/data",
expressCache({
dependsOn: () => [getUserID()],
timeOut: 60000, // Cache for 1 minute
onTimeout: (key, value) => {
console.log(`Cache removed for key: ${key}`);
},
}),
(req, res) => {
// time consuming api or database calls
let data = { success: true };
res.json(data);
}
);
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
3. Content Delivery Network
Content Delivery Networks (CDNs) consist of a geographically distributed group of servers that store copies of website content, such as HTML, CSS, JavaScript, images, and videos. It’s like a giant caching network.
By distributing content across multiple servers worldwide, CDNs significantly reduce the load on the origin server and latency―the time it takes for data to travel between servers. This means faster loading times for users, regardless of their location.
For example, Cloudflare is a popular CDN that offers DDoS protection, caching, and security features.
All you have to do is sign up, point your domain to your CDN’s name servers, and let it proxy your traffic to your origin server. The CDN will cache your content and serve it to users from the nearest server automatically.
4. Web Application Firewall
A Web Application Firewall (WAF) serves as the first line of defense, acting as a gatekeeper that filters incoming traffic before it reaches your servers.
WAFs are proxy servers. They sit in front of your web application, intercepting all incoming traffic. The WAF then analyzes each request based on a pre-defined set of rules (allowed IPs, HTTP headers, etc.), allowing legitimate traffic to pass through while blocking any malicious attempts.
Cloud-based solutions like Cloudflare offer intuitive interfaces for setting up WAF rules. For those seeking a self-hosted option, open-source projects like Wafris (available on GitHub at https://github.com/Wafris/wafris-caddy) provide a powerful and customizable WAF solution integrating with web servers like Caddy or Nginx.
5. Static Rendering
Static rendering pre-renders dynamic content into static HTML files to significantly enhance website performance and security.
There are three primary rendering methods:
- Server-Side Rendering (SSR) - Content is generated on the server for each request, offering optimal SEO and initial load times. However it can be resource-intensive without adequate caching policies.
- Static Site Generation (SSG) - Pages are pre-rendered at build time, delivering exceptional performance and SEO benefits. It is ideal for content that changes infrequently such as blog articles or landing pages.
- Single-Page Applications (SPAs) - JavaScript-heavy applications that load a single HTML page and dynamically update content. While offering a smooth user experience, they can have initial load time challenges and SEO limitations.
In high-traffic websites, even minuscule performance gains can yield substantial benefits. Static rendering makes it easy to cache entire pages aggressively for long periods, and optimizing your application by just 500 milliseconds can make a significant difference when serving thousands of requests per second.
You can begin by statically rendering all possible pages to establish a strong performance foundation. Even app pages can be pre-rendered if you use an app shell model with progressive enhancement.
You then reserve client-side data fetching for dynamic content that requires real-time updates or personalization via hydration mechanisms.
Most React framework websites and apps allow this by default, for example. All programming languages also have static site generators you can look up. If you use web frameworks like Laravel or Ruby on Rails, similar features are available as modules.
6. Load Balancer
Load balancing distributes incoming traffic across multiple servers, preventing any single server from becoming overwhelmed.
A web server like Caddy can also function as a powerful load balancer by leveraging its configuration directives to efficiently distribute traffic among multiple backend servers:
Web hosting providers can also offer load-balancing services, and cloud platforms like AWS, Google Cloud, and Azure provide robust load balancing out-of-the-box.
7. Floating IP
When you self-host your services, your domain name typically points directly to a static IP address. This exposes your infrastructure to potential attacks, as adversaries can easily target your IP address, bypassing any CDNs, proxies, or web application firewalls you might have in place.
To mitigate this risk, a floating IP is a dynamic IP address that can be quickly reassigned to different servers, effectively cutting off the attacker’s access.
Many cloud providers, such as Hetzner, offer floating IP services, and it usually takes just a few minutes to configure:
8. Rate Limiting
By imposing restrictions on the number of requests that can be made from a single IP address within a specific timeframe, rate limiting effectively prevents malicious actors from overwhelming your system.
Here’s a basic example of how to configure rate limiting in a Nginx config file:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location /login/ {
limit_req_zone=mylimit;
proxy_pass http://my_upstream;
}
}
The first line defines a shared memory zone used for rate limiting with 10 requests per second limit. The second line applies the rate limiting to the /login/
endpoint, ensuring that no more than 10 requests per second are allowed per IP address.
You can also define rate limits at the application level instead of the server level. For example, in a Node.js application, you can use the express-rate-limit
middleware to set rate limits for specific routes:
import { rateLimit } from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
limit: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
standardHeaders: 'draft-7', // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
// store: ... , // Redis, Memcached, etc. See below.
})
// Apply the rate limiting middleware to all requests.
app.use(limiter)
9. Captcha Bot Protection
DDoS is caused by bots, it’s important to distinguish between bots and humans.
Captcha challenges are digital puzzles designed to be easily solvable by humans but challenging for bots, serving as a crucial line of defense against a variety of threats.
For example, when Cloudflare enables DDoS attack mode on your website, it presents a captcha challenge to visitors to verify their humanity:
A variety of challenge formats, including text-based, image-based, and audio-based options, can help to deter even the most sophisticated bots. By tailoring your captcha strategy to your specific needs and audience, you can effectively protect your website while minimizing inconvenience for legitimate users.
For example, Cloudflare’s captcha challenge will stop cheap bots without slowing down ReadableStream, but it’ll be useless against more advanced AI that can understand and interact with user interfaces. However, even large language models have trouble playing simple games based on logic.
Captchas don’t have to be unsolvable, though. They just need to significantly slow down bots to make them too expensive to run at scale, effectively making DDoS unprofitable.
10. Auth
Authentication is the process of verifying a user’s identity to ensure they are who they claim to be before granting access. Strong authentication measures are key for protecting online infrastructure like non-public APIs, sensitive media files, and any other resources that shouldn’t be open to everyone.
There are two key components to consider when securing access:
- Authentication - Verifying a user’s identity (who they are).
- Authorization - Determining what level of access a user has (what they can do).
Without proper authentication, anyone could potentially stumble upon or exploit these resources.
It’s not just about adding a login/password form to your web page. You can use techniques like Cross-Origin Resource Sharing (CORS) policies to restrict which domains can access your resources. By specifying the allowed origins, methods, and headers, you can prevent unauthorized access and protect your data from malicious actors.
For example, this is how you implement simple CORS policies in Cloudflare serverless page functions:
// Respond to OPTIONS method
export const onRequestOptions = async () => {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Max-Age': '86400',
},
});
};
// Set CORS to all /api responses
export const onRequest = async (context) => {
const response = await context.next();
response.headers.set('Access-Control-Allow-Origin', '*');
response.headers.set('Access-Control-Max-Age', '86400');
return response;
};
Conclusion
DDoS attacks are a serious threat, but you can significantly reduce your risk by following simple steps:
- Identify Self-DDoS risks - Analyze your website code and optimize resource-intensive elements like videos.
- Implement caching strategies - Set appropriate cache policies for static and dynamic content.
- Use a CDN - Sign up with a CDN like Cloudflare.
- Secure your site with a WAF - Consider cloud-based WAF solutions or self-hosted options like Wafris.
- Explore static rendering techniques - Pre-render your website content.
- Implement load balancing - Learn how to configure load balancing with your web server or cloud provider.
- Use a floating IP - use a dynamic IP address to make it harder for attackers to target your infrastructure.
- Enable rate limiting - Limit the number of requests from a single IP address.
- Add Captcha challenges - Deter bots with human-solvable puzzles.
- Enforce authentication and authorization - Implement strong authentication measures and control access to sensitive resources.
- Add CORS policies - Restrict which domains can access your resources with Cross-Origin Resource Sharing policies.
While these steps focus on DDoS attacks, remember that they are often used to mask other malicious activities like phishing and credential theft. To truly secure your development process, consider a robust secret management solution like Onboardbase.
Onboardbase helps development teams securely store and manage sensitive data like API keys, passwords, and other credentials, preventing unauthorized access and mitigating the risks associated with stolen credentials, even after a DDoS attack.
Sign up for a free account today and start securing your development process!
Subscribe to our newsletter
The latest news, articles, features and resources of Onboardbase, sent to your inbox weekly