How to Make ASP.NET Core Fixed Global Rate Limiting by IP Address

AddRateLimiter


services.AddRateLimiter(options =>
{
    options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;

    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
    {
        string ipAddress = GetIPAddress(httpContext);

        return RateLimitPartition.GetFixedWindowLimiter(
            partitionKey: ipAddress,
            factory: _ => new FixedWindowRateLimiterOptions
            {
                PermitLimit = 70,
                Window = TimeSpan.FromSeconds(60),
            }
        );
    });
});

Methods to get IP address

public static string GetIPAddress(HttpContext httpContext)
{
    string ipAddress = GetRemoteHostIpAddressUsingXForwardedFor(httpContext)?.ToString();

    if (string.IsNullOrEmpty(ipAddress))
        ipAddress = httpContext.Connection.RemoteIpAddress?.ToString();

    if (string.IsNullOrEmpty(ipAddress))
        ipAddress = GetRemoteHostIpAddressUsingXRealIp(httpContext)?.ToString();

    return ipAddress;
}
private static IPAddress GetRemoteHostIpAddressUsingXForwardedFor(HttpContext httpContext)
{
    IPAddress remoteIpAddress = null;
    string forwardedFor = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();

    if (string.IsNullOrEmpty(forwardedFor) == false)
    {
        List<string> ipList = forwardedFor
            .Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(s => s.Trim())
            .ToList();

        foreach (string ip in ipList)
        {
            if (IPAddress.TryParse(ip, out var address) &&
                (address.AddressFamily is AddressFamily.InterNetwork or AddressFamily.InterNetworkV6))
            {
                remoteIpAddress = address;
                break;
            }
        }
    }

    return remoteIpAddress;
}
private static IPAddress GetRemoteHostIpAddressUsingXRealIp(HttpContext httpContext)
{
    bool xRealIpExists = httpContext.Request.Headers.TryGetValue("X-Real-IP", out var xRealIp);

    if (xRealIpExists)
    {
        if (!IPAddress.TryParse(xRealIp, out IPAddress address))
            return null;

        bool isValidIP = address.AddressFamily is AddressFamily.InterNetwork or AddressFamily.InterNetworkV6;

        if (isValidIP)
            return address;
    }

    return null;
}

UseRateLimiter

app.UseRateLimiter();