Cómo Proteger Bases de Datos con Firewall - Guía Completa

 

Cómo Proteger Bases de Datos con Firewall - Guía Completa

Te voy a enseñar exactamente cómo proteger cada tipo de base de datos. Es más fácil de lo que crees.


⚠️ REGLA DE ORO: NUNCA EXPONGAS LA BASE DE DATOS A INTERNET

Si tu base de datos está accesible desde internet, ya estás en riesgo. Solo debe ser accesible desde:

  1. Tu aplicación/servidor web (misma máquina o red privada)

  2. Tu IP personal (solo para administración)

  3. Nunca desde 0.0.0.0/0 (todo internet)


Parte 1: Configuración Básica por Tipo de BD

1. MySQL / MariaDB

bash
# 1. Escucha SOLO en localhost (editar configuración)
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

# Buscar y cambiar:
bind-address = 127.0.0.1  # SOLO localhost
# bind-address = 0.0.0.0  # ← ESTO ES PELIGROSO, NO LO HAGAS

# 2. Reiniciar MySQL
sudo systemctl restart mysql

# 3. Configurar UFW (Firewall)
# Permitir solo desde localhost
sudo ufw allow from 127.0.0.1 to any port 3306

# Si la app está en otra máquina, permitir solo esa IP
sudo ufw allow from 192.168.1.100 to any port 3306

# DENEGAR todo lo demás (esto ya lo hace UFW por defecto si configuraste bien)

2. PostgreSQL

bash
# 1. Editar postgresql.conf
sudo nano /etc/postgresql/*/main/postgresql.conf

# Cambiar:
listen_addresses = 'localhost'  # Solo localhost
# listen_addresses = '*'  # ← PELIGROSO

# 2. Editar pg_hba.conf para control de acceso
sudo nano /etc/postgresql/*/main/pg_hba.conf

# Solo permitir conexiones locales:
# host    all    all    127.0.0.1/32    md5
# host    all    all    ::1/128         md5

# 3. Reiniciar
sudo systemctl restart postgresql

# 4. Firewall
sudo ufw allow from 127.0.0.1 to any port 5432

3. MongoDB

bash
# 1. Editar mongod.conf
sudo nano /etc/mongod.conf

# Cambiar:
net:
  bindIp: 127.0.0.1  # Solo localhost
  # bindIp: 0.0.0.0  # ← EXPUESTO A INTERNET

# 2. Habilitar autenticación (IMPORTANTE)
security:
  authorization: enabled

# 3. Reiniciar
sudo systemctl restart mongod

# 4. Firewall
sudo ufw allow from 127.0.0.1 to any port 27017

4. Redis

bash
# 1. Editar redis.conf
sudo nano /etc/redis/redis.conf

# Cambiar:
bind 127.0.0.1  # Solo localhost
# bind 0.0.0.0   # ← PELIGROSO

# 2. Añadir contraseña (requerpass)
requirepass "tu_password_fuerte"

# 3. Reiniciar
sudo systemctl restart redis

# 4. Firewall
sudo ufw allow from 127.0.0.1 to any port 6379

Parte 2: Escenarios Comunes y Soluciones

Escenario 1: App y BD en la MISMA máquina

bash
# FÁCIL: Solo localhost
sudo ufw allow from 127.0.0.1 to any port 3306  # MySQL
sudo ufw allow from 127.0.0.1 to any port 5432  # PostgreSQL
sudo ufw allow from 127.0.0.1 to any port 27017 # MongoDB

# Verificar que solo localhost puede acceder
sudo ss -tuln | grep :3306
# Debe mostrar: 127.0.0.1:3306

Escenario 2: App y BD en DIFERENTES máquinas (misma red privada)

bash
# En el servidor de la Base de Datos:

# 1. Permitir solo IPs de la red privada
sudo ufw allow from 10.0.0.0/24 to any port 3306  # Red privada completa
# o mejor, solo la IP de la app:
sudo ufw allow from 10.0.0.10 to any port 3306

