Firewall para servidores sgcWebSockets

· Componentes

La seguridad ya no es opcional. Todo servidor WebSocket expuesto a internet es un objetivo de ataques por fuerza bruta, intentos de inyección, flooding de conexiones y abuso automatizado. Defenderse de estas amenazas suele implicar atornillar middleware externo, escribir lógica de filtrado a medida o desplegar un proxy inverso aparte —todo lo cual añade complejidad y ralentiza el desarrollo.

sgcWebSockets 2026.4.0 incorpora TsgcWSFirewall —un componente firewall dedicado que se conecta directamente a tu servidor WebSocket, ahora con 15 módulos de protección que incluyen filtrado por país con GeoIP, puntuación de amenazas adaptativa, escalado progresivo de baneos y un motor de reglas personalizadas. Coloca el componente, configura los módulos de protección que necesites, asígnalo al servidor y tu aplicación queda protegida. Sin dependencias externas. Sin middleware. Sin código a medida para los casos habituales.

Este artículo cubre todo el conjunto de funcionalidades y muestra cómo configurar cada módulo de protección en Delphi.

Quince módulos de protección, un único componente

El firewall proporciona quince módulos de protección independientes. Habilita sólo los que necesites —cada módulo funciona por sí solo o combinado con los demás.

Blacklist de IPs
Bloquea direcciones IP concretas o rangos enteros usando notación CIDR. Las conexiones desde IPs en blacklist se rechazan antes de llegar a tu código de aplicación.
Whitelist de IPs
Define una lista de IPs de confianza. Cuando está habilitada, las direcciones en whitelist saltan todas las demás comprobaciones de seguridad —ideal para servicios internos y herramientas de monitorización.
Protección contra fuerza bruta
Rastrea intentos de autenticación fallidos por IP. Banea automáticamente a los infractores tras superar un umbral configurable dentro de una ventana temporal deslizante.
Detección de SQL injection
Escanea los mensajes entrantes en busca de patrones comunes de SQL injection. Detección integrada para boolean injection, UNION SELECT, statement injection y más.
Detección de XSS
Detecta payloads de cross-site scripting en los mensajes. Captura etiquetas script, manejadores de eventos, URIs con protocolo JavaScript, inyección de iframes y expresiones CSS.
Rate limiting de conexiones
Limita el número de conexiones concurrentes por dirección IP. Evita que un solo cliente agote los recursos del servidor.
Protección contra message flooding
Limita el número de mensajes por segundo que puede enviar una IP. Protege frente a patrones de message flooding y denial of service.
Límite de tamaño de payload
Rechaza los mensajes que superen un umbral máximo de tamaño. Evita el agotamiento de memoria por payloads sobredimensionados.
Detección de path traversal
Detecta secuencias de directory traversal en los mensajes. Bloquea intentos de acceder a archivos fuera del ámbito previsto.
Detección de command injection
Detecta patrones de inyección de comandos del sistema en los mensajes. Bloquea metacaracteres de shell y secuencias de comandos habituales.
Filtrado por país con GeoIP
Permite o bloquea conexiones según su origen geográfico. Admite modos blocklist y allowlist con búsqueda en una base de datos CSV.
Sistema de threat score
Acumula puntuaciones ponderadas por IP a través de todos los tipos de violación. Banea automáticamente al alcanzar el umbral, con decaimiento automático con el tiempo.
Escalado progresivo de baneos
Aumenta la duración del baneo con cada reincidencia. Escala desde baneos cortos hasta bloqueos permanentes para infractores reiterados.
Protección WebSocket
Valida los orígenes WebSocket, aplica límites de tamaño de frame y filtra subprotocolos. Protección a nivel de protocolo más allá del contenido del mensaje.
Motor de reglas personalizadas
Define tus propias reglas de firewall con condiciones y acciones. Crea umbrales de violación, ventanas temporales y respuestas automatizadas.

Inicio rápido

Poner en marcha el firewall requiere sólo tres pasos: crear, configurar y asignar.

var
  oFirewall: TsgcWSFirewall;
  oServer: TsgcWebSocketHTTPServer;
