Plantilla de Documentación de Seguridad de Red
Una plantilla para documentar el inventario de reglas de seguridad de VPC, firewall y DNS.
Visión General
La red es lo primero que prueba un atacante y casi siempre lo último que alguien documenta. Reglas de firewall mal configuradas, security groups demasiado permisivos y registros DNS obsoletos son puntos de entrada habituales para atacantes, y casi imposibles de detectar sin un inventario. Esta plantilla te da ese inventario: cada regla con su justificación, su propietario y su fecha de revisión, para que puedas auditar la red en lugar de suponer.
La estructura funciona para una revisión de seguridad trimestral, para incorporar un servicio nuevo que necesita acceso a la red, o para demostrar cumplimiento cuando un auditor pregunta «¿quién aprobó esta regla y por qué existe?».
Cuándo Usar
Usa este recurso cuando:
- Incorpores un servicio nuevo que requiere reglas de acceso a la red
- Realices una auditoría de seguridad trimestral o prepares una prueba de penetración
- Migres infraestructura a una VPC nueva o a otro proveedor de nube
- Heredes un entorno donde nadie sabe por qué existe una regla
Sáltala en un sandbox de desarrollo de un solo propósito o en una prueba de concepto que se derriba en días: ahí el costo de la revisión supera al riesgo.
Solución
# Inventario de Seguridad de Red: `<Entorno>`
## 1. Alcance
| Campo | Valor |
|-------|-------|
| Entorno | `prod / staging / dev` |
| Proveedor de Nube | `AWS / GCP / Azure / On-prem` |
| CIDR de Red | `10.0.0.0/16` |
| Última Revisión | `YYYY-MM-DD` |
| Revisor | `@security-team` |
## 2. Segmentación de VPC / Red
| Segmento | CIDR | Propósito | Acceso a Internet | Peering |
|----------|------|-----------|-------------------|---------|
| Subnet pública | `10.0.1.0/24` | Load balancers, bastion | Sí (solo egress) | Ninguno |
| Subnet de aplicación | `10.0.2.0/24` | Microservicios | No | Peering a servicios compartidos |
| Subnet de base de datos | `10.0.3.0/24` | PostgreSQL, Redis | No | Peering a servicios compartidos |
| Subnet de administración | `10.0.4.0/24` | Runners de CI/CD, monitoreo | Sí (NAT) | Ninguno |
| Servicios compartidos | `10.1.0.0/24` | SSO, logging, secretos | No | Peering a todas las VPCs |
## 3. Reglas de Firewall / Security Groups
### 3.1. Reglas de Entrada
| Origen | Protocolo | Puerto | Destino | Justificación | Última Revisión |
|--------|-----------|--------|---------|---------------|---------------|
| `0.0.0.0/0` | TCP | 443 | ALB público | HTTPS público | `YYYY-MM-DD` |
| `10.0.2.0/24` | TCP | 5432 | Subnet de base de datos | Aplicación → DB | `YYYY-MM-DD` |
| `10.0.4.0/24` | TCP | 22 | Bastion host | Acceso admin | `YYYY-MM-DD` |
| `CIDR VPN` | TCP | 3389 | Windows jump host | Acceso admin | `YYYY-MM-DD` |
### 3.2. Reglas de Salida
| Destino | Protocolo | Puerto | Origen | Justificación | Última Revisión |
|---------|-----------|--------|--------|---------------|---------------|
| `0.0.0.0/0` | TCP | 443 | Todas las subnets | Actualizaciones de software, APIs | `YYYY-MM-DD` |
| `0.0.0.0/0` | TCP | 53 | Todas las subnets | Resolución DNS | `YYYY-MM-DD` |
| `0.0.0.0/0` | UDP | 53 | Todas las subnets | Resolución DNS | `YYYY-MM-DD` |
| `Rango IP SaaS` | TCP | 443 | Subnet de aplicación | API de terceros | `YYYY-MM-DD` |
## 4. Configuración de DNS
| Registro | Tipo | Valor | TTL | Propósito | Seguro |
|----------|------|-------|-----|-----------|--------|
| `api.example.com` | A | IP ALB | 60s | API pública | DNSSEC habilitado |
| `internal.example.com` | A | IP privada | 300s | Servicios internos | Solo zona privada |
| `cdn.example.com` | CNAME | `cdn.provider.com` | 300s | Entrega de assets | HTTPS forzado |
## 5. Controles de Acceso a la Red
| Control | Implementación | Alcance | Estado |
|---------|----------------|---------|--------|
| Protección DDoS | AWS Shield / Cloud Armor / Azure DDoS | Endpoints públicos | Activo |
| WAF | AWS WAF / Cloudflare / ModSecurity | Endpoints públicos | Activo |
| Detección de intrusiones | Suricata / GuardDuty / Azure Sentinel | Flow logs de VPC | Activo |
| VPN / Zero Trust | WireGuard / Zscaler / BeyondCorp | Todo acceso admin | Activo |
| Endpoints privados | VPC endpoints / PrivateLink / Private Link | Servicios AWS / Azure | Activo |
## 6. Registro de Cambios
| Fecha | Cambio | Solicitante | Aprobado Por | Ticket |
|-------|--------|-------------|--------------|--------|
| `YYYY-MM-DD` | Apertura del puerto 5432 para un nuevo servicio de analytics | `data-team` | `security-team` | `SEC-123` |
| `YYYY-MM-DD` | Eliminación de SSH de la subnet pública | `sre-team` | `security-team` | `SEC-124` |
Cómo Rellenar Cada Sección
Cada tabla de la plantilla se corresponde con un comando o una vista de consola que ya tienes. No la rellenes de memoria: hazlo desde la fuente de verdad.
| Sección | Qué capturar | De dónde sacarlo |
|---|---|---|
| Alcance | Entorno, proveedor, CIDR, revisor | Página de detalles de la VPC o aws ec2 describe-vpcs |
| Segmentación | Una fila por subnet/VPC con su propósito | aws ec2 describe-subnets, gcloud compute networks subnets list, portal de Azure → VNets |
| Reglas de entrada | Origen, puerto, destino, justificación | aws ec2 describe-security-groups, gcloud compute firewall-rules list, az network nsg rule list |
| Reglas de salida | Los mismos campos, para egress | Los mismos comandos: las reglas de egress vienen en la misma salida |
| DNS | Registro, tipo, valor, TTL, seguro | Exportación de Route 53 / Cloud DNS / registrador, o dig/nslookup para comprobaciones puntuales |
| Controles de acceso | Estado de DDoS, WAF, IDS, VPN y endpoints privados | La consola de cada servicio; marca explícitamente lo que falte en lugar de omitir la fila |
| Registro de cambios | Fecha, cambio, solicitante, aprobador, ticket | Tu sistema de tickets; si un cambio no tiene ticket, eso ya es un hallazgo |
La única columna que la gente se salta es Justificación. También es la única que hace que el inventario valga algo seis meses después. «Abierto para depurar el despliegue en marzo» es una justificación; «hacía falta» no lo es.
Ejemplo Rellenado
Así queda la sección 3.1 completada para un entorno de producción de un SaaS mediano:
| Origen | Protocolo | Puerto | Destino | Justificación | Última Revisión |
|---|---|---|---|---|---|
0.0.0.0/0 | TCP | 443 | alb-orders-prod | Entrada pública HTTPS | 2026-09-01 |
10.0.2.0/24 | TCP | 5432 | rds-orders-primary | Orders API → Postgres | 2026-09-01 |
10.0.4.0/24 | TCP | 22 | bastion-prod-01 | SSH admin vía bastion | 2026-06-15 |
203.0.113.0/24 | TCP | 443 | alb-orders-prod | Allowlist API del partner (Contrato P-118) | 2026-08-20 |
Hay dos cosas que copiar del ejemplo: cada fila nombra un recurso concreto (no «la base de datos»), y la regla del partner lleva su referencia de contrato, de modo que renovarla o eliminarla es un ticket en lugar de un proyecto de arqueología.
Explicación
La plantilla trata tu red como un sistema de defensa en profundidad. La segmentación implica que si una subnet queda comprometida, el atacante no puede moverse lateralmente hasta la base de datos. Cada regla exige una justificación y una fecha de revisión para que las reglas obsoletas no persistan para siempre: una regla que nadie sabe explicar es una regla que debería cerrarse. El DNS queda olvidado en la mayoría de las revisiones, pero un registro secuestrado u obsoleto redirige el tráfico a infraestructura del atacante con la misma eficacia que un puerto abierto.
Fíjate en la asimetría: la subnet pública es la única con entrada desde internet, y solo el load balancer termina ahí. Si tu inventario muestra una regla de aplicación o base de datos alcanzable desde 0.0.0.0/0 en entrada, esa es la primera fila a revisar.
Cuando documentes las decisiones de segmentación, acompaña este inventario con la plantilla de política de segmentación de red: el inventario registra lo que existe y la política registra lo que está permitido que exista. Se desincronizan más rápido de lo que parece.
Lo Que Suele Encontrar una Primera Revisión
Espera que la primera pasada sobre un entorno real saque a la luz los mismos problemas de siempre:
- Puertos de administración abiertos al mundo: SSH o RDP alcanzables desde
0.0.0.0/0, casi siempre restos de un atajo de aprovisionamiento. Muévelos detrás del bastion o la VPN. - Reglas huérfanas: puertos abiertos para un servicio que ya no existe, normalmente de un proyecto que se lanzó o murió sin ticket de limpieza.
- Una sola red plana: una única subnet que lleva tráfico web, de aplicación y de base de datos, lo que hace que cada revisión de reglas empiece desde cero.
- Egress que nadie miró: las reglas de entrada reciben escrutinio mientras las de salida quedan abiertas de par en par — está bien para DNS y actualizaciones, pero cualquier otra cosa necesita justificación.
- DNS sin propietario: registros apuntando a IPs retiradas, o nadie que sepa quién creó un registro A crítico.
Cada hallazgo se convierte en una fila del registro de cambios y en un ticket con propietario. El trabajo del inventario es hacerlos visibles, no arreglarlos sobre la marcha.
Variantes
| Entorno | Enfoque | Notas |
|---|---|---|
| AWS | VPC + Security Groups + NACLs | NACLs para reglas a nivel de subnet, SGs a nivel de instancia |
| GCP | VPC Firewall Rules + Cloud Armor | Las reglas de firewall son con estado; usa service accounts para identidad |
| Azure | NSGs + Azure Firewall | Los NSGs aplican a subnets o NICs; Azure Firewall para logging central |
| Kubernetes | Network Policies + Cilium / Calico | Aísla namespaces; default-deny es lo más seguro |
| Híbrido / On-prem | Firewall físico + SD-WAN | Documenta las rutas lógicas y las físicas |
La forma del inventario se mantiene entre proveedores; solo cambian los nombres de los campos. En Kubernetes, una «subnet» es un namespace y un «security group» es una NetworkPolicy; si operas contenedores a escala, la plantilla de baseline de seguridad de contenedores cubre los controles complementarios en la imagen y el runtime.
Lo que funciona
- Deniega todo por defecto y permite solo lo que tenga una justificación documentada.
- Revisa las reglas de firewall cada trimestre y elimina lo que haya perdido su justificación.
- Permite
0.0.0.0/0en entrada solo hacia un load balancer que termine TLS; nunca hacia instancias. - Activa los flow logs de VPC y conserva al menos 90 días; son el único registro que tendrás del movimiento lateral.
- Alcanza los servicios de nube a través de endpoints privados en lugar de la internet pública.
Errores Comunes
- Permitir SSH o RDP desde
0.0.0.0/0en lugar de canalizar el acceso admin por un bastion o una VPN. - Reutilizar el mismo security group en producción y staging, lo que difumina todos los límites que dibujaste.
- Dejar olvidadas reglas temporales tras un incidente o una sesión de depuración; nadie recuerda haberlas abierto.
- Recoger flow logs de VPC sin mirarlos nunca, así el movimiento lateral pasa desapercibido durante una brecha.
- Fijar direcciones IP en DNS en lugar de usar CNAMEs hacia los load balancers.
Cadencia de Revisión y Propiedad
Un inventario que nadie mantiene es peor que no tenerlo: te da respuestas seguras que son incorrectas.
- Revisión trimestral: repasa cada regla cuya
Última Revisióntenga más de 90 días. Cada una recibe uno de tres resultados: conservar (renovar justificación), eliminar (abrir el ticket) o marcar para aceptación de riesgo. - Un propietario por fila: el equipo que pidió la regla es dueño de su justificación. Cuando no pueden explicarla, la acción por defecto es eliminarla, no renovarla.
- La aceptación de riesgo es una decisión documentada: si una regla no puede eliminarse pero tampoco es ideal (un proveedor exige una allowlist de IP fija, por ejemplo), registra al dueño del riesgo y una fecha de caducidad para la excepción; no dejes que «temporal» se vuelva permanente por silencio.
- Disciplina de registro de cambios: cada entrada vincula un cambio de regla a un ticket. Si el registro y la configuración real no coinciden, confía en la configuración real y arregla el proceso que permitió la deriva.
- Complementa con checklists adyacentes: la checklist de seguridad de endpoints cubre el lado del host de la misma revisión, y la plantilla de seguridad del pipeline de CI/CD cubre la ruta de despliegue que sigue tocando estas reglas.
Soluciones Avanzadas
Auditoría automatizada de security groups con AWS CLI
Exporta y analiza todas las reglas de security groups para encontrar configuraciones demasiado permisivas:
import boto3
import csv
from dataclasses import dataclass
from typing import List
@dataclass
class SecurityGroupFinding:
group_id: str
group_name: str
direction: str # ingress o egress
protocol: str
from_port: int
to_port: int
cidr: str
severity: str # critical / warning / ok
vpc_id: str
class SecurityGroupAuditor:
def __init__(self, region: str = "us-east-1"):
self.ec2 = boto3.client("ec2", region_name=region)
def audit_all_security_groups(self) -> List[SecurityGroupFinding]:
"""Audita todos los security groups buscando reglas demasiado permisivas."""
findings = []
response = self.ec2.describe_security_groups()
for sg in response["SecurityGroups"]:
for rule_type in ["IpPermissions", "IpPermissionsEgress"]:
direction = "ingress" if rule_type == "IpPermissions" else "egress"
for rule in sg.get(rule_type, []):
for ip_range in rule.get("IpRanges", []):
cidr = ip_range.get("CidrIp", "N/A")
from_port = rule.get("FromPort", 0)
# 0.0.0.0/0 en puertos no web es crítico; en puertos web es aviso
if cidr != "0.0.0.0/0":
severity = "ok"
elif direction == "ingress" and from_port not in (80, 443):
severity = "critical"
else:
severity = "warning"
findings.append(SecurityGroupFinding(
group_id=sg["GroupId"],
group_name=sg["GroupName"],
direction=direction,
protocol=rule.get("IpProtocol", "all"),
from_port=from_port,
to_port=rule.get("ToPort", 0),
cidr=cidr,
severity=severity,
vpc_id=sg.get("VpcId", "default"),
))
return findings
def export_findings(self, output_file: str) -> None:
"""Exporta los hallazgos a CSV para el registro de auditoría."""
findings = self.audit_all_security_groups()
with open(output_file, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow([
"Group ID", "Group Name", "Direction", "Protocol",
"From Port", "To Port", "CIDR", "Severity", "VPC ID"
])
for finding in findings:
writer.writerow([
finding.group_id, finding.group_name, finding.direction,
finding.protocol, finding.from_port, finding.to_port,
finding.cidr, finding.severity, finding.vpc_id,
])
risky = [f for f in findings if f.severity == "critical"]
print(f"Total rules: {len(findings)}")
print(f"Critical rules: {len(risky)}")
for r in risky:
print(
f" RISK: {r.group_name} ({r.direction})"
f" - {r.protocol}:{r.from_port} from {r.cidr}"
)
# Ejemplo de uso
auditor = SecurityGroupAuditor(region="us-east-1")
auditor.export_findings("sg-audit-report.csv")
Análisis de flow logs de VPC para detección de movimiento lateral
Analiza flow logs de VPC para detectar patrones de tráfico sospechoso:
#!/bin/bash
set -euo pipefail
# Consulta los flow logs de VPC buscando tráfico rechazado en las últimas 24 horas
LOG_GROUP="/aws/vpc/flow-logs"
START_TIME=$(date -d '24 hours ago' +%s)000
END_TIME=$(date +%s)000
aws logs filter-log-events \
--log-group-name "$LOG_GROUP" \
--start-time "$START_TIME" \
--end-time "$END_TIME" \
--filter-pattern "REJECT" \
--query 'events[*].message' \
--output text | while read -r line; do
# Campos del flow log (separados por espacio):
# version account-id srcaddr dstaddr srcport dstport
# protocol packets bytes start end action log-status
SRC=$(echo "$line" | awk '{print $4}')
DST=$(echo "$line" | awk '{print $5}')
DSTPORT=$(echo "$line" | awk '{print $7}')
ACTION=$(echo "$line" | awk '{print $13}')
echo "REJECTED: $SRC -> $DST:$DSTPORT ($ACTION)"
done
# Agrega por IP de origen para encontrar intentos de escaneo
echo ""
echo "=== Top Source IPs by Rejected Connections ==="
aws logs filter-log-events \
--log-group-name "$LOG_GROUP" \
--start-time "$START_TIME" \
--end-time "$END_TIME" \
--filter-pattern "REJECT" \
--query 'events[*].message' \
--output text | \
awk '{print $4}' | \
sort | uniq -c | sort -rn | head -20
Aplicación de network policies de Kubernetes con Cilium
Define y verifica políticas default-deny en todos los namespaces:
# default-deny-all.yaml - Aplica a cada namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# allow-dns.yaml - Permite DNS explícitamente
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
---
# allow-frontend-to-backend.yaml - Comunicación específica entre servicios
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
#!/bin/bash
# Verifica que todos los namespaces tienen políticas default-deny
set -euo pipefail
NAMESPACES=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')
for ns in $NAMESPACES; do
POLICIES=$(kubectl get networkpolicy -n "$ns" -o json | \
jq -r '.items[] | select(.metadata.name | test("default-deny")) | .metadata.name')
if [ -z "$POLICIES" ]; then
echo "WARNING: el namespace '$ns' no tiene network policy default-deny"
else
echo "OK: el namespace '$ns' tiene la política: $POLICIES"
fi
done
Código companion: el repo companion de network-security-template tiene estos scripts como archivos ejecutables.
Ver También
- Documentación de Security Groups de AWS — referencia de reglas, límites y valores por defecto.
- VPC Flow Logs de AWS — configuración y formato de registro.
- Reglas de firewall de VPC de GCP — reglas implícitas y semántica de prioridades.
- Visión general de NSG de Azure — orden de evaluación de los NSG.
- NIST SP 800-41 — directrices de política de firewall del NIST.
- Guía de arquitectura Zero Trust — el modelo general al que alimenta este inventario.
Preguntas frecuentes
¿Cómo audito security groups existentes rápidamente?
Usa aws ec2 describe-security-groups (o equivalente) y exporta a CSV. Después ordena por las reglas que permiten entrada desde 0.0.0.0/0 y cruza cada una con tickets de cambio. Si una regla no tiene justificación o no se revisó en más de un año, márcala para eliminación y notifica al equipo propietario.
¿Debería usar Network ACLs o Security Groups?
Ambos. Los security groups funcionan con estado sobre instancias y son tu control principal. Los NACLs funcionan sin estado sobre subnets, así que úsalos como defensa de respaldo de grano grueso. Un NACL, por ejemplo, bloquea un puerto a nivel de subnet incluso si un security group lo permite por error.
¿Cómo aseguro los registros DNS?
Activa DNSSEC en las zonas públicas; frena el envenenamiento de caché. Dale a los registros que puedan necesitar cambios rápidos un TTL corto (60-300s). Vigila los cambios no autorizados con los logs de auditoría del proveedor DNS. En el DNS interno, mantén todo en zonas privadas alcanzables solo desde la VPC y restringe las transferencias a servidores autorizados.
¿Cada cuánto debería revisar las reglas de firewall?
Trimestralmente es la cadencia que se sostiene en la práctica: las revisiones mensuales acaban saltándose y las anuales dejan acumular demasiada mugre. Todo lo que toque 0.0.0.0/0 en entrada merece una mirada en cada revisión, y las reglas temporales deberían llevar fecha de caducidad desde el momento en que se abren.
¿Qué hago con una regla que nadie sabe justificar?
Primero mira en los flow logs si hubo tráfico real durante los últimos 90 días. Si está en silencio, elimina la regla y espera quejas: con el cambio registrado, revertir es trivial. Si transporta tráfico, sigue el origen hasta su propietario y pídele que escriba la justificación o que migre a una regla mejor acotada.
Recursos Relacionados
Plantilla de Política de Auto-Scaling
Plantilla de política de auto-scaling lista para copiar, con umbrales de scale-up/down, cooldowns, controles de costo y ejemplos en Terraform y Kubernetes HPA.
DocPlantilla de Verificación de Backup y Restore
Una plantilla para documentar procedimientos de verificación de backups de bases de datos y archivos.
DocPlantilla de Prueba de Failover Cross-Region
Plantilla tipo runbook para planificar, ejecutar y documentar una prueba de failover entre regiones con criterios de aborto y failback.
DocPlantilla de Checklist de Despliegue
Una checklist de verificación lista para copiar que asegura despliegues de producción seguros, desde los tests previos hasta el monitoreo posterior.
DocPlantilla de Política de Segmentación de Red
Una plantilla para documentar zonas de seguridad de red, reglas de segmentación y controles de tráfico entre entornos e inquilinos.
DocPlantilla de Checklist de Seguridad para Endpoints
Una plantilla de checklist para endurecer laptops, estaciones de trabajo y dispositivos móviles que acceden a datos y sistemas corporativos.