# 2. Configurar la BD para escuchar en IP privada
# En MySQL:
# bind-address = 10.0.0.100  # IP privada del servidor BD

# 3. Bloquear internet
sudo ufw deny from any to any port 3306
# (ya está bloqueado por defecto con "default deny incoming")

Escenario 3: Necesitas acceder desde tu PC para administrar

bash
# Solo tu IP pública (temporalmente)
# 1. Obtén tu IP pública: curl ifconfig.me
# 2. Permite SOLO tu IP:
sudo ufw allow from [TU_IP_PUBLICA] to any port 3306

# 3. Cuando termines, elimina la regla:
sudo ufw status numbered  # Busca el número
sudo ufw delete [NUMERO]

# Mejor aún: Usa VPN o SSH Tunnel (más seguro)

Parte 3: SSH Tunnel - Método SÚPER SEGURO

Acceder a BD mediante túnel SSH (recomendado)

bash
# Desde tu PC local, crea un túnel:
ssh -L 3306:localhost:3306 usuario@tu-servidor.com
# -L [puerto_local]:localhost:[puerto_remoto]

# Luego conectas desde tu PC como si fuera local:
mysql -h 127.0.0.1 -P 3306 -u usuario -p

Ventajas:

  • La BD solo escucha en localhost (127.0.0.1)

  • Todo pasa por SSH (encriptado)

  • No necesitas abrir puertos en el firewall

  • MUY SEGURO


Parte 4: Script de Protección Automática

Script para Proteger TODAS las Bases de Datos

bash
#!/bin/bash
# protector-bd.sh - Protege automáticamente tus bases de datos

echo "🔒 CONFIGURANDO PROTECCIÓN PARA BASES DE DATOS"

# 1. Configurar políticas por defecto
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 2. Permitir SSH (obligatorio)
sudo ufw allow 22/tcp

# 3. CERRAR todos los puertos de bases de datos a internet
echo "🚫 Cerrando puertos de BD a internet..."

# MySQL/MariaDB
sudo ufw deny 3306/tcp
echo "   MySQL (3306) - CERRADO a internet"

# PostgreSQL
sudo ufw deny 5432/tcp
echo "   PostgreSQL (5432) - CERRADO a internet"

# MongoDB
sudo ufw deny 27017/tcp
echo "   MongoDB (27017) - CERRADO a internet"

# Redis
sudo ufw deny 6379/tcp
echo "   Redis (6379) - CERRADO a internet"

# Elasticsearch
sudo ufw deny 9200/tcp
sudo ufw deny 9300/tcp
echo "   Elasticsearch (9200, 9300) - CERRADO a internet"

# 4. Permitir solo localhost (para apps en la misma máquina)
echo "🔐 Permitir solo localhost..."
sudo ufw allow from 127.0.0.1 to any port 3306
sudo ufw allow from 127.0.0.1 to any port 5432
sudo ufw allow from 127.0.0.1 to any port 27017
sudo ufw allow from 127.0.0.1 to any port 6379

# 5. Activar firewall
sudo ufw --force enable

# 6. Mostrar configuración
echo ""
echo "✅ CONFIGURACIÓN COMPLETADA"
echo "=============================="
sudo ufw status numbered

# 7. Verificar
echo ""
echo "🔍 VERIFICANDO PUERTOS ABIERTOS..."
sudo ss -tuln | grep -E ':3306|:5432|:27017|:6379'

Cómo usar el script:

bash
# 1. Guardar como protector-bd.sh
nano protector-bd.sh

# 2. Dar permisos de ejecución
chmod +x protector-bd.sh

# 3. Ejecutar
sudo ./protector-bd.sh

Parte 5: Configuración con Docker (CASO ESPECIAL)

❌ CONFIGURACIÓN PELIGROSA (NO HACER)

bash
# Esto EXPONE la BD a internet:
docker run -d -p 3306:3306 mysql

