To prevent DoS (Denial of Service) attacks in an ASP.NET Core MVC application, you can implement several strategies, each addressing different aspects of potential vulnerabilities. Here are the common approaches.
1. Rate Limiting and Throttling
- Rate limiting controls the number of requests a client can make within a specific time period, preventing malicious users from overwhelming the server.
- You can use middleware or third-party libraries like AspNetCoreRateLimit to implement rate limiting.
Example. using AspNetCoreRateLimit
dotnet add package AspNetCoreRateLimit
Configure it in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.Configure<IpRateLimitOptions>(options =>
{
options.GeneralRules = new List<RateLimitRule>
{
new RateLimitRule
{
Endpoint = "*",
Limit = 1000,
Period = "5m"
}
};
});
services.AddInMemoryRateLimiting();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseIpRateLimiting();
}
2. Request Size Limiting
Limit the size of requests to prevent large payloads from being used to exhaust server resources.
In Program.cs or Startup.cs
services.Configure<IISServerOptions>(options =>
{
options.MaxRequestBodySize = 10 * 1024; // Set limit to 10KB
});
services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = 10 * 1024; // 10KB
});
3. Timeout Configuration
Set proper timeout values for requests to avoid long-running connections that could hog resources.
In Startup.cs
services.AddHttpClient("myClient")
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) // Set handler timeout
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10))); // Set HTTP request timeout
4. Input Validation
Properly validate user input to avoid potential DoS vulnerabilities caused by computational complexity or resource exhaustion.
- Validate the length, type, and format of input.
- Reject large or malformed data early in the request pipeline.
5. Captcha for Forms
Add CAPTCHAs (e.g., Google reCAPTCHA) to critical forms (login, registration, etc.) to prevent automated bots from generating large numbers of requests.
dotnet add package reCAPTCHA.AspNetCore
Configure in Startup.cs
services.AddRecaptcha(options =>
{
options.SiteKey = "your-site-key";
options.SecretKey = "your-secret-key";
});
6. Distributed Caching for Load Balancing
Use caching to reduce the load on your server, thus preventing resource exhaustion. You can implement caching using MemoryCache, Redis, or NCache.
Example using MemoryCache
services.AddMemoryCache();
7. Use CDN for Static Resources
Offload static resources (images, CSS, JavaScript) to a Content Delivery Network (CDN) to reduce server load.
8. Web Application Firewall (WAF)
Use a WAF to inspect and filter traffic before it reaches your application. WAFs can block suspicious IP addresses, filter out malformed requests, and provide additional security against attacks.
9. Client-Side Caching
Implement proper cache headers to reduce unnecessary server requests by allowing browsers to cache resources.
10. HTTP/2 and Keep-Alive Settings
Tune server settings to prevent resource exhaustion. Ensure HTTP/2 is enabled, which multiplexes requests, and configure Keep-Alive settings.
Example in Startup.cs
services.Configure<KestrelServerOptions>(options =>
{
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
});
Now we will implement the complete project for this article.
Step 1. Create a New ASP.NET Core MVC Project
Create a new ASP.NET Core MVC project via the.NET CLI or Visual Studio.
dotnet new mvc -n DoSAttackPrevention
cd DoSAttackPrevention
Step 2. Install Required NuGet Packages
Install the necessary NuGet packages.
dotnet add package AspNetCoreRateLimit
dotnet add package reCAPTCHA.AspNetCore
Step 3. Configure Services in Startup.cs
Modify Startup.cs to include the middleware and services.
using AspNetCoreRateLimit;
using Microsoft.AspNetCore.HttpOverrides;
using reCAPTCHA.AspNetCore;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Add MVC
services.AddControllersWithViews();
// Memory Cache for Rate Limiting
services.AddMemoryCache();
// Configure Rate Limiting Options
services.Configure<IpRateLimitOptions>(options =>
{
options.GeneralRules = new List<RateLimitRule>
{
new RateLimitRule
{
Endpoint = "*",
Limit = 100,
Period = "1m" // 100 requests per minute per IP
}
};
});
services.AddInMemoryRateLimiting();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
// Add Recaptcha Service
services.AddRecaptcha(options =>
{
options.SiteKey = "your-site-key";
options.SecretKey = "your-secret-key";
});
// Configure Request Size Limit
services.Configure<IISServerOptions>(options =>
{
options.MaxRequestBodySize = 10 * 1024; // 10 KB
});
services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = 10 * 1024; // 10 KB
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseIpRateLimiting(); // Apply Rate Limiting
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Step 4. Add Rate Limiting Configuration
In the appsettings.json file, add rate-limiting options.
{
"IpRateLimit": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"HttpStatusCode": 429,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1m",
"Limit": 100
}
]
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Step 5. Implement CAPTCHA in a Form (e.g., Login Form)
In the Login View (Views/Home/Login.cshtml), implement Google reCAPTCHA.
@using reCAPTCHA.AspNetCore
@inject IRecaptchaService _recaptcha
@{
var recaptchaResult = await _recaptcha.Validate(Request);
}
<form asp-controller="Home" asp-action="Login" method="post">
<div class="form-group">
<label for="Username">Username</label>
<input type="text" class="form-control" id="Username" name="Username" required>
</div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" class="form-control" id="Password" name="Password" required>
</div>
<!-- Google reCAPTCHA -->
<div class="g-recaptcha" data-sitekey="your-site-key"></div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
@section Scripts {
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
}
Step 6. Handle CAPTCHA Validation in the Controller
In the HomeController (Controllers/HomeController.cs), validate the CAPTCHA.
using Microsoft.AspNetCore.Mvc;
using reCAPTCHA.AspNetCore;
public class HomeController : Controller
{
private readonly IRecaptchaService _recaptcha;
public HomeController(IRecaptchaService recaptcha)
{
_recaptcha = recaptcha;
}
[HttpPost]
public async Task<IActionResult> Login(string username, string password)
{
var recaptchaResult = await _recaptcha.Validate(Request);
if (!recaptchaResult.success)
{
ModelState.AddModelError(string.Empty, "CAPTCHA validation failed.");
return View();
}
// Perform login logic here (e.g., validate username/password)
return RedirectToAction("Index");
}
public IActionResult Index()
{
return View();
}
}
Step 7. Implement Input Validation
Ensure that proper validation is applied to forms. For example, in the login form above, you can add validation attributes in the model or controller.
[Required]
[MaxLength(50)]
public string Username { get; set; }
[Required]
[MinLength(6)]
public string Password { get; set; }
Step 8. Configure Caching (Optional)
You can implement caching to reduce server load.
services.AddMemoryCache();
Step 9. Build and Run the Project
You can now run the project.
dotnet run
The project demonstrates rate limiting, request size limiting, and CAPTCHA integration, which are essential measures to prevent DoS attacks. You can extend this further by adding distributed caching (e.g., Redis) and a WAF.
GitHub Project Link: https://github.com/SardarMudassarAliKhan/DoSAttackPrevention
Conclusion
Implementing DoS attack prevention measures in an ASP.NET Core MVC application is essential to protect your application from malicious traffic and resource exhaustion. By leveraging techniques such as rate limiting, request size limiting, CAPTCHA integration, and input validation, you can significantly enhance the security and resilience of your application. These strategies, along with proper caching and server configurations, ensure that your application can handle legitimate traffic while mitigating the risk of potential attacks, keeping both performance and user experience intact.