← ← Volver a todas las notas

Guía Completa: Hardening de Servidores Linux para Producción

2025-11-16 · Benja

Checklist de 50+ puntos con variables de entorno y próximos pasos estratégicos.

Guía Completa: Hardening de Servidores Linux para Producción
Guía Completa: Hardening de Servidores Linux para Producción
Esta guía está pensada para servidores Linux en entorno de producción, priorizando reproducibilidad, seguridad y mantenibilidad usando variables de entorno y scripts reutilizables.

🚨 Introducción: Variables de Entorno Críticas

Antes de comenzar, configura estas variables de entorno para personalizar tu despliegue:

# Crear archivo de variables en /etc/server-config.env
sudo tee /etc/server-config.env > /dev/null << EOF
# =============================================================================
# CONFIGURACIÓN DEL SERVIDOR - VARIABLES DE ENTORNO
# =============================================================================

# IDENTIFICACIÓN DEL SERVIDOR
export SERVER_NAME="prod-web-01"
export ENVIRONMENT="production"
export DOMAIN="tudominio.com"

# CONFIGURACIÓN DE RED
export SSH_PORT="5822"
export SERVER_TIMEZONE="America/Argentina/Buenos_Aires"

# USUARIOS Y ACCESOS
export DEPLOY_USER="deploy"
export ADMIN_EMAIL="admin@tudominio.com"

# BASE DE DATOS
export DB_NAME="app_production"
export DB_USER="app_user"
export DB_HOST="localhost"
export DB_PORT="5432"

# MONITOREO Y LOGGING
export PROMETHEUS_PORT="9090"
export GRAFANA_PORT="3000"
export LOG_RETENTION_DAYS="30"

# BACKUP Y RETENCIÓN
export BACKUP_DIR="/backups"
export BACKUP_RETENTION_DAYS="7"
export AWS_S3_BUCKET="backups-tudominio"  # Opcional para cloud

# SEGURIDAD
export FAIL2BAN_BANTIME="86400"
export FAIL2BAN_MAXRETRY="3"
export UFW_DEFAULT_DENY="true"
EOF

# Cargar variables en la sesión actual
source /etc/server-config.env

🔧 1. Configuración Inicial del Sistema

1.1 Actualización del Sistema usando Variables

# Cargar configuración
source /etc/server-config.env

# Configurar timezone usando variable
sudo timedatectl set-timezone $SERVER_TIMEZONE

# Actualizar sistema
sudo apt update && sudo apt upgrade -y

# Verificar configuración
echo "=== Configuración del Servidor ==="
echo "Servidor: $SERVER_NAME"
echo "Entorno: $ENVIRONMENT"
echo "Timezone: $SERVER_TIMEZONE"
echo "Usuario Deploy: $DEPLOY_USER"

1.2 Creación de Usuarios con Variables

# Crear usuario de deploy desde variable
sudo adduser $DEPLOY_USER
sudo usermod -aG sudo $DEPLOY_USER

# Configurar directorio SSH seguro
sudo mkdir -p /home/$DEPLOY_USER/.ssh
sudo chmod 700 /home/$DEPLOY_USER/.ssh

🛡️ 2. Hardening de Seguridad con Configuración Flexible

2.1 Configuración Dinámica de SSH

# Backup de configuración original
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Aplicar configuración dinámica
sudo tee -a /etc/ssh/sshd_config > /dev/null << EOF
# =============================================================================
# CONFIGURACIÓN SSH AUTOMATIZADA - $(date)
# =============================================================================

# Puerto desde variable de entorno
Port $SSH_PORT

# Seguridad básica
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no

# Limitar acceso
AllowUsers $DEPLOY_USER
MaxAuthTries 3
MaxSessions 5

# Criptografía moderna
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org
MACs hmac-sha2-512-etm@openssh.com
EOF

# Recargar servicio SSH
sudo systemctl reload ssh

2.2 Configuración de Firewall con Variables

# Configurar UFW dinámicamente
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Reglas desde variables
sudo ufw allow $SSH_PORT/tcp comment 'SSH personalizado'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Rate limiting usando variables
sudo ufw limit $SSH_PORT/tcp

# Habilitar firewall
sudo ufw enable

📊 3. Monitoreo y Métricas con Variables Configurables

3.1 Node Exporter con Configuración Dinámica

# Crear usuario para monitoring
sudo useradd --no-create-home --shell /bin/false node_exporter

# Descargar y configurar Node Exporter
cd /tmp
NODE_EXPORTER_VERSION="1.6.1"
wget https://github.com/prometheus/node_exporter/releases/download/v$NODE_EXPORTER_VERSION/node_exporter-$NODE_EXPORTER_VERSION.linux-amd64.tar.gz
tar xvfz node_exporter-*.tar.gz
sudo mv node_exporter-*/node_exporter /usr/local/bin/