begin
  oFirewall := TsgcWSFirewall.Create(nil);
  oFirewall.Enabled := True;
  // Enable the modules you need
  oFirewall.Blacklist.Enabled := True;
  oFirewall.Blacklist.IPs.Add('10.0.0.0/8');
  oFirewall.RateLimit.Enabled := True;
  oFirewall.RateLimit.MaxConnectionsPerIP := 5;
  oFirewall.SQLInjection.Enabled := True;
  oFirewall.XSS.Enabled := True;
  // Assign to any server component
  oServer.Firewall := oFirewall;
  oServer.Active := True;
end;

Una vez asignado, el firewall se integra automáticamente: las conexiones se comprueban antes de llegar a tus manejadores de eventos, los mensajes se escanean en tiempo real y los clientes desconectados se desregistran del seguimiento —todo sin escribir una sola línea de código de manejo de eventos.

Blacklist y whitelist de IPs

La blacklist rechaza conexiones desde IPs o rangos concretos. La whitelist hace lo contrario —define un conjunto de direcciones de confianza que saltan todas las demás comprobaciones, incluyendo el filtrado de mensajes.

Ambas admiten direcciones IP exactas y notación CIDR para filtrado por rangos:

// Blacklist: block entire subnets and specific IPs
oFirewall.Blacklist.Enabled := True;
oFirewall.Blacklist.IPs.Add('10.0.0.0/8');        // All 10.x.x.x
oFirewall.Blacklist.IPs.Add('172.16.0.0/16');     // All 172.16.x.x
oFirewall.Blacklist.IPs.Add('192.168.1.100');     // Single IP
// Whitelist: trusted IPs bypass everything
oFirewall.Whitelist.Enabled := True;
oFirewall.Whitelist.IPs.Add('192.168.1.1');       // Admin machine
oFirewall.Whitelist.IPs.Add('192.168.1.0/24');    // Internal network

Prioridad. Cuando la whitelist está habilitada, se comprueba primero. Si la IP coincide, la conexión se permite inmediatamente —se saltan blacklist, baneos, rate limits y filtros de mensajes.

Protección contra fuerza bruta

El módulo de fuerza bruta rastrea los intentos de autenticación fallidos por IP usando una ventana temporal deslizante. Cuando una IP supera el número máximo de intentos dentro de la ventana, se banea automáticamente durante una duración configurable.

Propiedad Por defecto Descripción
MaxAttempts 5 Intentos fallidos antes del baneo
TimeWindowSec 60 Ventana deslizante en segundos para contar intentos
BanDurationSec 300 Duración del baneo en segundos (0 = permanente)
// Ban after 3 failed logins within 60 seconds, for 10 minutes
oFirewall.BruteForce.Enabled := True;
oFirewall.BruteForce.MaxAttempts := 3;
oFirewall.BruteForce.TimeWindowSec := 60;
oFirewall.BruteForce.BanDurationSec := 600;
// Register failed attempts from your authentication handler
procedure TForm1.ServerAuthentication(Connection: TsgcWSConnection;
  aUser, aPassword: String; var Authenticated: Boolean);
begin
  Authenticated := ValidateCredentials(aUser, aPassword);
  if not Authenticated then
    oFirewall.RegisterFailedAttempt(Connection.IP);
end;

El firewall gestiona automáticamente el resto: cuenta los intentos, comprueba la ventana temporal y banea la IP cuando se alcanza el umbral. Las IPs baneadas se rechazan a nivel de conexión antes de cualquier procesamiento posterior.

Gestión manual de baneos

Además de los baneos automáticos, puedes gestionar baneos por código en cualquier momento:

// Ban an IP for 1 hour
oFirewall.BanIP('203.0.113.50', 3600);
// Permanent ban (duration = 0)
oFirewall.BanIP('198.51.100.10');
// Check ban status
if oFirewall.IsBanned('203.0.113.50') then
  WriteLn('IP is banned');
// Remove a specific ban
oFirewall.UnbanIP('203.0.113.50');
// Clear all bans
oFirewall.ClearBans;

Detección de SQL injection

El módulo de SQL injection escanea cada mensaje de texto entrante en busca de patrones de ataque habituales. Cuando se detecta una coincidencia, la acción configurable determina la respuesta: bloquear al cliente, registrar el evento o dejarlo pasar.

oFirewall.SQLInjection.Enabled := True;
oFirewall.SQLInjection.Action := faDeny;  // faDeny, faLog, or faAllow
// Add custom patterns beyond the built-in set
oFirewall.SQLInjection.CustomPatterns.Add('WAITFOR DELAY');
oFirewall.SQLInjection.CustomPatterns.Add('BENCHMARK(');

