如何在ASP.net网站中封锁单个IP地址或国家IP段及实现方法
ASP.NET 封锁单个IP/国家IP段实现方案
下面分原生配置和自定义代码两种方案,适配不同版本的ASP.NET运行环境:
方案1:IIS原生配置(适合ASP.NET 4.x/部署在IIS上的.NET Core项目,无需修改代码)
仅适合简单的单个IP/IP段封锁,依赖IIS功能:
- 先开启IIS的IP和域限制功能:打开服务器管理器→角色和功能→Web服务器(IIS)→安全性→勾选「IP和域限制」,安装完成后重启IIS。
- 打开网站根目录的
web.config文件,在<system.webServer>节点下添加如下配置:
<system.webServer> <security> <ipSecurity allowUnlisted="true"> <!-- 封锁单个IPv4地址 --> <add ipAddress="192.168.1.100" allowed="false" /> <!-- 封锁指定IPv4段,subnetMask为子网掩码 --> <add ipAddress="10.0.0.0" subnetMask="255.0.0.0" allowed="false" /> <!-- 封锁单个IPv6地址 --> <add ipAddress="2001:db8::1" allowed="false" /> </ipSecurity> </security> </system.webServer>
- 配置保存后立即生效,无需重启站点。
方案2:自定义中间件(适合ASP.NET Core/.NET 5+,跨平台,支持国家IP段批量封锁)
灵活性更高,不依赖IIS功能,适合需要批量封锁指定国家所有IP段的场景:
第一步:编写IP封锁中间件
using Microsoft.AspNetCore.Http; using System.Net; using System.Net.Sockets; public class IpBlockMiddleware { private readonly RequestDelegate _next; // 实际项目可改为从appsettings.json/数据库加载黑名单 private static readonly HashSet<IPAddress> _blockedSingleIps = new HashSet<IPAddress> { IPAddress.Parse("192.168.1.100"), IPAddress.Parse("2001:db8::1") }; // 国家IP段存CIDR格式,可提前导出对应国家的CIDR段批量存入 private static readonly List<(IPAddress Network, int PrefixLength)> _blockedCidrRanges = new List<(IPAddress, int)> { // 示例:封锁10.0.0.0/8段 (IPAddress.Parse("10.0.0.0"), 8) }; public IpBlockMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var clientIp = context.Connection.RemoteIpAddress; // 适配IPv4映射的IPv6地址 if (clientIp.IsIPv4MappedToIPv6) { clientIp = clientIp.MapToIPv4(); } // 匹配单个IP黑名单 if (_blockedSingleIps.Contains(clientIp)) { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; await context.Response.WriteAsync("Access denied"); return; } // 匹配CIDR IP段 if (IsIpInCidrRanges(clientIp, _blockedCidrRanges)) { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; await context.Response.WriteAsync("Access denied"); return; } await _next(context); } private bool IsIpInCidrRanges(IPAddress ip, List<(IPAddress Network, int PrefixLength)> ranges) { if (ip.AddressFamily == AddressFamily.InterNetwork) { // IPv4转32位整数做掩码匹配 var ipBytes = ip.GetAddressBytes(); Array.Reverse(ipBytes); uint ipUint = BitConverter.ToUInt32(ipBytes, 0); foreach (var range in ranges) { if (range.Network.AddressFamily != AddressFamily.InterNetwork) continue; var mask = uint.MaxValue << (32 - range.PrefixLength); var networkBytes = range.Network.GetAddressBytes(); Array.Reverse(networkBytes); uint networkUint = BitConverter.ToUInt32(networkBytes, 0); if ((ipUint & mask) == (networkUint & mask)) return true; } } // 需支持IPv6段匹配可自行扩展对应逻辑 return false; } }
第二步:注册中间件
在Program.cs(.NET 6+)或Startup.cs中,将中间件注册到请求管道的最前端,确保所有请求进来优先做IP校验:
// 必须放在UseRouting、UseAuthorization等其他中间件之前 app.UseMiddleware<IpBlockMiddleware>();
注意事项
- 如果网站使用了CDN、反向代理,需要先配置转发头获取真实客户端IP:ASP.NET Core中需先注册
UseForwardedHeaders中间件,并且配置信任的代理服务器IP,否则会误封CDN节点IP。 - 国家IP段可以提前导出对应国家的所有CIDR格式段,批量存入配置或数据库,项目启动时加载到内存即可,无需每次请求查库。
内容的提问来源于stack exchange,提问作者DHY
相关产品推荐
相关产品推荐

