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:,以便进行准确的校验。

小结

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

相关推荐
易天ETU1 小时前
短距离光模块 COB 封装与同轴工艺的区别有哪些
网络·人工智能·光模块·光通信·cob·qsfp28·100g
明月心9521 小时前
IP 中 0/24 和 0/16 的区别
linux·服务器·网络·ip
李洛克071 小时前
RDMA CM UDP 通信完整指南
单片机·网络协议·udp
Kapibalapikapi2 小时前
工具 | netcat, netstat
网络·笔记·逆向
福尔摩斯张2 小时前
基于C++的UDP网络通信系统设计与实现
linux·c语言·开发语言·网络·c++·tcp/ip·udp
北京耐用通信2 小时前
终结混合网络调试噩梦:耐达讯自动化实现EtherCAT对DeviceNet设备的直接读写
网络·人工智能·物联网·网络协议·自动化·信息与通信
Henry Zhu1233 小时前
VPP中的DPDK插件源码详解第一篇:DPDK插件的作用和意义以及整体架构
运维·服务器·网络·计算机网络·云原生
分***83 小时前
新版局域网IP扫描神器IPScanner.exe 绿色版V1.28.2,支持跨网段扫描_端口扫描_系统端口查看工具
网络·tcp/ip·端口扫描·ipscanner·局域网扫描
千天夜3 小时前
文件系统磁盘块分配方式:从隐式链接到索引结构
网络·网络协议
2501_915918413 小时前
HTTPS 端口深度解析,443 并不是唯一入口,理解 TLS 流量行为与抓包策略
网络协议·http·ios·小程序·https·uni-app·iphone