En .NET puedes restringir ciertos controladores o endpoints para que solo se consuman desde la red interna (intranet o LAN), mientras que otros sigan siendo accesibles desde Internet.
Hay varias formas de lograrlo según tu escenario, pero te explico las tres más usadas (de más simple a más robusta):
🔹 Opción 1: Validar la IP del cliente en los controladores
Puedes agregar un filtro global o atributo personalizado que valide si la IP del cliente pertenece a la red interna (por ejemplo, 192.168.x.x, 10.x.x.x, 172.16.x.x).
Ejemplo práctico:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Net;
public class InternalOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
if (remoteIp == null)
{
context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
return;
}
// Rango privado típico: 192.168.0.0/16
var internalRange = IPNetwork.Parse("192.168.0.0/16");
if (!internalRange.Contains(remoteIp))
{
context.Result = new ContentResult
{
StatusCode = StatusCodes.Status403Forbidden,
Content = "Acceso permitido solo desde la red interna."
};
}
}
}
Luego, lo aplicas a controladores o endpoints específicos:
[ApiController]
[Route("api/[controller]")]
[InternalOnly] // 👈 solo accesible desde red interna
public class AdminInternalController : ControllerBase
{
[HttpGet("status")]
public IActionResult GetStatus() => Ok("Servicio interno funcionando");
}
Los demás controladores siguen funcionando normalmente desde Internet.
🔹 Opción 2: Usar un middleware de restricción por IP
Si tienes varios controladores internos, puedes aplicar la validación de IP en el pipeline antes de llegar al controlador.
app.Use(async (context, next) =>
{
var ip = context.Connection.RemoteIpAddress;
if (context.Request.Path.StartsWithSegments("/api/internal"))
{
var internalNetwork = IPNetwork.Parse("192.168.0.0/16");
if (!internalNetwork.Contains(ip))
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
await context.Response.WriteAsync("Acceso restringido a red interna");
return;
}
}
await next.Invoke();
});
Así, cualquier endpoint bajo /api/internal/... queda protegido.
🔹 Opción 3: Controlarlo a nivel de infraestructura (recomendado para producción)
Si tu servicio está detrás de Nginx, Traefik o un Load Balancer, puedes controlar el acceso directamente desde allí:
Ejemplo Nginx:
location /api/internal {
allow 192.168.0.0/16; # Red interna
deny all; # Denegar el resto
proxy_pass http://localhost:5000;
}
location /api {
proxy_pass http://localhost:5000;
}
De este modo, la API ni siquiera recibe peticiones externas a esos endpoints internos.
✅ Recomendación práctica
| Nivel | Método | Cuándo usarlo |
|---|---|---|
| App (.NET) | Atributo [InternalOnly] o Middleware | Rápido de implementar, útil si no controlas el proxy inverso |
| Infraestructura (Nginx, Firewall) | allow/deny | Más seguro y eficiente; ideal en producción |
| Mixto | Ambos | Seguridad por capas: app + proxy |