Hoje veremos como bloquear endereços IP em uma aplicação ASP.NET Core Web API. |
O bloqueio de endereços IP é um recurso útil se quisermos garantir que usuários
mal-intencionados conhecidos não tenham acesso ao nosso aplicativo. Essa
abordagem permite o acesso a API e define apenas a lista de endereços IP a serem
bloqueados pelo nosso aplicativo.
Da mesma forma, podemos decidir permitir que apenas uma
determinada lista de endereços IP acesse nosso aplicativo, adotando a abordagem
de bloquear o acesso a todos e permitir que apenas entidades conhecidas e
confiáveis acessem nossa API.
Ambos os métodos são maneiras válidas de restringir o
acesso ao nosso aplicativo com base no endereço IP e, logicamente, no código, há
pouca diferença na implementação.
Formas de bloquer o endereço IP
A ASP.NET Core nos fornece duas maneiras diferentes de bloquear o acesso de
endereços IP aos nossos aplicativos.
Em primeiro lugar, podemos optar por implementar o bloqueio em todo o aplicativo
para cada solicitação que nosso aplicativo recebe, por meio do Middleware
ASP.NET Core .
A segunda opção é usar filtros de ação, permitindo que sejamos mais seletivos sobre quais controladores ou até endpoints específicos desejamos aplicar o bloqueio.
Vamos apresentar uma implementação das duas opções.
Criando o projeto API
Vamos usar o VS 2022 no ambiente do .NET6 e criar um projeto ASP.NET Core Web API chamado ApiBloqueioIP.
No projeto vamos criar um controlador chamado BloqueioIPController e definir dois endpoints que iremos usar para teste:
using Microsoft.AspNetCore.Mvc;
namespace ApiBloqueioIp.Controllers;
[Route("api/[controller]")]
[ApiController]
public class BloqueioIPController : ControllerBase
{
[HttpGet("desbloqueado")]
public string Desbloqueado()
{
return $"Acesso Desbloqueado para este endpoint : {DateTime.Now}";
}
[HttpGet("bloqueado")]
public string Bloqueado()
{
return $"Acesso BLOQUEADO para este endpoint : {DateTime.Now}";
}
}
|
Implementando o serviço para bloquear IPs
Agora vamos criar um serviço que pode usar tanto middleware como Action Filters para realizar o bloqueio de ips.
Crie uma pasta Services no
projeto e nesta pasta vamos criar a interface
IBloquearIPService :
using System.Net;
namespace ApiBloqueioIp.Services;
public interface IBloquearIPService
{
bool EstaBloqueado(IPAddress ipAddress);
}
|
A seguir vamos criar a classe BloquearIPService :
using System.Net;
namespace ApiBloqueioIp.Services;
public class BloquearIPService : IBloquearIPService
{
private readonly List<string> _IpsBloqueados;
public BloquearIPService(IConfiguration configuration)
{
var IpsBloqueados = configuration.GetValue<string>("IPsBloqueados");
_IpsBloqueados = IpsBloqueados.Split(',').ToList();
}
public bool EstaBloqueado(IPAddress ipAddress) => _IpsBloqueados.Contains(ipAddress.ToString());
}
|
Neste código injetamos a interface
IConfiguration e a usamos para obter o valor dos Ips bloqueados em
IPsBloqueados
do arquivo
appsettings.json, que é uma lista de endereços IP
separados por vírgula.
Finalmente, chamamos o método
EstaBloqueado()
para verificar se nossa lista
_IpsBloqueados
contém
o parâmetro ipAddress.
Precisamos agora definir no arquivo appsettings.json uma seção chamada : IPsBloqueados onde iremos definir os IPs que desejamos bloquear:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"IPsBloqueados": ""
}
|
Para conlcuir
vamos registrar nosso serviço como um serviço com tempo de vida Transient na
classe Program:
builder.Services.AddTransient<IBloquearIPService
,
BloquearIPService
>();
Com o serviço criado, vamos ver como bloquear o acesso ao nosso aplicativo
usando o middleware ASP.NET Core.
Criando um middleware de bloqueio de IP
Vamos criar agora um middleware para realizar o bloqueio de IPs criando a classe BloquearIPMiddleware na pasta Services :
using System.Net;
namespace ApiBloqueioIp.Services;
public class BloquearIPMiddleware
{
private readonly RequestDelegate _next;
private readonly IBloquearIPService _bloquearIpService;
public BloquearIPMiddleware(RequestDelegate next, IBloquearIPService bloquearIpService)
{
_next = next;
_bloquearIpService = bloquearIpService;
}
public async Task Invoke(HttpContext context)
{
var remoteIp = context.Connection.RemoteIpAddress;
var estaBloqueado = _bloquearIpService.EstaBloqueado(remoteIp!);
if (estaBloqueado)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}
await _next.Invoke(context);
}
}
|
Entendendo o código :
Primeiro, injetamos RequestDelegate,
que é uma função que pode processar uma solicitação HTTP. Ele representa o
próximo delegado no pipeline que manipulará a solicitação HTTP.
A seguir injetamos a interface
IBloquearIPService
.
Em seguida, o método Invoke() toma o HttpContext
atual como parâmetro, o que nos permite recuperar o endereço IP do request atual
por meio de context.Connection.RemoteIpAddress.
Depois passamos esse endereço IP para o método
EstaBloqueado()
para verificar se o IP deve ser bloqueado e, se for, configuramos
context.Response.StatusCode para
Forbidden e retornamos do método.
Para concluir se o endereço IP não estiver bloqueado,
chamamos Invoke() em RequestDelegate para
garantir que a solicitação continue pelo restante do pipeline de middleware.
Com nosso middleware definido, podemos adicioná-lo ao pipeline na classe
Program:
...
var app = builder.Build();
//middleware para bloquear ips
app.UseMiddleware<BloquearIPMiddleware>();
...
|
Testando a implementação
Para testar vamos criar uma aplicação ASP .NET Core MVC no VS 2022 e definir o seguinte código na classe Program:
var
baseUrl =
"https://localhost:7224/"; builder.Services.AddScoped(sp => new HttpClient{ BaseAddress = new Uri(baseUrl) }); |
Aqui definimos o endereço para acessar a nossa API que esta atendendo em https://localhost:7224/
A seguir no controlador HomeController vamos criar o método Action ConsomeAPI com o seguinte código:
public async Task<IActionResult> ConsomeAPI()
{
var response = await _httpClient.GetAsync($"api/bloqueioip/bloqueado");
if (response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.NoContent)
{
ViewBag.Resultado = $"Status Code : {response.StatusCode}";
return View();
}
var resultado = await response.Content.ReadAsStringAsync();
ViewBag.Resultado = resultado;
}
else
{
var message = await response.Content.ReadAsStringAsync();
ViewBag.Resultado = $"Status Code : {response.StatusCode} {message}";
_logger.LogError($" Não foi possivel acessar o endpoint - {message}");
}
return View();
}
|
A nossa view ConsomeAPI é bem simples e apenas exibe o resultado :
@model
string < p class="text-danger"> <h3>@ViewBag.Resultado</h3></ p> |
Para restringir o
acesso ao nosso IP vamos definir no arquivo appsettings
da API os seguintes valores :
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "IPsBloqueados": "127.0.0.0,::1" } |
Executando o projeto teremos a pagina inicial:
Tentando acessar qualquer um dos endpoints da API iremos
obter o resultado abaixo:
Usando o middleware
bloqueamos o IP para acessar todos os endpoints da nossa API.
Na próxima parte do artigo veremos como usar um filtro
para restringir o acesso de um IP.
Pegue o código aqui : ApiBloqueioIp.zip ...
"Porque os que são segundo a carne inclinam-se para as coisas da carne; mas os
que são segundo o Espírito para as coisas do Espírito. Porque a inclinação da
carne é morte; mas a inclinação do Espírito é vida e paz."
Romanos 8:5,6
Referências: