An ASP.NET Core MVC application can be protected against DoS (Denial of Service) attacks by implementing a number of solutions, each of which addresses a different component of possible vulnerability. These are the standard methods.


1. Throttling and rate limitation

  • Rate limitation stops malevolent users from flooding the server with requests by restricting the amount of requests a client can make in a certain amount of time.
  • Rate limitation can be implemented by middleware or third-party libraries such as AspNetCoreRateLimit.

Using AspNetCoreRateLimit as an example
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.csservices.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 MemoryCacheservices.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 PackagesInstall the necessary NuGet packages.
dotnet add package AspNetCoreRateLimit
dotnet add package reCAPTCHA.AspNetCore
Step 3. Configure Services in Startup.csModify 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.