# Crear servicio systemd con variables
sudo tee /etc/systemd/system/node_exporter.service > /dev/null << EOF
[Unit]
Description=Node Exporter $NODE_EXPORTER_VERSION
Documentation=https://prometheus.io/docs/guides/node-exporter/
After=network.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
  --web.listen-address=:$PROMETHEUS_PORT \
  --collector.systemd \
  --collector.logind \
  --collector.processes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter

🔍 4. Variables de Entorno para Aplicaciones

4.1 Archivo de Configuración de Aplicación

# Crear variables específicas para la aplicación
sudo tee /etc/app-environment.env > /dev/null << EOF
# =============================================================================
# CONFIGURACIÓN DE APLICACIÓN - NO COMMITEAR AL REPOSITORIO
# =============================================================================

# Base de Datos
export DATABASE_URL="postgresql://$DB_USER:@$DB_HOST:$DB_PORT/$DB_NAME"
export DB_POOL_SIZE="20"
export DB_TIMEOUT="30"

# Redis Cache
export REDIS_URL="redis://localhost:6379"
export REDIS_PASSWORD=""

# API Keys y Secrets
export JWT_SECRET="$(openssl rand -hex 32)"
export ENCRYPTION_KEY="$(openssl rand -hex 16)"

# Servicios Externos
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="587"
export SMTP_USER="noreply@$DOMAIN"

# Características de la Aplicación
export LOG_LEVEL="info"
export NODE_ENV="production"
export PORT="3000"
EOF

# Proteger el archivo de configuración
sudo chmod 600 /etc/app-environment.env
sudo chown $DEPLOY_USER:$DEPLOY_USER /etc/app-environment.env

🚀 5. Próximos Pasos Estratégicos

Fase 1: Inmediata (Primera Semana)

# 1. Implementar sistema de backups automatizado
sudo tee /usr/local/bin/backup-script.sh > /dev/null << 'EOF'
#!/bin/bash
source /etc/server-config.env

BACKUP_FILE="backup-$(date +%Y%m%d-%H%M%S).tar.gz"
LOG_FILE="/var/log/backups.log"

echo "$(date): Iniciando backup" >> $LOG_FILE

# Backup de bases de datos
sudo -u postgres pg_dumpall | gzip > $BACKUP_DIR/db-$BACKUP_FILE

# Backup de configuraciones
tar -czf $BACKUP_DIR/config-$BACKUP_FILE /etc

# Rotación
find $BACKUP_DIR -name "*.tar.gz" -mtime +$BACKUP_RETENTION_DAYS -delete

echo "$(date): Backup completado: $BACKUP_FILE" >> $LOG_FILE
EOF

sudo chmod +x /usr/local/bin/backup-script.sh

Fase 2: Corto Plazo (2–4 Semanas)

🎯 ROADMAP DE MEJORAS – PRÓXIMOS 30 DÍAS

1. Monitoreo Avanzado

  • [ ] Implementar Grafana para dashboards
  • [ ] Configurar alertas por email/Telegram
  • [ ] Monitoreo de logs con ELK Stack
  • [ ] Métricas de negocio personalizadas

2. Seguridad Adicional

  • [ ] Implementar WAF (Web Application Firewall)
  • [ ] Configurar Cloudflare para DDoS protection
  • [ ] Auditoría de seguridad automatizada
  • [ ] Scaneo de vulnerabilidades semanal

3. Alta Disponibilidad

  • [ ] Configurar balanceador de carga
  • [ ] Replicación de base de datos
  • [ ] Servidores en múltiples regiones
  • [ ] Failover automático

Fase 3: Medio Plazo (1–3 Meses)

# docker-compose.prod.yml - Ejemplo de orquestación futura
version: '3.8'
services:
  app:
    image: myapp:${APP_VERSION}
    env_file: /etc/app-environment.env
    ports:
      - "3000:3000"
    depends_on:
      - postgres
      - redis
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl

📋 Checklist de Verificación con Variables

Script de Verificación Automatizado

#!/bin/bash
# verify-deployment.sh

# Cargar configuración
source /etc/server-config.env

echo "=== VERIFICACIÓN DE DESPLIEGUE ==="
echo "Servidor: $SERVER_NAME"
echo "Entorno: $ENVIRONMENT"
echo ""