✅ CONFIGURACIÓN SEGURA

Opción 1: Solo localhost

bash
# Solo accesible desde la misma máquina
docker run -d -p 127.0.0.1:3306:3306 mysql

# Verificar:
sudo ss -tuln | grep :3306
# Debe mostrar: 127.0.0.1:3306

Opción 2: Red privada de Docker

bash
# 1. Crear red interna
docker network create red-interna

# 2. Ejecutar MySQL en la red interna
docker run -d --name mysql --network red-interna \
  -e MYSQL_ROOT_PASSWORD=contraseña_fuerte \
  mysql

# 3. Ejecutar tu app en la misma red
docker run -d --name mi-app --network red-interna \
  -e DB_HOST=mysql \
  mi-app

# 4. La BD NO está expuesta a internet
# Solo otros contenedores en "red-interna" pueden acceder

Opción 3: Conectar contenedor existente

bash
# Si ya tienes un contenedor corriendo:

# 1. Crear red
docker network create red-segura

# 2. Conectar contenedores a la red
docker network connect red-segura mysql
docker network connect red-segura mi-app

# 3. Desconectar de la red bridge por defecto
docker network disconnect bridge mysql

Parte 6: Verificación y Monitoreo

Comandos para Verificar que tu BD está Protegida

1. Desde la misma máquina (debe funcionar):

bash
# MySQL
mysql -h 127.0.0.1 -u usuario -p

# PostgreSQL
psql -h localhost -U usuario

# MongoDB
mongosh --host localhost

2. Desde otra máquina (debe FALLAR):

bash
# Instalar cliente MySQL si no lo tienes
sudo apt install mysql-client

# Intentar conectar DESDE INTERNET (debe fallar)
mysql -h [IP_PUBLICA_SERVIDOR] -u usuario -p
# ERROR 2003: Can't connect to MySQL server

3. Escanear puertos desde fuera:

bash
# Desde otra máquina, con nmap:
nmap -p 3306,5432,27017 [IP_PUBLICA_SERVIDOR]

# Debe mostrar:
# 3306/tcp  closed  mysql
# 5432/tcp  closed  postgresql
# 27017/tcp closed  mongodb

4. Ver conexiones activas:

bash
# Ver todas las conexiones a puertos de BD
sudo lsof -i :3306
sudo netstat -tulpn | grep :3306

# Ver IPs que intentan conectarse (logs)
sudo tail -f /var/log/mysql/error.log
sudo grep "connect" /var/log/mysql/error.log

Parte 7: Reglas Específicas por IP

Permitir solo CIERTAS IPs específicas:

bash
# Ejemplo: Solo tu oficina y servidores de apps
sudo ufw allow from 201.175.84.100 to any port 3306  # Oficina
sudo ufw allow from 10.0.0.10 to any port 3306       # Servidor App 1
sudo ufw allow from 10.0.0.11 to any port 3306       # Servidor App 2

# Bloquear TODO lo demás (ya está bloqueado por defecto)

Usar archivo con lista de IPs permitidas:

bash
# Crear lista de IPs confiables
sudo nano /etc/ips-permitidas.txt

# Contenido:
201.175.84.100
10.0.0.10
10.0.0.11

# Script para aplicar reglas
while read ip; do
  sudo ufw allow from $ip to any port 3306
  echo "Permitido: $ip"
done < /etc/ips-permitidas.txt

Parte 8: Firewall en la Nube + Sistema Operativo

Doble protección:

text
INTERNET → [Cloud Firewall] → [UFW] → [Base de Datos]

Digital Ocean:

bash
# 1. Cloud Firewall (en panel web):
# - Deny All Inbound
# - Allow SSH (22) from Your IP
# - Allow HTTP/HTTPS (80,443) from Any
# - NO permitir puertos de BD (3306, 5432, etc)

# 2. Luego UFW en el servidor:
sudo ufw allow from 127.0.0.1 to any port 3306
sudo ufw allow from 10.0.0.0/24 to any port 3306  # Red interna