Patrones integrados

El detector incluye comprobaciones insensibles a mayúsculas para las técnicas de SQL injection más habituales:

Detección de XSS

El módulo XSS detecta payloads de cross-site scripting en los mensajes WebSocket antes de que puedan llegar a la lógica de tu aplicación o ser retransmitidos a otros clientes.

oFirewall.XSS.Enabled := True;
oFirewall.XSS.Action := faDeny;

La detección integrada cubre:

Rate limiting de conexiones

Limita el número de conexiones concurrentes que puede mantener una sola dirección IP. Esto evita el agotamiento de recursos por parte de clientes que abren conexiones excesivas, ya sea de forma maliciosa o por mala configuración.

// Allow up to 5 concurrent connections per IP
oFirewall.RateLimit.Enabled := True;
oFirewall.RateLimit.MaxConnectionsPerIP := 5;
oFirewall.RateLimit.TimeWindowSec := 60;

El seguimiento de conexiones es totalmente automático: el firewall incrementa el contador al conectar y lo decrementa al desconectar. Cuando una nueva conexión superaría el límite, se rechaza antes de que se dispare el evento OnConnect del servidor.

Protección contra message flooding

Limita el número de mensajes por segundo que puede enviar una IP. Esto protege frente a patrones de denial of service en los que un cliente envía mensajes rápidamente para saturar el servidor u otros clientes conectados.

// Limit to 50 messages per second per IP
oFirewall.FloodProtection.Enabled := True;
oFirewall.FloodProtection.MaxMessagesPerSec := 50;
oFirewall.FloodProtection.Action := faDeny;  // Disconnect offender

Límite de tamaño de payload

Aplica un tamaño máximo de mensaje para evitar que los clientes envíen payloads sobredimensionados que puedan agotar la memoria del servidor. Los mensajes que superan el umbral se rechazan antes de procesarse.

oFirewall.PayloadLimit.Enabled := True;
oFirewall.PayloadLimit.MaxSizeBytes := 65536;  // 64 KB max
oFirewall.PayloadLimit.Action := faDeny;

Detección de path traversal

El módulo de path traversal escanea los mensajes entrantes en busca de secuencias de directory traversal que intentan acceder a archivos fuera del ámbito previsto. Esto es crítico para aplicaciones que procesan rutas de archivo o identificadores de recursos a partir de los mensajes del cliente.

La detección integrada cubre:

oFirewall.PathTraversal.Enabled := True;
oFirewall.PathTraversal.Action := faDeny;

Detección de command injection

El módulo de command injection detecta patrones de inyección de comandos del sistema en los mensajes. Captura metacaracteres de shell y secuencias de comandos habituales usadas para ejecutar comandos arbitrarios en el sistema.

La detección integrada cubre:

oFirewall.CommandInjection.Enabled := True;
oFirewall.CommandInjection.Action := faDeny;

Filtrado por país con GeoIP

Filtra conexiones según su origen geográfico usando resolución de IP a país. El módulo GeoIP admite dos modos: BlockList (bloquea países concretos, permite todo lo demás) y AllowList (permite sólo países concretos, bloquea todo lo demás).

Propiedad Descripción
Mode gmBlockList o gmAllowList
Countries códigos de país ISO 3166-1 alpha-2 (por ejemplo, US, GB, DE)
DatabaseFile ruta al archivo CSV para la resolución de IP a país

Bloquear países concretos

oFirewall.GeoIP.Enabled := True;
oFirewall.GeoIP.Mode := gmBlockList;
oFirewall.GeoIP.Countries.Add('CN');
oFirewall.GeoIP.Countries.Add('RU');
oFirewall.LoadGeoIPDatabase('geoip.csv');

Permitir sólo países concretos

// Only allow connections from US, UK, and Germany
oFirewall.GeoIP.Enabled := True;
oFirewall.GeoIP.Mode := gmAllowList;
oFirewall.GeoIP.Countries.Add('US');
oFirewall.GeoIP.Countries.Add('GB');
oFirewall.GeoIP.Countries.Add('DE');
oFirewall.LoadGeoIPDatabase('geoip.csv');

Bases de datos GeoIP. Existen bases de datos CSV de IP a país gratuitas de proveedores como DB-IP e IP2Location. Como alternativa, implementa el evento OnResolveCountry para usar tu propia lógica de resolución.

