Wrapper around abuseipdb.com API for .net
PM> Install-Package Kenc.AbuseIPDB
Kenc.AbuseIPDb is built with dependency-injection as a first-class-citizen. As a result, there's a helper function to register the library including pointing to the configuration section, if IConfiguration is being utilized.
services.AddAbuseIPDBClient(Configuration.GetSection("AbuseIPDB"));
with the configuration section "AbuseIPDB" having the following settings:
"AbuseIPDB": {
"APIKey": "<APIKey>",
"APIEndpoint": "https://api.abuseipdb.com/api/v2/"
}
Note: Don't embed your API key with your source code, load it from keyvault or another secure storage.
With the client registered with dependency injection, add IAbuseIPDBClient abuseIPDBClient to your constructor, eg:
private readonly ILogger<HomeController> _logger;
private readonly IAbuseIPDBClient _abuseIPDBClient;
private readonly IHttpContextAccessor _httpContextAccessor;
public HomeController(ILogger<HomeController> logger, IAbuseIPDBClient abuseIPDBClient, IHttpContextAccessor httpContextAccessor)
{
_logger = logger;
_abuseIPDBClient = abuseIPDBClient ?? throw new ArgumentNullException(nameof(abuseIPDBClient));
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
In an ASP.net MVC app, to check for an abusive IP:
[HttpPost]
public async Task<IActionResult> PostComment(CommentModel comment)
{
var ip = _httpContextAccessor.HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
try
{
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
(Check abuseCheck, _) = await _abuseIPDBClient.CheckAsync(ip.ToString(), 90, false, cancellationTokenSource.Token);
if (abuseCheck.AbuseConfidenceScore > 70)
{
_logger.LogWarning($"{nameof(HomeController)} refused comment by {ip} due to high abuse confidence score.");
var error = new ErrorModel
{
Title = "Bad Request.",
Detail = "User IP is blocked due to abuse.",
Instance = $"/comment/{Activity.Current?.Id ?? httpContextAccessor.HttpContext.TraceIdentifier}",
Status = 400,
Type = "/comment/abusiveip"
};
// return a 400 with the error information
return Unauthorized(error);
}
}
catch (OperationCanceledException)
{
_logger.LogError($"{nameof(HomeController)}: Failed to check AbuseIPDb within configured timeout.");
}
catch (ApiException abuseIPException)
{
_logger.LogError($"{nameof(HomeController)}: Caught error with AbuseIPDB: {abuseIPException.Message}");
}
}
In case you have a website with a significant amount of traffic, or where users are expected to send multiple requests, consider using the cached IAbuseIPDBClient. This adds a memory cache in-front, so only a single lookup per IP/block is made.
PM> Install-Package Kenc.AbuseIPDB
Register it with dependency injection using:
services.AddAbuseIPDBClientCache(Configuration.GetSection("AbuseIPDB"), Configuration.GetSection("AbuseIPDBCache"));
The configuration section can be used to configure for how long values are cached.
Name | Default |
---|---|
CheckCacheLifetime | 1 hour |
CheckBlockCacheLifetime | 1 hour |
BlackListCacheLifetime | 24 hours |
Configuration values are deserialized into TimeSpan. By default these follow ISO 8601 durations
The following sets the configurations to keep Check() responses for 1 minute, CheckBlock() responses for 2 hours and 30 minutes and lastly BlackList() checks for 36 hours.
{
"AbuseIPDBCache": {
"CheckCacheLifetime": "PT1M",
"CheckBlockCacheLifetime": "PT2H30M",
"BlackListCacheLifetime": "PT36H"
}
}