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

小结

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

相关推荐
敲键盘的Q1 小时前
【eNSP实战】将路由器配置为DHCP服务器
网络
东阳马生架构1 小时前
Netty基础—4.NIO的使用简介二
java·网络·netty
Estrella-q2 小时前
深入理解Linux网络随笔(七):容器网络虚拟化--Veth设备对
linux·网络
遥逖2 小时前
UDP Socket
网络·网络协议·udp
小突突突6 小时前
总结 HTTP 协议的基本格式, 相关知识以及抓包工具fiddler的使用
网络协议·http·fiddler
碳烤小肥杨..8 小时前
DHCP中继实验
网络·网络协议·网络安全
咖啡星人k8 小时前
雷池WAF 处理 HTTP 请求的流程
网络·网络协议·http
Antonio9159 小时前
【网络编程】HTTP网络编程
网络·网络协议·http
lboyj9 小时前
新能源汽车电控系统的大尺寸PCB需求:猎板PCB的技术突围
大数据·网络·人工智能
wanhengidc10 小时前
独立IP服务器的好处都有哪些?
服务器·网络协议·tcp/ip