AWS Security Groups:

json
{
  "Inbound": [
    {"Port": 22, "Source": "Tu-IP/32"},
    {"Port": 80, "Source": "0.0.0.0/0"},
    {"Port": 443, "Source": "0.0.0.0/0"}
    # NO agregar puertos 3306, 5432, etc aquí
  ]
}

Parte 9: Qué Hacer Si Necesitas Acceso Remoto

Opción 1: VPN (RECOMENDADO)

bash
# Instalar WireGuard (por ejemplo)
sudo apt install wireguard

# Configurar VPN, luego:
sudo ufw allow from 10.8.0.0/24 to any port 3306  # Red VPN

Opción 2: SSH Port Forwarding Temporal

bash
# Cuando necesites acceso:
ssh -L 3306:localhost:3306 usuario@servidor -Nf
# Ahora mysql -h 127.0.0.1 funciona desde tu PC

# Cuando termines:
killall ssh

Opción 3: Regla Temporal con Timeout

bash
# Permitir tu IP por 1 hora
sudo ufw allow from [TU_IP] to any port 3306

# Programar eliminación automática
(sleep 3600 && sudo ufw delete allow from [TU_IP] to any port 3306) &

Parte 10: Checklist de Seguridad para Bases de Datos

✅ Configuración MÍNIMA SEGURA:

  • BD configurada para bind-address = 127.0.0.1

  • UFW bloquea puertos de BD a internet

  • Solo localhost puede conectarse

  • Autenticación habilitada con contraseñas fuertes

  • Usuario root/administrador no accesible remotamente

✅ Configuración IDEAL:

  • BD en red privada/VPC

  • Acceso solo desde IPs específicas

  • Logs de conexiones habilitados

  • Conexiones SSL/TLS habilitadas

  • Backup automático configurado

✅ Verificación Periódica:

bash
# Script de verificación mensual
echo "=== VERIFICACIÓN SEGURIDAD BD ==="
echo "1. Puertos expuestos:"
sudo ss -tuln | grep -E ':3306|:5432|:27017'

echo "2. Intentos de conexión rechazados:"
sudo ufw status | grep DENY

echo "3. Conexiones activas a BD:"
sudo netstat -tulpn | grep -E '(mysql|postgres|mongo)'

echo "4. Escaneo externo (desde otra máquina):"
echo "   Ejecutar: nmap -p 3306,5432,27017 [TU_IP]"
echo "   Todos deben mostrar 'closed'"

Resumen Final

REGLA #1:

bash
# NUNCA HAGAS ESTO:
sudo ufw allow 3306/tcp  # ← PELIGRO: Expone a TODO internet

# SIEMPRE HAZ ESTO:
sudo ufw allow from 127.0.0.1 to any port 3306  # ← SEGURO: Solo localhost

REGLA #2: Si necesitas acceso remoto, usa:

  1. SSH Tunnel (para administración ocasional)

  2. VPN (para acceso frecuente)

  3. IPs específicas (nunca 0.0.0.0/0)

REGLA #3: Doble protección:

text
Internet → [Cloud Firewall] → [UFW] → [BD configurada en localhost]

Comando que te salvará:

bash
# Verifica ANTES de activar:
sudo ufw status
# Si ves puertos de BD abiertos a 0.0.0.0, CORRÍGELOS

# Comando mágico para ver exposición:
sudo ss -tuln | grep -E ':3306|:5432|:27017'
# Solo debe mostrar 127.0.0.1 o IPs privadas

Recuerda: Un puerto de base de datos expuesto a internet es como dejar la puerta de tu casa abierta con un cartel que dice "mis joyas están aquí". ¡Sigue estas reglas y dormirás tranquilo! 🔐

This response is AI-generated, for reference only.

Comentarios

Entradas más populares de este blog

14. Publish and Detached modes

12. Hola Mundo en Docker.

11¿Qué es Docker? y ¿Por qué debo saberlo?