Sistema de threat score

El sistema de threat score asigna puntos ponderados a cada tipo de violación y acumula una puntuación por dirección IP. Cuando la puntuación supera el umbral de auto-ban, la IP se banea automáticamente. Las puntuaciones decaen con el tiempo, de modo que un incidente puntual no se traduce en penalizaciones permanentes.

Propiedad Default Descripción
AutoBanThreshold 100 puntuación a partir de la que la IP se banea automáticamente
DecayPerHour 10 puntos restados por cada hora de inactividad
oFirewall.ThreatScore.Enabled := True;
oFirewall.ThreatScore.AutoBanThreshold := 80;
oFirewall.ThreatScore.DecayPerHour := 5;

Monitorizar cambios de puntuación

Usa el evento OnThreatScoreChanged para monitorizar las puntuaciones en tiempo real y tomar acciones a medida antes de alcanzar el umbral de auto-ban.

procedure TForm1.FirewallThreatScoreChanged(Sender: TObject;
  const aIP: string; const aOldScore, aNewScore: Integer);
begin
  if aNewScore >= 50 then
    LogToFile(Format('[%s] Threat score elevated: %d -> %d',
      [aIP, aOldScore, aNewScore]));
end;

Escalado progresivo de baneos

En lugar de una duración fija, el módulo de escalado aumenta la longitud del baneo con cada reincidencia. Los infractores noveles reciben un baneo corto; los reincidentes persistentes escalan hasta un bloqueo permanente.

oFirewall.BanEscalation.Enabled := True;
oFirewall.BanEscalation.Levels.Add('300');    // 5 minutes
oFirewall.BanEscalation.Levels.Add('1800');   // 30 minutes
oFirewall.BanEscalation.Levels.Add('7200');   // 2 hours
oFirewall.BanEscalation.Levels.Add('86400');  // 24 hours
oFirewall.BanEscalation.Levels.Add('0');      // permanent

Consejo. Combina el escalado progresivo con el sistema de threat score para máxima efectividad. El threat score identifica actores maliciosos en múltiples tipos de violación, y el escalado asegura que los reincidentes se enfrenten a consecuencias cada vez más severas.

Protección específica de WebSocket

Más allá del escaneo a nivel de mensaje, el firewall proporciona protecciones a nivel de protocolo específicas para conexiones WebSocket: validación de Origin, aplicación de límites de tamaño de frame y filtrado de subprotocolos.

// Validate the Origin header to prevent cross-site hijacking
oFirewall.WebSocket.Enabled := True;
oFirewall.WebSocket.AllowedOrigins.Add('https://www.example.com');
oFirewall.WebSocket.AllowedOrigins.Add('https://app.example.com');
// Enforce maximum frame size (bytes)
oFirewall.WebSocket.MaxFrameSize := 131072;  // 128 KB
// Only allow specific subprotocols
oFirewall.WebSocket.AllowedSubProtocols.Add('graphql-ws');
oFirewall.WebSocket.AllowedSubProtocols.Add('mqtt');

Motor de reglas personalizadas

El motor de reglas personalizadas te permite definir tus propias reglas de firewall con condiciones y acciones automatizadas. Cada regla especifica un umbral de violaciones dentro de una ventana temporal y la acción a tomar cuando se supera el umbral.

Propiedad Descripción
Name nombre descriptivo de la regla
MinViolations número de violaciones necesarias para disparar la regla
TimeWindowSec ventana deslizante en segundos para contar violaciones
ActionType acción a realizar: raDeny, raAllow, raBan o raLog
BanDurationSec duración del baneo cuando ActionType es raBan

Tipos de acción:

Acción Comportamiento
raDeny desconecta al cliente inmediatamente
raAllow sin acción (la regla se rastrea pero no se aplica)
raBan banea la IP durante la duración especificada
raLog dispara únicamente el evento OnViolation
var
  vRule: TsgcFirewallRuleItem;
begin
  oFirewall.CustomRules.Enabled := True;
  vRule := TsgcFirewallRuleItem(oFirewall.CustomRules.Rules.Add);
  vRule.Name := 'Block high-risk IPs';
  vRule.MinViolations := 5;
  vRule.TimeWindowSec := 300;
  vRule.ActionType := raBan;
  vRule.BanDurationSec := 3600;