checks=(
    "Variables de entorno:test -f /etc/server-config.env && echo '✅' || echo '❌'"
    "Usuario deploy:id $DEPLOY_USER >/dev/null 2>&1 && echo '✅' || echo '❌'"
    "Puerto SSH:sshd -T | grep -q 'port $SSH_PORT' && echo '✅' || echo '❌'"
    "Firewall:sudo ufw status | grep -q 'Status: active' && echo '✅' || echo '❌'"
    "Node Exporter:curl -s http://localhost:$PROMETHEUS_PORT/metrics >/dev/null && echo '✅' || echo '❌'"
    "Backups:test -f /usr/local/bin/backup-script.sh && echo '✅' || echo '❌'"
    "Logging:sudo systemctl is-active rsyslog | grep -q 'active' && echo '✅' || echo '❌'"
    "NTP:timedatectl status | grep -q 'synchronized: yes' && echo '✅' || echo '❌'"
)

for check in "${checks[@]}"; do
    IFS=':' read -r description command <<< "$check"
    result=$(eval "$command")
    printf "%-25s %s\n" "$description" "$result"
done

echo ""
echo "=== PRÓXIMOS PASOS RECOMENDADOS ==="
echo "1. Configurar backups en cloud: $AWS_S3_BUCKET"
echo "2. Implementar monitoreo avanzado en puerto: $GRAFANA_PORT"
echo "3. Configurar alertas para: $ADMIN_EMAIL"
echo "4. Programar auditoría de seguridad semanal"

🔮 Estrategia de Evolución del Servidor

Arquitectura Objetivo a 6 Meses

graph TB A[Usuario] --> B[Cloudflare DNS] B --> C[Load Balancer] C --> D[Servidor Web 1] C --> E[Servidor Web 2] D --> F[Base de Datos Master] E --> F F --> G[Base de Datos Replica] D --> H[Redis Cluster] E --> H I[Monitoring] --> J[Prometheus] J --> K[Grafana] J --> L[Alert Manager]

Tecnologías a Evaluar

🚀 Tecnologías para Escalabilidad

Contenedores y Orquestación

  • Docker Swarm: Para clusters simples
  • Kubernetes: Para orquestación compleja
  • Nomad: Alternativa lightweight

Monitoreo y Observabilidad

  • Grafana Loki: Log aggregation
  • Tempo: Distributed tracing
  • Jaeger: APM y tracing

Seguridad Avanzada

  • Vault: Gestión de secrets
  • Teleport: Access management
  • Falco: Security monitoring

📞 Plan de Respuesta a Incidentes

Checklist de Emergencia

#!/bin/bash
# emergency-checklist.sh

source /etc/server-config.env

echo "🚨 CHECKLIST DE EMERGENCIA - $SERVER_NAME"
echo "Tiempo: $(date)"
echo ""

echo "1. VERIFICAR ESTADO DEL SERVIDOR"
uptime
free -h
df -h

echo ""
echo "2. VERIFICAR SERVICIOS CRÍTICOS"
systemctl is-active nginx postgresql redis

echo ""
echo "3. REVISAR LOGS RECIENTES"
journalctl --since "10 minutes ago" -p err

echo ""
echo "4. CONEXIONES ACTIVAS"
ss -tulpn | grep -E "($SSH_PORT|80|443|5432)"

echo ""
echo "5. CONTACTOS DE EMERGENCIA"
echo "Admin: $ADMIN_EMAIL"
echo "Backup Contact: backup-admin@$DOMAIN"

✅ Conclusión y Mantenimiento Continuo

Resumen de Variables Críticas

# Comando para verificar configuración actual
echo "=== RESUMEN DE CONFIGURACIÓN ==="
echo "🔧 Servidor: $SERVER_NAME"
echo "🌍 Dominio: $DOMAIN"
echo "🔐 SSH Port: $SSH_PORT"
echo "📊 Monitoreo: $PROMETHEUS_PORT"
echo "💾 Backups: $BACKUP_DIR"
echo "🛡️ Retención Logs: $LOG_RETENTION_DAYS días"

Mantenimiento Programado Recomendado

# /etc/cron.d/server-maintenance
0 2 * * * root /usr/local/bin/backup-script.sh
0 3 * * 1 root apt update && apt upgrade -y
0 4 * * * root /usr/local/bin/security-scan.sh
0 5 * * * root find /var/log -name "*.log" -mtime +$LOG_RETENTION_DAYS -delete

Próximos Pasos Inmediatos

  1. Ejecutar el script de verificación.
  2. Configurar alertas de monitoreo.
  3. Programar primera auditoría de seguridad.
  4. Documentar procedimientos de recuperación.

¿Listo para el siguiente nivel? Comienza con la Fase 1 y adapta las variables y configuraciones a tu caso de uso específico.