NetCore项目实现IP黑名单功能

文章目录

前言

使用场景:使用IP黑名单防止已知恶意 IP 地址的访问,降低系统被攻击的风险。阻止来自特定 IP 地址的大量请求,可以减轻分布式拒绝服务(DDoS)攻击的影响。通过监控访问日志,可以发现异常访问行为,并将可疑 IP 地址加入黑名单进而拒绝特别IP访问网站。

使用技术:Net8.0,Redis缓存(用来存储黑名单IP)

代码配置

首先创建中间件页面

csharp 复制代码
 public class IpBlacklistMiddleware
 {
     private readonly RequestDelegate next;
     private IIpBlacklistService _blacklistManager;

     public IpBlacklistMiddleware(RequestDelegate next, IIpBlacklistService blacklistManager)
     {
         this.next = next;
         _blacklistManager = blacklistManager;
     }

     public async Task InvokeAsync(HttpContext context)
     {
         //获取到用户真实IP地址
         var remoteIp = context.GetUserIp()?.Replace("::ffff:", "");

         // 检查 IP 是否在黑名单中
         if (!string.IsNullOrEmpty(remoteIp) && _blacklistManager.IsIpBlacklisted(remoteIp))
         {
             // 返回 403 Forbidden 状态码
             context.Response.StatusCode = StatusCodes.Status403Forbidden;
             await context.Response.WriteAsync("您的IP被列入黑名单");
             return;
         }
         await next(context);
     }
 }

中间件属于全局规则 ,比如请求控制器接口、服务器图片路径、css文件、js文件等等,即使静态文件请求也会进行拦截处理 。而Ip中间件的作用就是:当用户访问网站的时候,请求到达服务器后会先进入Ip中间件进行校验当前用户网络IP是否存储在Redis黑名单里面,如果是黑名单IP,直接驳回网络请求,不允许当前用户访问网站并返回403状态码

中间件可以在应用程序的整个生命周期中应用于所有请求,而无需在每个控制器中重复定义,所以只需要定义一遍就可以了。

其次注册服务和中间件
在 Program.cs 中注册 Redis 服务和中间件:

csharp 复制代码
var builder = WebApplication.CreateBuilder(args);

//reids配置
builder.Services.AddSingleton(new RedisService(builder.Configuration["Redis:ConnectionString"]));

builder.Services.AddControllers();

var app = builder.Build();

// Ip中间件
app.UseMiddleware<IpBlacklistMiddleware>();

app.UseAuthorization();

app.MapControllers();

app.Run();

这时候在网站运行的时候,就已经开启了中间件全局拦截。

然后再填写Redis的配置

在appsettings.json里面填写redis的连接配置:

csharp 复制代码
 "RedisConn": "127.0.0.1,Password=111111,SyncTimeout=15000", //redis连接字符串

在redis公共方法里面进行配置:

csharp 复制代码
 public RedisCacheService()
  {
      var csredis = new CSRedisClient(AppSetting.RedisConnectionString);
      RedisHelper.Initialization(csredis);
  }
csharp 复制代码
 public class IpBlacklistService : IIpBlacklistService
 {
     private RedisCacheService _redisCacheService;
     private const string BlacklistKey = "ip_blacklist";

     public IpBlacklistService(RedisCacheService redisCacheService)
     {
         _redisCacheService = redisCacheService;
     }

     //添加 IP 到黑名单
     public bool AddIp(string ip)
     {
         if (!string.IsNullOrWhiteSpace(ip))
         {
             _redisCacheService.SAddToSet(BlacklistKey, ip);
             return true;
         }
         return false;
     }
     //检查 IP 是否在黑名单中
     public bool IsIpBlacklisted(string ip)
     {
         if (string.IsNullOrWhiteSpace(ip))
         {
             return false;
         }
         // 使用 RedisCacheService 检查 IP 是否在黑名单中
         return _redisCacheService.Exists(BlacklistKey) &&
                _redisCacheService.IsMember(BlacklistKey, ip);
     }

     //从黑名单中移除 IP
     public bool RemoveIp(string ip)
     {
         if (!string.IsNullOrWhiteSpace(ip))
         {
             _redisCacheService.RemoveFromSet(BlacklistKey, ip);
             return true;
         }
         return false;
     }
 }