end;

Estadísticas en tiempo real

El firewall expone un objeto Stats con contadores en tiempo real para conexiones activas, intentos bloqueados totales y contadores por tipo de violación. Úsalo para construir dashboards de monitorización o registrar resúmenes periódicos.

WriteLn('Active: ', oFirewall.Stats.ActiveConnections);
WriteLn('Blocked: ', oFirewall.Stats.TotalBlocked);
WriteLn('SQL Injection: ', oFirewall.Stats.GetViolationCount(fvSQLInjection));

Baneos persistentes

Por defecto, los baneos se almacenan en memoria y se borran al reiniciar. Usa SaveBansToFile y LoadBansFromFile para persistirlos entre reinicios del servidor.

// Save bans before shutdown
oFirewall.SaveBansToFile('bans.dat');
// Restore bans on startup
oFirewall.LoadBansFromFile('bans.dat');

Modos de acción

Los módulos de SQL injection, XSS y flood protection admiten tres acciones configurables cuando se detecta una violación:

Acción Comportamiento Caso de uso
faDeny bloquea y desconecta al cliente servidores en producción
faLog dispara el evento OnViolation pero permite la conexión monitorización, pruebas, rollout gradual
faAllow sin acción deshabilitar temporalmente un módulo sin quitar la configuración

Consejo. Empieza con faLog en producción para observar cómo reacciona el firewall a tu tráfico real antes de cambiar a faDeny. Esto evita bloquear a usuarios legítimos durante el despliegue inicial.

Eventos — logging y overrides

Los eventos te dan total visibilidad sobre las decisiones del firewall y la capacidad de sobrescribirlas cuando sea necesario.

OnViolation — logging de seguridad

Se dispara en cada violación detectada. Úsalo para escribir logs de seguridad, enviar alertas o alimentar un dashboard de monitorización.

procedure TForm1.FirewallViolation(Sender: TObject;
  const aIP: string;
  const aViolationType: TsgcFirewallViolationType;
  const aDetails: string);
begin
  LogToFile(Format('[%s] Firewall: %s - %s',
    [aIP, ViolationTypeToStr(aViolationType), aDetails]));
end;

Los tipos de violación incluyen:

Tipo Cuándo se dispara
fvBlacklist la IP está en la blacklist
fvBruteForce se supera el umbral de intentos fallidos
fvRateLimit se supera el rate limit de conexiones
fvFlood se detecta message flooding
fvSQLInjection se detecta un patrón de SQL injection
fvXSS se detecta un patrón XSS
fvGeoIP conexión bloqueada por el filtro por país
fvPathTraversal se detecta un patrón de path traversal
fvCommandInjection se detecta un patrón de command injection
fvPayloadSize el mensaje supera el tamaño máximo de payload
fvOrigin el origen WebSocket no está en la lista permitida
fvFrameSize el frame WebSocket supera el tamaño máximo
fvThreatScore el threat score supera el umbral de auto-ban
fvCustomRule se supera el umbral de una regla personalizada

OnFiltered — sobrescribir decisiones

Se dispara cuando una conexión o mensaje está a punto de ser bloqueado. El parámetro Allow te permite sobrescribir la decisión del firewall en tiempo de ejecución.

procedure TForm1.FirewallFiltered(Sender: TObject;
  const aIP: string; const aReason: string;
  var Allow: Boolean);
begin
  // Override: always allow the office IP even if rate-limited
  if aIP = '203.0.113.10' then
    Allow := True;
end;

OnResolveCountry — resolución GeoIP personalizada

Se dispara cuando el módulo GeoIP necesita resolver una dirección IP a un código de país. Úsalo para implementar tu propia lógica de resolución en lugar de (o además de) la base de datos CSV integrada.

procedure TForm1.FirewallResolveCountry(Sender: TObject;
  const aIP: string; var aCountryCode: string);
begin
  aCountryCode := MyGeoIPLookup(aIP);
end;

OnThreatScoreChanged — monitorización de puntuación

Se dispara cada vez que cambia el threat score de una IP. Úsalo para implementar umbrales personalizados, alertas o respuestas graduadas antes de alcanzar el umbral de auto-ban.

procedure TForm1.FirewallThreatScoreChanged(Sender: TObject;
  const aIP: string; const aOldScore, aNewScore: Integer);
