.NET Core ASP.NET API에서 외부 IP를 차단하고, 그 차단 목록이 DB에 저장되어 있는 경우, 다음과 같은 방식으로 구현할 수 있습니다.
✅ 구현 전략 요약
- 미들웨어에서 클라이언트 IP 확인
- DB에서 차단된 IP 목록 조회
- 요청이 차단된 IP에서 온 경우 403 Forbidden 반환
✅ 1. 미들웨어 방식 (가장 추천)
ASP.NET Core의 커스텀 미들웨어(Middleware) 를 사용하면 모든 요청 전에 IP를 검사할 수 있습니다.
<IP 차단 미들웨어>
public class IpBlockingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<IpBlockingMiddleware> _logger;
public IpBlockingMiddleware(RequestDelegate next, ILogger<IpBlockingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, IBlockedIpService blockedIpService)
{
var remoteIp = context.Connection.RemoteIpAddress?.ToString();
if (string.IsNullOrEmpty(remoteIp))
{
await _next(context);
return;
}
if (await blockedIpService.IsBlockedAsync(remoteIp))
{
_logger.LogWarning($"Blocked request from IP: {remoteIp}");
context.Response.StatusCode = StatusCodes.Status403Forbidden;
await context.Response.WriteAsync("Forbidden: Your IP is blocked.");
return;
}
await _next(context);
}
}
<서비스 인터페이스>
public interface IBlockedIpService
{
Task<bool> IsBlockedAsync(string ipAddress);
}
<구현예시: EF Core>
public class BlockedIpService : IBlockedIpService
{
private readonly AppDbContext _dbContext;
public BlockedIpService(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<bool> IsBlockedAsync(string ipAddress)
{
return await _dbContext.BlockedIps
.AnyAsync(b => b.IpAddress == ipAddress);
}
}
<미들웨어 등록>
app.UseMiddleware<IpBlockingMiddleware>();
<서비스 등록>
builder.Services.AddScoped<IBlockedIpService, BlockedIpService>();
✅ 2. 성능 최적화 (옵션)
DB 조회가 느릴 수 있으니, 차단 IP를 캐싱하거나 메모리에 로드해 두는 것도 좋습니다.
public class BlockedIpService : IBlockedIpService
{
private readonly IMemoryCache _cache;
private readonly AppDbContext _dbContext;
private static readonly string CacheKey = "BlockedIpList";
public BlockedIpService(AppDbContext dbContext, IMemoryCache cache)
{
_dbContext = dbContext;
_cache = cache;
}
public async Task<bool> IsBlockedAsync(string ipAddress)
{
var blockedIps = await _cache.GetOrCreateAsync(CacheKey, async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
return await _dbContext.BlockedIps
.Select(b => b.IpAddress)
.ToListAsync();
});
return blockedIps.Contains(ipAddress);
}
}
✅ 3. 클라이언트 IP 가져오기 주의점
실제 IP는 프록시를 통해 올 수 있음
var ip = context.Connection.RemoteIpAddress?.ToString();
하지만 프록시 서버나 로드밸런서가 있는 경우에는 X-Forwarded-For 헤더를 사용해야 정확함.
var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault()
?? context.Connection.RemoteIpAddress?.ToString();
⚠️ 주의: X-Forwarded-For는 조작될 수 있으므로 보안 고려 필요
✅ 요약 정리
목적구현 방식
모든 요청에서 IP 차단 | ✅ 커스텀 미들웨어 |
차단 IP는 DB에서 조회 | IBlockedIpService 활용 |
성능 최적화 | MemoryCache 사용 |
실제 클라이언트 IP 확인 | X-Forwarded-For 고려 필요 |