Sdílet prostřednictvím


Seznam bezpečných IP adres klienta pro ASP.NET Core

Damien Bowden a Tom Dykstra

Tento článek ukazuje tři způsoby implementace seznamu bezpečných IP adres (označovaného také jako seznam povolených) v aplikaci ASP.NET Core. Doprovodná ukázková aplikace ukazuje všechny tři přístupy. Můžete použít:

  • Middleware pro kontrolu vzdálené IP adresy každého požadavku.
  • Filtry akcí MVC pro kontrolu vzdálené IP adresy požadavků pro konkrétní kontrolery nebo metody akcí.
  • Razor Filtry stránek pro kontrolu vzdálené IP adresy požadavků na Razor stránky.

V každém případě se v nastavení aplikace uloží řetězec obsahující schválené IP adresy klienta. Middleware nebo filtr:

  • Parsuje řetězec do pole.
  • Zkontroluje, jestli v poli existuje vzdálená IP adresa.

Přístup je povolený, pokud pole obsahuje IP adresu. Jinak se vrátí stavový kód HTTP 403 Zakázáno.

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Seznam bezpečných IP adres

V ukázkové aplikaci je seznam bezpečných IP adres:

{
  "AdminSafeList": "127.0.0.1;192.168.1.5;::1",
  "Logging": {

V předchozím příkladu jsou povolené adresy 127.0.0.1 IPv4 a 192.168.1.5 adresy ::1 zpětné smyčky IPv6 (komprimovaného formátu pro 0:0:0:0:0:0:0:1).

Middleware

Metoda Startup.Configure přidá vlastní AdminSafeListMiddleware typ middlewaru do kanálu požadavku aplikace. Seznam safelist se načte pomocí zprostředkovatele konfigurace .NET Core a předá se jako parametr konstruktoru.

app.UseMiddleware<AdminSafeListMiddleware>(Configuration["AdminSafeList"]);

Middleware analyzuje řetězec do pole a vyhledá vzdálenou IP adresu v poli. Pokud se vzdálená IP adresa nenajde, middleware vrátí http 403 Zakázáno. Tento proces ověřování se vynechá pro požadavky HTTP GET.

public class AdminSafeListMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AdminSafeListMiddleware> _logger;
    private readonly byte[][] _safelist;

    public AdminSafeListMiddleware(
        RequestDelegate next,
        ILogger<AdminSafeListMiddleware> logger,
        string safelist)
    {
        var ips = safelist.Split(';');
        _safelist = new byte[ips.Length][];
        for (var i = 0; i < ips.Length; i++)
        {
            _safelist[i] = IPAddress.Parse(ips[i]).GetAddressBytes();
        }

        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Method != HttpMethod.Get.Method)
        {
            var remoteIp = context.Connection.RemoteIpAddress;
            _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp);

            var bytes = remoteIp.GetAddressBytes();
            var badIp = true;
            foreach (var address in _safelist)
            {
                if (address.SequenceEqual(bytes))
                {
                    badIp = false;
                    break;
                }
            }

            if (badIp)
            {
                _logger.LogWarning(
                    "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
                context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next.Invoke(context);
    }
}

Filtr akcí

Pokud chcete řízení přístupu řízené seznamem pro konkrétní kontrolery MVC nebo metody akcí, použijte filtr akcí. Příklad:

public class ClientIpCheckActionFilter : ActionFilterAttribute
{
    private readonly ILogger _logger;
    private readonly string _safelist;

    public ClientIpCheckActionFilter(string safelist, ILogger logger)
    {
        _safelist = safelist;
        _logger = logger;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
        _logger.LogDebug("Remote IpAddress: {RemoteIp}", remoteIp);
        var ip = _safelist.Split(';');
        var badIp = true;
        
        if (remoteIp.IsIPv4MappedToIPv6)
        {
            remoteIp = remoteIp.MapToIPv4();
        }
        
        foreach (var address in ip)
        {
            var testIp = IPAddress.Parse(address);
            
            if (testIp.Equals(remoteIp))
            {
                badIp = false;
                break;
            }
        }

        if (badIp)
        {
            _logger.LogWarning("Forbidden Request from IP: {RemoteIp}", remoteIp);
            context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
            return;
        }

        base.OnActionExecuting(context);
    }
}

Do Startup.ConfigureServiceskolekce filtrů MVC přidejte filtr akcí. V následujícím příkladu ClientIpCheckActionFilter se přidá filtr akcí. Seznam bezpečných kódů a instance protokolovacího modulu konzoly se předávají jako parametry konstruktoru.

services.AddScoped<ClientIpCheckActionFilter>(container =>
{
    var loggerFactory = container.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger<ClientIpCheckActionFilter>();

    return new ClientIpCheckActionFilter(
        Configuration["AdminSafeList"], logger);
});
services.AddScoped<ClientIpCheckActionFilter>(_ =>
{
    var logger = _loggerFactory.CreateLogger<ClientIpCheckActionFilter>();
    
    return new ClientIpCheckActionFilter(
        Configuration["AdminSafeList"], logger);
});

Filtr akcí se pak dá použít u kontroleru nebo metody akce s atributem [ServiceFilter] :

[ServiceFilter(typeof(ClientIpCheckActionFilter))]
[HttpGet]
public IEnumerable<string> Get()

V ukázkové aplikaci se filtr akcí použije na metodu Get akce kontroleru. Když aplikaci otestujete odesláním:

  • Požadavek HTTP GET, [ServiceFilter] atribut ověří IP adresu klienta. Pokud je přístup k Get metodě akce povolený, vytvoří se pomocí filtru akcí a metody akce varianta následujícího výstupu konzoly:

    dbug: ClientIpSafelistComponents.Filters.ClientIpCheckActionFilter[0]
          Remote IpAddress: ::1
    dbug: ClientIpAspNetCore.Controllers.ValuesController[0]
          successful HTTP GET    
    
  • Příkaz požadavku HTTP jiný než GET AdminSafeListMiddleware ověří middleware IP adresu klienta.

Razor Filtr stránek

Pokud chcete pro aplikaci Pages řídit přístup řízený seznamem Razor , použijte Razor filtr Stránky. Příklad:

public class ClientIpCheckPageFilter : IPageFilter
{
    private readonly ILogger _logger;
    private readonly IPAddress[] _safelist;

    public ClientIpCheckPageFilter(
        string safelist,
        ILogger logger)
    {
        var ips = safelist.Split(';');
        _safelist = new IPAddress[ips.Length];
        for (var i = 0; i < ips.Length; i++)
        {
            _safelist[i] = IPAddress.Parse(ips[i]);
        }

        _logger = logger;
    }

    public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
    {
        var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
        if (remoteIp.IsIPv4MappedToIPv6)
        {
            remoteIp = remoteIp.MapToIPv4();
        }
        _logger.LogDebug(
            "Remote IpAddress: {RemoteIp}", remoteIp);

        var badIp = true;
        foreach (var testIp in _safelist)
        {
            if (testIp.Equals(remoteIp))
            {
                badIp = false;
                break;
            }
        }

        if (badIp)
        {
            _logger.LogWarning(
                "Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
            context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
            return;
        }
    }

    public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
    {
    }

    public void OnPageHandlerSelected(PageHandlerSelectedContext context)
    {
    }
}

Pokud Startup.ConfigureServiceschcete filtr Stránky povolit Razor , přidejte ho do kolekce filtrů MVC. V následujícím příkladu ClientIpCheckPageFilterRazor se přidá filtr Pages. Seznam bezpečných kódů a instance protokolovacího modulu konzoly se předávají jako parametry konstruktoru.

services.AddRazorPages()
    .AddMvcOptions(options =>
    {
        var logger = LoggerFactory.Create(builder => builder.AddConsole())
                        .CreateLogger<ClientIpCheckPageFilter>();
        var filter = new ClientIpCheckPageFilter(
            Configuration["AdminSafeList"], logger);
        
        options.Filters.Add(filter);
    });
services.AddMvc(options =>
{
    var logger = _loggerFactory.CreateLogger<ClientIpCheckPageFilter>();
    var clientIpCheckPageFilter = new ClientIpCheckPageFilter(
        Configuration["AdminSafeList"], logger);
    
    options.Filters.Add(clientIpCheckPageFilter);
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Když se požaduje indexováRazor stránka ukázkové aplikace, Razor filtr Pages ověří IP adresu klienta. Filtr vytvoří variantu následujícího výstupu konzoly:

dbug: ClientIpSafelistComponents.Filters.ClientIpCheckPageFilter[0]
      Remote IpAddress: ::1

Další materiály