begin
  if aNewScore >= 50 then
    SendAlert(Format('IP %s threat score: %d', [aIP, aNewScore]));
end;

Integración con el servidor

El firewall funciona con los tres componentes de servidor. Una única instancia de firewall puede incluso compartirse entre varios servidores.

Componente Descripción
TsgcWebSocketHTTPServer servidor WebSocket + HTTP (basado en Indy)
TsgcWebSocketServer servidor WebSocket puro (Indy TCP)
TsgcWebSocketServer_HTTPAPI servidor WebSocket que usa el driver kernel HTTP.SYS

La integración es automática una vez asignado. El firewall intercepta en tres puntos:

Ejemplo completo

Un servidor WebSocket totalmente configurado con los módulos de protección principales y las nuevas funcionalidades avanzadas habilitadas.

uses
  sgcWebSocket_Server, sgcWebSocket_Server_Firewall;
var
  oFirewall: TsgcWSFirewall;
  oServer: TsgcWebSocketHTTPServer;
begin
  oFirewall := TsgcWSFirewall.Create(nil);
  oServer := TsgcWebSocketHTTPServer.Create(nil);
  Try
    // IP filtering
    oFirewall.Blacklist.Enabled := True;
    oFirewall.Blacklist.IPs.Add('10.0.0.0/8');
    oFirewall.Whitelist.Enabled := True;
    oFirewall.Whitelist.IPs.Add('192.168.1.0/24');
    // Brute force: ban after 3 failures in 60s, for 10 minutes
    oFirewall.BruteForce.Enabled := True;
    oFirewall.BruteForce.MaxAttempts := 3;
    oFirewall.BruteForce.BanDurationSec := 600;
    // Message security
    oFirewall.SQLInjection.Enabled := True;
    oFirewall.XSS.Enabled := True;
    // Rate limiting and flood protection
    oFirewall.RateLimit.Enabled := True;
    oFirewall.RateLimit.MaxConnectionsPerIP := 5;
    oFirewall.FloodProtection.Enabled := True;
    oFirewall.FloodProtection.MaxMessagesPerSec := 50;
    // Payload size limit
    oFirewall.PayloadLimit.Enabled := True;
    oFirewall.PayloadLimit.MaxSizeBytes := 65536;
    // GeoIP: block specific countries
    oFirewall.GeoIP.Enabled := True;
    oFirewall.GeoIP.Mode := gmBlockList;
    oFirewall.GeoIP.Countries.Add('CN');
    oFirewall.GeoIP.Countries.Add('RU');
    oFirewall.LoadGeoIPDatabase('geoip.csv');
    // Threat scoring with auto-ban
    oFirewall.ThreatScore.Enabled := True;
    oFirewall.ThreatScore.AutoBanThreshold := 80;
    oFirewall.ThreatScore.DecayPerHour := 5;
    // Progressive ban escalation
    oFirewall.BanEscalation.Enabled := True;
    oFirewall.BanEscalation.Levels.Add('300');
    oFirewall.BanEscalation.Levels.Add('3600');
    oFirewall.BanEscalation.Levels.Add('86400');
    oFirewall.BanEscalation.Levels.Add('0');
    // Restore persistent bans
    oFirewall.LoadBansFromFile('bans.dat');
    // Events
    oFirewall.OnViolation := FirewallViolation;
    oFirewall.OnFiltered := FirewallFiltered;
    oFirewall.OnThreatScoreChanged := FirewallThreatScoreChanged;
    // Assign to server and start
    oServer.Port := 443;
    oServer.Firewall := oFirewall;
    oServer.Active := True;
    WriteLn('Server running with firewall protection.');
    ReadLn;
    // Save bans before shutdown
    oFirewall.SaveBansToFile('bans.dat');
  Finally
    oServer.Active := False;
    oServer.Free;
    oFirewall.Free;
  End;
end;

Seguridad multihilo

El componente firewall es totalmente thread-safe. Todos los métodos públicos usan critical sections internas para proteger el acceso concurrente a los datos de seguimiento. Se ha sometido a pruebas de estrés con 20 hilos concurrentes ejecutando 100.000 operaciones sin errores ni fugas de memoria.

El componente se puede compartir con seguridad entre varias instancias de servidor y acceder desde cualquier hilo —manejadores de eventos del servidor, hilos de timer, workers en segundo plano— sin sincronización externa.

Notas importantes