然后在控制器中编写Api

csharp 复制代码
[JWTAuthorize]
[Route("/api/IpBlack")]
public class IpBlackController : Controller
{
    private readonly IIpBlacklistService _ipBlacklistService;
    public IpBlackController(IIpBlacklistService ipBlacklistService)
    {
        _ipBlacklistService = ipBlacklistService;
    }
    // 添加 IP 到黑名单
    [HttpPost, Route("Add"), AllowAnonymous]
    public ActionResult AddIp(string ip)
    {
        if (string.IsNullOrWhiteSpace(ip))
        {
            return Json(false);
        }
        try
        {
            var result = _ipBlacklistService.AddIp(ip);
            return Json(new { code = 200, status=result });
        }
        catch (Exception ex)
        {
            return Json(new { code = 400, status = false });
        }
    }
    [HttpPost("Remove")]
    //[ApiActionPermission(ActionRolePermission.SuperAdmin)]
    [AllowAnonymous]
    public ActionResult RemoveIp([FromBody] string ip)
    {
        if (string.IsNullOrWhiteSpace(ip))
        {
            return Json(false);
        }
        var result = _ipBlacklistService.RemoveIp(ip);
        return Json(result);
    }

注意:项目使用了Jwttoken进行身份验证,但是ip黑名单的接口不需要身份验证,所以在接口头部增加AllowAnonymous取消身份验证。

到此代码开发部分算是完成。

下面可以增加一些测试:使用Postman增加黑名单Ip

然后在redis里面就可以看到已经存在当前Ip值。

最后使用Jmeter测试工具进行对接口添加到Redis的数据性能测试。

并发生成5000条数据,没有问题,校验redis并发添加问题。

技术细节

在本地开发阶段,为了顺利进行项目开发,以下工具和配置是必需的:

1.Redis 客户端:

在本地电脑上安装 Redis 客户端,例如 RedisDesktopManager。这样可以方便地管理和查看 Redis 数据库中的数据。

注意:如果项目中配置的 Redis 地址指向本地,但本地未安装 Redis,将会导致连接错误。
2.性能测试:

使用 JMeter 软件进行性能测试,可以模拟大量用户请求,以评估系统的响应能力和稳定性。
3.接口测试:

使用 Postman 进行接口测试,方便地发送请求并查看返回结果,确保 API 的正确性和性能。
4.IP 校验:

在校验用户 IP 时,需要注意获取到的 IP 地址可能是 IPv6 格式。在这种情况下,需要去除前缀 ::ffff:,以便进行准确的校验。

小结

代码不算多,也容易理解,主要是各种工具的配合使用需要慢慢去配置,这个需要花费一些时间来熟悉。

相关推荐
黑客呀19 分钟前
软考网络安全专业
网络·安全·web安全
ssr——ssss35 分钟前
网络华为HCIA+HCIP数据链路层协议-以太网协议
网络·华为
EPSDA40 分钟前
介绍HTTP协议基本结构与Linux中基本实现HTTPServer
linux·运维·开发语言·c++·网络协议·tcp/ip·http
冬冬小圆帽1 小时前
axios的二次封装
网络
敲键盘的Q2 小时前
【eNSP实战】将路由器配置为DHCP服务器
网络
东阳马生架构3 小时前
Netty基础—4.NIO的使用简介二
java·网络·netty
Estrella-q3 小时前
深入理解Linux网络随笔(七):容器网络虚拟化--Veth设备对
linux·网络
遥逖3 小时前
UDP Socket
网络·网络协议·udp
小突突突7 小时前
总结 HTTP 协议的基本格式, 相关知识以及抓包工具fiddler的使用
网络协议·http·fiddler
碳烤小肥杨..9 小时前
DHCP中继实验
网络·网络协议·网络安全