You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bienvenido coder, en esta guía vas a aprender a configurar un servidor web Linux como servidores cloud implementando las mejores prácticas y recomendaciones para que despliegues tu aplicación o página web de la mejor manera, aplicando las mejores prácticas de seguridad. Si te gusta la guía, apóyame con una estrella y reaccionando a la discusión.
Si deseas apoyarme para seguir brindando soporte a esta guía, ¡te agradecería un montón por tu hamburguesa!
En la presente guía realicé la configuración en un servidor Linux con el sistema operativo AlmaLinux 9, una distribución basada en Red Hat Enterprise Linux (RHEL) 9. Pueden usar cualquier otra distribución como Ubuntu, Debian, Rocky Linux, etc., pero tengan en cuenta que las rutas de los directorios y los comandos pueden variar según el sistema operativo elegido. La mayoría de los comandos están basados en la shell Bash, que es el intérprete de comandos predeterminado en la mayoría de las distribuciones Linux. Sin más preámbulos, comencemos con la configuración.
Configuraciones Básicas y Optimización del Sistema
Conexión Inicial
Primero, iniciamos la configuración de nuestro servidor realizando la conexión SSH con el usuario root proporcionado por nuestro proveedor de servidor cloud.
Actualización del Sistema
Ejecutamos los siguientes comandos para actualizar el sistema:
dnf update -y
dnf upgrade -y
Una vez terminado, mostrará:
Limpieza del Sistema
Tras la actualización, procedemos a limpiar y remover paquetes obsoletos.
Nota: El comando dnf autoremove puede eliminar paquetes que necesites. Verifica la lista de paquetes a remover antes de confirmar la eliminación.
Este conjunto de comandos realiza una limpieza profunda del sistema: elimina paquetes innecesarios, limpia la caché del gestor de paquetes DNF, libera memoria RAM y elimina archivos temporales. Los comandos de monitoreo (free -h y df -h) permiten verificar el impacto de la limpieza en el sistema.
Configuración SSH y SCP
Ahora vamos a configurar nuestra conexión SSH procurando mantener activa nuestra compatibilidad SCP, ya que ésta nos permitirá transferir archivos de manera efectiva y rápida entre nuestro servidor y nuestro dispositivo local y viceversa.
Como primer paso, vamos a incorporar las siguientes configuraciones a nuestro archivo de configuración SSH que se encuentra en la siguiente ruta:
vi /etc/ssh/sshd_config
Configuraciones Básicas del protocolo SSH
Port 22
Port #### # IMPORTANTE: Reemplazar por el número de puerto que queremos reasignar
Protocol 2 # Solo usar protocolo SSH v2
AddressFamily inet # Solo IPv4 para reducir superficie de ataque## Autenticación
LoginGraceTime 30 # Tiempo límite para autenticación
PermitRootLogin no # Deshabilitar login directo como root
MaxAuthTries 3 # Máximo de intentos de autenticación
MaxSessions 2 # Limitar sesiones simultáneas## Claves y contraseñas
PubkeyAuthentication yes # Permitir autenticación por clave pública
PasswordAuthentication no # Mantener autenticación por contraseña (temporal)
PermitEmptyPasswords no # No permitir contraseñas vacías
AuthenticationMethods publickey
ChallengeResponseAuthentication no
UsePAM yes
## Seguridad de transferencia
AllowTcpForwarding yes # Necesario para SCP
X11Forwarding no # Deshabilitar reenvío X11
AllowAgentForwarding no # Deshabilitar reenvío de agente## Timeouts y sesión
ClientAliveInterval 300 # Verificar cliente cada 5 minutos
ClientAliveCountMax 3 # Desconectar después de 3 fallos
TCPKeepAlive yes # Mantener conexiones TCP activas## Restricciones adicionales
MaxStartups 10:30:60 # Limitar conexiones simultáneas
UseDNS no # Deshabilitar resolución DNS
Al agregar y guardar nuestra configuración, procedemos a insertar nuestra llave privada de acceso a nuestro servidor para que solo nosotros que contenemos la llave podamos acceder a nuestro servidor.
Agregar la Clave Privada en el Servidor Web
En la ruta principal de nuestro usuario root tenemos un directorio llamado .ssh en el cual se encuentran las llaves de conexión a nuestro servidor. Aquí se encuentran las llaves de acceso de nuestro proveedor como también de algunos usuarios que brindan soporte.
Al ingresar al directorio:
cd /root/.ssh/
Y ejecutar ls tendremos los siguientes archivos:
authorized_keys: En este archivo tendremos las claves de quienes brindan soporte a nuestro servidor (PROVEEDOR)
id_rsa: No borrar
id_rsa.pub: No borrar
Primero realizamos una copia de seguridad, creando un directorio en el cual irán todos los archivos originales. Ya que éstos serán necesarios para cuando posteriormente queramos actualizar nuestro servidor ampliando memoria o más características y se necesite el soporte de nuestro proveedor para asignar de manera correcta a nuestro servidor.
Una vez completado el respaldo, procederemos a crear nuestro par de claves (pública y privada) para agregarlas al servidor. Este proceso lo realizaré desde una máquina con Win11, pero esto se puede realizar también en una máquina Linux.
Creación de Claves en Windows 11
En una terminal de PowerShell ejecutamos el siguiente comando para la generación de las claves de seguridad SSH. El sistema nos solicitará la ruta donde se guardarán y una frase de seguridad. En este caso, utilizaremos la ruta por defecto y asignaremos una frase segura.
ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (C:\rutaUsuario/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\rutaUsuario/.ssh/id_rsa
Your public key has been saved in C:\rutaUsuario/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:[KEY]
The key's randomart image is:+---[RSA 4096]----+|B+o. .+o * o. ||=o+ o.+.B B . ||o* =...+.= .. ||..=.oo.... . || ..o ...S.* || . . ...+.o || o o. . || |+----[SHA256]-----+
Para visualizar nuestra clave generada y agregarla en nuestro servidor cloud, ejecutamos:
type C:\rutaUsuario\.ssh\id_rsa.pub
-- COPIAMOS LA SIGUIENTE LLAVE COMPLETA
ssh-rsa [KEY]
Ahora procedemos a borrar todo el contenido de nuestro archivo authorized_keys:
vi .ssh/authorized_keys
Eliminamos todas las llaves que contiene nuestro archivo, procurando observar el formato de registro de las llaves para poder insertar correctamente la nuestra.
NOTA: Con el editor vi, para borrar el contenido ingresamos al modo visualizador presionando la tecla 'v', seleccionamos lo que deseamos eliminar y presionamos la tecla 'd'.
Después salimos guardando e insertamos nuestra clave con el siguiente comando:
Ingresamos a revisar que se haya insertado correctamente como en la siguiente imagen:
Al terminar de agregar la llave, guardamos y procedemos a reiniciar el servicio para comprobar que todo esté correcto.
Ejecutamos los siguientes comandos:
systemctl restart sshd
systemctl status sshd
Si todo está correcto, nos indicará que el servidor se inició correctamente y no tenemos ningún error:
Creación del Único Usuario de Acceso con Permisos Root
Tras ya tener nuestra clave ingresada y registrada en nuestro servidor, procedemos a crear un único usuario con permisos root, el cual podrá acceder al sistema. Solo este usuario podrá acceder a nuestro servidor web.
Con los siguientes comandos:
[root ~]# useradd -m -G wheel sunken
[root ~]# passwd sunken
Cambiando la contraseña del usuario sunken.
Nueva contraseña:
Vuelva a escribir la nueva contraseña:
passwd: todos los tokens de autenticación se actualizaron exitosamente.
Ahora asignamos todos los permisos necesarios para nuestro usuario:
Con estos comandos se le asignan las claves SSH para que se pueda conectar, otorgando también los permisos de superusuario del sistema.
[root ~]# systemctl restart sshd
[root ~]# systemctl status sshd
Ahora vamos a bloquear el login del usuario root y que solo permita la conexión al usuario que creamos. Como configuramos anteriormente ya en la configuración de SSH indicamos que se rechace la conexión del usuario root, pero falta asignar este bloqueo a nuestros archivos de 50-redhat.conf y 99-custom.conf que se encuentran en la ruta /etc/ssh/sshd_config.d/. Estos archivos son parte de la configuración modular de SSH en sistemas Red Hat, donde el 50-redhat.conf contiene configuraciones específicas de Red Hat y el 99-custom.conf está destinado para personalizaciones del administrador del sistema.
Primero con la configuración del primer archivo:
[root ~]# vi /etc/ssh/sshd_config.d/50-redhat.conf
Al final del archivo agregamos las siguientes líneas:
PermitRootLogin no
AllowUsers sunken
Ahora el siguiente archivo, modificamos el PermitRootLogin a valor de no:
[root ~]# vi /etc/ssh/sshd_config.d/99-custom.conf
PermitRootLogin no
PermitUserEnvironment yes
Salimos y guardamos el archivo. Ahora por último procedemos a verificar si la configuración del servicio está correcta y procedemos a reiniciar el servicio.
Si todo está configurado de manera correcta procedemos a cerrar la conexión SSH e intentamos iniciar sesión con el usuario root, este rechazará nuestra conexión indicando:
Pero si en nuestra cadena de conexión, en vez de ingresar con nuestro usuario root, colocamos el usuario que creamos, asignando el puerto de conexión el cual cambiamos, nos pedirá la frase de nuestra llave para efectuar la conexión y al insertar la frase correcta la conexión se establece de manera satisfactoria.
~
❯ ssh -p[Num_Puerto_Asignado] sunken@IP
Enter passphrase for key 'C:\rutaUsuario/.ssh/id_rsa':
[sunken ~]$
Probamos que tenemos acceso como superusuario con:
sudo su
[sunken ~]$ sudo su
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.#2) Think before you type.#3) With great power comes great responsibility.
[sudo] password for sunken:
[root@ sunken]#
Como se puede visualizar, nos solicita el ingreso de la contraseña del usuario que creamos. Después de ingresarla, ya tenemos permisos de superusuario.
Crear Copia de Seguridad del Sistema
Si deseamos tener una copia de seguridad de nuestro sistema con las configuraciones actuales, podremos realizarlo con los siguientes comandos:
Realizará una copia de seguridad completa de nuestro sistema operativo y, al terminar, transferiremos la copia de seguridad a nuestra máquina local con el siguiente comando. Con esto también comprobaremos que nuestro servicio de SCP funcione correctamente.
NOTA: Para poder guardar en el directorio principal de nuestra máquina local con Windows o en otra ruta, es recomendable ejecutar PowerShell como administrador.
Reemplaza /dev/sdX con el disco donde quieres instalar GRUB.
Asegúrate de actualizar fstab con los UUIDs correctos:
sudo blkid
sudo nano /etc/fstab
Reinicia la máquina:
sudo reboot
NOTA: Los UUIDs son identificadores únicos universales que el sistema utiliza para identificar de manera única los dispositivos de almacenamiento. Es crucial actualizarlos en el archivo fstab después de una restauración para asegurar que el sistema monte correctamente todas las particiones durante el arranque.
Configuración de Seguridad
Instalación y Configuración de Fail2ban
Fail2ban es una herramienta de seguridad informática diseñada para proteger servidores y sistemas contra ataques maliciosos, especialmente aquellos que buscan acceder de manera no autorizada mediante intentos repetidos de inicio de sesión. Su función principal es monitorear archivos de registro (logs) en busca de patrones sospechosos, como múltiples intentos fallidos de autenticación, y tomar medidas preventivas para bloquear las direcciones IP de los posibles atacantes.
Vamos a instalarlo y configurarlo para evitar y blindar nuestro servidor contra posibles ataques. Se implementará protección para SSH, monitoreo de accesos sospechosos en Nginx e integración de Firewalld para bloquear accesos.
Primero vamos a instalarlo con el siguiente comando:
[root@sunken]# dnf install fail2ban -y
En Fail2ban debemos respetar el siguiente esquema para tener una idea de cómo funciona y configurarlo correctamente. El jail.local toma las configuraciones de cada servicio en el jail.d. El nombre de cada servicio configurado tiene una extensión .conf y nosotros crearemos un .conf que funcionará como filtro para el servidor Nginx:
/etc/fail2ban/
├── jail.conf # Archivo base (nunca modificar)
├── jail.local # Configuraciones globales personalizadas
└── jail.d/
├── sshd.conf # Configuración específica para SSH
├── nginx-http-badbot.conf # Creación del filtro
Para configurarlo vamos a crear el archivo .local en la siguiente ruta:
[root@sunken]# vi /etc/fail2ban/jail.local
Ahora procedemos a pegar las siguientes configuraciones en nuestro archivo jail.local. Asegúrate de no guardar con comentarios:
[DEFAULT]bantime = 3600 # Tiempo de baneo: 1 hora (3600 segundos)findtime = 600 # Ventana de tiempo para buscar intentos fallidos: 10 minutosmaxretry = 5 # Número máximo de intentos antes del baneobackend = systemd # Usa systemd como backend para los logs[sshd]enabled = true
mode = normal
port = [NUM_PORT_SSH],22
filter = sshd
logpath = /var/log/secure
maxretry = 5
findtime = 600
bantime = 3600
banaction = iptables-multiport
protocol = tcp
# ignoreip = 127.0.0.1/8 ::1 Esta línea debería contener solo las IPs que quieres excluir del baneo puede ir nuestra máquina local y la del servidor.[selinux-ssh]port = [NUM_PORT_SSH],22
logpath = %(auditd_log)s
[nginx-http-badbot]enabled = true
port = http,https
filter = nginx-http-badbot
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 3600
Guardamos y salimos. Ahora vamos a crear nuestro filtro de protección para Nginx:
[root@sunken]# vi /etc/fail2ban/filter.d/nginx-http-badbot.conf
Ahora, para no tener problemas al activar nuestro servicio de fail2ban, otorgamos permisos para rc.local que es usado para ejecutar scripts personalizados durante el arranque del sistema:
[root@sunken]# chmod +x /etc/rc.d/rc.local
Ejecutamos:
[root@sunken]# systemctl start firewalld
NOTA: Vamos a perder conexión SSH con nuestro servidor. Debemos conectarnos mediante Consola VNC que generalmente se encuentra en nuestro proveedor del Servidor Web. Pueden aparecer alertas menores como "ip_set no está mantenido activamente", pero podemos ignorarlas ya que aún no terminamos de configurar nuestro servidor cloud.
Configuración del Firewall
Iniciamos sesión con nuestro usuario y accedemos como superusuario para activar nuestra conexión SSH y terminar de configurar de manera correcta.
En el siguiente comando podemos observar que no tenemos conexión porque nuestro puerto SSH y los demás puertos para el servidor de Nginx no están agregados. Para ello vamos a agregarlos:
Verificamos que nuestras configuraciones estén funcionando correctamente con los siguientes comandos:
[root@sunken]# sudo fail2ban-client -d
[root@sunken]# sudo fail2ban-client status
[root@sunken]# sudo fail2ban-client status nginx-http-badbot
[root@sunken]# sudo fail2ban-client status sshd
Si queremos desbloquear (unban) una IP, podemos ejecutar el siguiente comando, en el cual solo reemplazamos el nombre del servicio del que queremos remover el bloqueo:
[root@sunken]# sudo fail2ban-client set nginx-http-badbot unbanip x.x.x.x
Transferencia de Archivos
Para la siguiente sección debemos recordar cómo realizar la transferencia de archivos. A continuación, se presentan ejemplos de cómo transferir archivos desde y hacia nuestro servidor.
NOTA: Reemplaza [NUM_PORT_SSH], [IP_SERVER], name-project y name.online con tus valores correspondientes.
Configuración del Servidor Nginx
Ahora instalaremos nuestro servidor Nginx. Si instalamos desde nuestro gestor de paquetes por defecto nos instalará una versión desactualizada del paquete, la cual no requerimos ya que somos unos masters y no queremos manejarnos con versiones desactualizadas.
Como se ve a continuación:
[root@sunken]# yum info nginx
Last metadata expiration check: 0:04:33 ago on Sat Jan 11 01:17:13 2025.
Installed Packages
Name : nginx
Epoch : 2
Version : 1.20.1
Release : 20.el9.alma.1
Architecture : x86_64
Size : 148 k
Source : nginx-1.20.1-20.el9.alma.1.src.rpm
Repository : @System
From repo : local-appstream
Summary : A high performance web server and reverse proxy server
URL : https://nginx.org
License : BSD
Description : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
: IMAP protocols, with a strong focus on high concurrency, performance and low
: memory usage.
Obviamente necesitamos la versión actual pero estable. En este caso vamos a realizar los siguientes cambios en nuestro sistema para obtener los paquetes actuales y no tener ningún problema. Me apoyé en la documentación oficial de:
He indicado, con el parámetro priority=1, que se dé prioridad al primer repositorio, que contiene la versión estable. En el segundo, solo lo dejé activado.
Ahora, tras guardar el archivo, procedemos a limpiar e instalar Nginx. Si en caso tenemos pre-instalado Nginx, ejecutamos:
NOTA: Recomiendo ejecutar dos veces yum autoremove ya que algunas dependencias que se remueven heredan otras que no se usan.
Continuando, vamos a proceder a limpiar la caché y refrescarla para poder instalar de manera correcta el paquete:
[root@sunken]# yum clean all
[root@sunken]# yum makecache
IMPORTANTE: Ten en cuenta al instalar el paquete no aceptes todas las claves, solamente la que especifica la documentación oficial. En la actualidad, la clave GPG debe coincidir con: 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
Ahora sí procedemos a instalar el paquete con el siguiente comando. Para asegurarnos de que instalamos la versión estable, ejecutamos:
Ahora creemos la configuración de Nginx para tu dominio. Crea el archivo:
[root@sunken]# vi /etc/nginx/conf.d/name.online.conf
Agrega estas configuraciones temporales para generar el certificado SSL:
server{listen80;server_name name.online www.name.online;root /var/www/name.online;indexindex.html; # Comentamos temporalmente la configuración SSL #listen 443 ssl; #http2 on; #listen 443 quic reuseport; #ssl_certificate /etc/letsencrypt/live/name.online/fullchain.pem; #ssl_certificate_key /etc/letsencrypt/live/name.online/privkey.pem; # ... (comenta el resto de la configuración SSL)location / {try_files$uri$uri/ /index.html;}location /.well-known/acme-challenge/ {root /var/www/certbot;}}
Preparación para el Certificado SSL
Ahora podemos proceder con la generación de nuestro certificado SSL.
Configura los registros DNS de tu dominio:
Agrega un registro A que apunte a la IP de tu servidor, si quieres www, agrega un CNAME para www que apunte a tu dominio principal
NOTA: Ten en cuenta que para este paso ya debes tener apuntando tu dominio a tu servidor. En mi caso, mi proveedor me facilita de manera gráfica conectar mi dominio con el servidor, ya que tengo contratado el dominio y el servidor en el mismo proveedor.
Instalación del Certificado SSL
Continuamos con la instalación del certificado SSL siguiendo la documentación oficial de Certbot. Procedemos a ejecutar los siguientes comandos:
NOTA: Puede indicar error: "too early for operation, device not yet seeded or device model not acknowledged". Se soluciona volviendo a ejecutar el comando.
Ahora, tras guardar el archivo, vamos a verificar que la configuración de nuestro servidor Nginx esté correcta con los siguientes comandos:
[root@sunken]# nginx -t
NOTA: Si está correcto indicará:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@sunken]# nginx -s reload
Ahora generamos el certificado apuntando a la carpeta de nuestro servidor al cual queremos agregar el certificado, usando el archivo recién creado. Para ello ejecutamos el siguiente comando:
El proceso de generación del certificado te pedirá:
Un correo electrónico que te notificará cuando caduque el certificado y necesite autorenovarse
Aceptar los términos y condiciones
Opción de compartir tu correo para información adicional
Ejemplo de la salida del comando:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): name@example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
[...]
Certificate is saved at: /etc/letsencrypt/live/name.online/fullchain.pem
Key is saved at: /etc/letsencrypt/live/name.online/privkey.pem
This certificate expires on 2025-04-12.
NOTA: No te preocupes por la renovación del certificado. Los paquetes de Certbot en tu sistema vienen con una tarea cron o un temporizador systemd que renovará tus certificados automáticamente antes de que caduquen. No necesitarás ejecutar Certbot de nuevo, a menos que cambies tu configuración.
Felicidades 🎉, ya tienes tu servidor implementado con un certificado SSL. Aunque este es gratuito y solo valida la propiedad del dominio, si requieres otro tipo de certificado, procura informarte cuál necesita tu modelo de negocio. Puedes adquirir certificados comerciales en diferentes páginas como www.digicert.com, que usa Facebook.
Configuración Final Nginx
Después de haber generado el certificado, debes reemplazar la configuración temporal con la configuración que se verá a continuación.
Volvemos a ingresar en el archivo name.online.conf:
[root@sunken]# vi /etc/nginx/conf.d/name.online.conf
Eliminamos todo el contenido y pegamos la siguiente configuración:
¡Bien! Aquí ya puedes subir el build de tu aplicación. En mi caso, uso Angular para construir mis aplicaciones y páginas web porque me encanta su arquitectura. Para subir los archivos desde tu máquina local a tu servidor, usa el siguiente comando:
Por última parte, ahora verificamos que Nginx no tenga errores:
[root@sunken]# nginx -t
Si todo está bien y no hay errores, procedemos a reiniciar el servidor Nginx:
[root@sunken]# systemctl restart nginx
Para asegurarnos de que todo está marchando como debe, comprobamos que el servidor esté corriendo de manera correcta con el siguiente comando:
[root@sunken]# systemctl status nginx
¡Y listo! Ahora podemos ingresar a nuestro dominio en el navegador y comprobar que todo esté funcionando de manera correcta. No olvides verificar que el certificado SSL se haya implementado correctamente - deberías ver el candadito en la barra de direcciones de tu navegador. Si todo salió bien, ¡felicidades! Ya tienes tu aplicación corriendo de manera segura en tu servidor. :D
Protección contra Ataques DDoS
¡Excelente! Ahora vamos a dar un plus más de seguridad a nuestro servidor implementando protección contra ataques DDoS. Vamos a ser más restrictivos y limitar a solo 20 conexiones simultáneas (más seguro para aplicaciones pequeñas y medianas).
¿Qué hace cada parte de este comando? Te lo explico:
--connlimit-above 10: Limita a 20 conexiones por IP
--connlimit-mask 32: Aplica el límite a cada IP individual
--dport 80 y --dport 443: Aplica para conexiones HTTP y HTTPS
-j REJECT: Rechaza las conexiones que superen el límite
Ahora vamos con la configuración del kernel. Abre el archivo:
[root@sunken]# vi /etc/sysctl.conf
Agrega estas configuraciones y te explico cada sección:
# Protección contra SYN flood (ataques que saturan con peticiones de conexión)net.ipv4.tcp_syncookies = 1 # Activa cookies SYN para proteger contra inundacionesnet.ipv4.tcp_syn_retries = 5 # Número de reintentos para conexiones salientesnet.ipv4.tcp_synack_retries = 2 # Número de reintentos para respuestas SYN-ACK# Aumentar el backlog de conexiones (cola de conexiones pendientes)net.core.somaxconn = 65535 # Máximo de conexiones pendientes en colanet.core.netdev_max_backlog = 65535 # Máximo de paquetes en cola de procesamiento# Protección contra ataques ICMP (ping floods)net.ipv4.icmp_echo_ignore_broadcasts = 1 # Ignora pings broadcastnet.ipv4.icmp_ignore_bogus_error_responses = 1 # Ignora respuestas ICMP malformadas# Habilitar protección contra IP spoofing (suplantación de IP)net.ipv4.conf.all.rp_filter = 1 # Activa filtro de ruta inversanet.ipv4.conf.default.rp_filter = 1 # Lo mismo para nuevas interfaces# Deshabilitar redirección ICMP (previene redirecciones maliciosas)net.ipv4.conf.all.accept_redirects = 0 # No aceptar redirecciones ICMPnet.ipv4.conf.default.accept_redirects = 0 # Lo mismo para nuevas interfacesnet.ipv4.conf.all.secure_redirects = 0 # No aceptar redirecciones "seguras"net.ipv4.conf.default.secure_redirects = 0 # Lo mismo para nuevas interfaces# Ajustar timeouts TCP (reduce recursos ocupados por conexiones muertas)net.ipv4.tcp_fin_timeout = 30 # Tiempo para cerrar conexiones (en segundos)net.ipv4.tcp_keepalive_time = 1200 # Tiempo entre comprobaciones keepalive# Limitar conexiones TCP (previene agotamiento de recursos)net.ipv4.tcp_max_syn_backlog = 65536 # Máximo de conexiones TCP semi-abiertasnet.ipv4.tcp_max_tw_buckets = 65536 # Máximo de sockets en estado TIME_WAIT
Aplicamos los cambios al kernel:
[root@sunken]# sysctl -p
Por último, configuramos los límites de recursos del sistema:
[root@sunken]# vi /etc/security/limits.conf
Agregamos al final (después de "# End of file"):
# Límites para el usuario www-data (usuario de Nginx)
www-data soft nproc 4000 # Límite suave de procesos (puede superarse temporalmente)
www-data hard nproc 8000 # Límite duro de procesos (no puede superarse)
www-data soft nofile 16384 # Límite suave de archivos abiertos
www-data hard nofile 32768 # Límite duro de archivos abiertos
¡Y ahora sí! Necesitamos reiniciar el servidor para que todos los cambios surtan efecto:
[root@sunken]# reboot
NOTA: Estos valores son bastante conservadores y seguros para la mayoría de las aplicaciones web pequeñas y medianas. Si tu aplicación maneja mucho tráfico o necesitas más conexiones simultáneas, puedes ajustar estos números gradualmente mientras monitorizas el rendimiento del servidor.
CONSEJO: Para monitorizar si estos límites están funcionando, puedes revisar los logs de Nginx (/var/log/nginx/error.log) y del sistema (journalctl -xe) en busca de conexiones rechazadas. 🔍
🚀 ¡Servidor Desplegado y Blindado con Éxito!
¡Y así llegamos al final coders! Espero que esta guía les haya ayudado a configurar su servidor web Linux de manera segura y profesional. Como pudieron ver, hemos implementado las mejores prácticas y recomendaciones para que puedan desplegar sus aplicaciones o páginas web de la mejor manera posible. Si les gustó la guía, ¡apóyenme con una estrella y reaccionando a la discusión!
Recuerden que este es un proyecto vivo y seguiré brindando soporte y actualizaciones a medida que lo requieran. ¿Encontraste algún error? ¿Tienes sugerencias? ¡No dudes en abrir un issue! Entre todos podemos hacer que esta guía sea cada vez mejor.
Si deseas apoyarme para seguir brindando soporte a esta guía y crear más contenido como este, ¡te agradecería un montón por tu hamburguesa! 🍔
¡Feliz coding y que sus servidores sean tan seguros como Fort Knox! 💪
documentationImprovements or additions to documentationserver-security-enhancementAdvanced improvements and optimizations for secure Linux server deployment in web and cloud environmsecurityAdvanced security configurations and best practices for server protection and hardeningcommunity-contributionOpen for community contributions and improvements to maintain guide relevance and qualitybeginner-friendlyStructured and accessible guide for system administrators of all experience levels
1 participant
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Implementación Segura de Servidores Linux
Versión 2025.1
Introducción
Bienvenido coder, en esta guía vas a aprender a configurar un servidor web Linux como servidores cloud implementando las mejores prácticas y recomendaciones para que despliegues tu aplicación o página web de la mejor manera, aplicando las mejores prácticas de seguridad. Si te gusta la guía, apóyame con una estrella y reaccionando a la discusión.
Si deseas apoyarme para seguir brindando soporte a esta guía, ¡te agradecería un montón por tu hamburguesa!
En la presente guía realicé la configuración en un servidor Linux con el sistema operativo AlmaLinux 9, una distribución basada en Red Hat Enterprise Linux (RHEL) 9. Pueden usar cualquier otra distribución como Ubuntu, Debian, Rocky Linux, etc., pero tengan en cuenta que las rutas de los directorios y los comandos pueden variar según el sistema operativo elegido. La mayoría de los comandos están basados en la shell Bash, que es el intérprete de comandos predeterminado en la mayoría de las distribuciones Linux. Sin más preámbulos, comencemos con la configuración.
📑 Índice de Contenidos
Configuraciones Básicas y Optimización del Sistema
Conexión Inicial
Primero, iniciamos la configuración de nuestro servidor realizando la conexión SSH con el usuario root proporcionado por nuestro proveedor de servidor cloud.
Actualización del Sistema
Ejecutamos los siguientes comandos para actualizar el sistema:
Una vez terminado, mostrará:

Limpieza del Sistema
Tras la actualización, procedemos a limpiar y remover paquetes obsoletos.
Pasos de Limpieza
Descripción del Proceso
Este conjunto de comandos realiza una limpieza profunda del sistema: elimina paquetes innecesarios, limpia la caché del gestor de paquetes DNF, libera memoria RAM y elimina archivos temporales. Los comandos de monitoreo (
free -hydf -h) permiten verificar el impacto de la limpieza en el sistema.Configuración SSH y SCP
Ahora vamos a configurar nuestra conexión SSH procurando mantener activa nuestra compatibilidad SCP, ya que ésta nos permitirá transferir archivos de manera efectiva y rápida entre nuestro servidor y nuestro dispositivo local y viceversa.
Como primer paso, vamos a incorporar las siguientes configuraciones a nuestro archivo de configuración SSH que se encuentra en la siguiente ruta:
Configuraciones Básicas del protocolo SSH
Al agregar y guardar nuestra configuración, procedemos a insertar nuestra llave privada de acceso a nuestro servidor para que solo nosotros que contenemos la llave podamos acceder a nuestro servidor.
Agregar la Clave Privada en el Servidor Web
En la ruta principal de nuestro usuario root tenemos un directorio llamado
.sshen el cual se encuentran las llaves de conexión a nuestro servidor. Aquí se encuentran las llaves de acceso de nuestro proveedor como también de algunos usuarios que brindan soporte.Al ingresar al directorio:
cd /root/.ssh/Y ejecutar
lstendremos los siguientes archivos:authorized_keys: En este archivo tendremos las claves de quienes brindan soporte a nuestro servidor (PROVEEDOR)id_rsa: No borrarid_rsa.pub: No borrarPrimero realizamos una copia de seguridad, creando un directorio en el cual irán todos los archivos originales. Ya que éstos serán necesarios para cuando posteriormente queramos actualizar nuestro servidor ampliando memoria o más características y se necesite el soporte de nuestro proveedor para asignar de manera correcta a nuestro servidor.
Una vez completado el respaldo, procederemos a crear nuestro par de claves (pública y privada) para agregarlas al servidor. Este proceso lo realizaré desde una máquina con Win11, pero esto se puede realizar también en una máquina Linux.
Creación de Claves en Windows 11
En una terminal de PowerShell ejecutamos el siguiente comando para la generación de las claves de seguridad SSH. El sistema nos solicitará la ruta donde se guardarán y una frase de seguridad. En este caso, utilizaremos la ruta por defecto y asignaremos una frase segura.
Para visualizar nuestra clave generada y agregarla en nuestro servidor cloud, ejecutamos:
Ahora procedemos a borrar todo el contenido de nuestro archivo authorized_keys:
Eliminamos todas las llaves que contiene nuestro archivo, procurando observar el formato de registro de las llaves para poder insertar correctamente la nuestra.
Después salimos guardando e insertamos nuestra clave con el siguiente comando:
Ingresamos a revisar que se haya insertado correctamente como en la siguiente imagen:
Al terminar de agregar la llave, guardamos y procedemos a reiniciar el servicio para comprobar que todo esté correcto.
Ejecutamos los siguientes comandos:
Si todo está correcto, nos indicará que el servidor se inició correctamente y no tenemos ningún error:
Creación del Único Usuario de Acceso con Permisos Root
Tras ya tener nuestra clave ingresada y registrada en nuestro servidor, procedemos a crear un único usuario con permisos root, el cual podrá acceder al sistema. Solo este usuario podrá acceder a nuestro servidor web.
Con los siguientes comandos:
Ahora asignamos todos los permisos necesarios para nuestro usuario:
Con estos comandos se le asignan las claves SSH para que se pueda conectar, otorgando también los permisos de superusuario del sistema.
Ahora vamos a bloquear el login del usuario root y que solo permita la conexión al usuario que creamos. Como configuramos anteriormente ya en la configuración de SSH indicamos que se rechace la conexión del usuario root, pero falta asignar este bloqueo a nuestros archivos de
50-redhat.confy99-custom.confque se encuentran en la ruta/etc/ssh/sshd_config.d/. Estos archivos son parte de la configuración modular de SSH en sistemas Red Hat, donde el50-redhat.confcontiene configuraciones específicas de Red Hat y el99-custom.confestá destinado para personalizaciones del administrador del sistema.Primero con la configuración del primer archivo:
Al final del archivo agregamos las siguientes líneas:
Ahora el siguiente archivo, modificamos el PermitRootLogin a valor de no:
Salimos y guardamos el archivo. Ahora por último procedemos a verificar si la configuración del servicio está correcta y procedemos a reiniciar el servicio.
Si todo está configurado de manera correcta procedemos a cerrar la conexión SSH e intentamos iniciar sesión con el usuario root, este rechazará nuestra conexión indicando:
Pero si en nuestra cadena de conexión, en vez de ingresar con nuestro usuario root, colocamos el usuario que creamos, asignando el puerto de conexión el cual cambiamos, nos pedirá la frase de nuestra llave para efectuar la conexión y al insertar la frase correcta la conexión se establece de manera satisfactoria.
Probamos que tenemos acceso como superusuario con:
Como se puede visualizar, nos solicita el ingreso de la contraseña del usuario que creamos. Después de ingresarla, ya tenemos permisos de superusuario.
Crear Copia de Seguridad del Sistema
Si deseamos tener una copia de seguridad de nuestro sistema con las configuraciones actuales, podremos realizarlo con los siguientes comandos:
Realizará una copia de seguridad completa de nuestro sistema operativo y, al terminar, transferiremos la copia de seguridad a nuestra máquina local con el siguiente comando. Con esto también comprobaremos que nuestro servicio de SCP funcione correctamente.
Creación de Backup
scp -P [PORT_SSH] sunken@IP_SERVER:/home/sunken/backup/almalinux-backup.tar.gz "C:\"Al ejecutar, se comenzará a recibir nuestro archivo de backup desde nuestro servidor.
Restauración del Backup en otra Máquina AlmaLinux 9
Para restaurar el sistema en otra máquina:
Prepara la máquina de destino:
Restaura el sistema:
Reparar GRUB y fstab (si es necesario):
Si la máquina de destino tiene diferente configuración de discos:
Reemplaza
/dev/sdXcon el disco donde quieres instalar GRUB.Reinicia la máquina:
Configuración de Seguridad
Instalación y Configuración de Fail2ban
Fail2ban es una herramienta de seguridad informática diseñada para proteger servidores y sistemas contra ataques maliciosos, especialmente aquellos que buscan acceder de manera no autorizada mediante intentos repetidos de inicio de sesión. Su función principal es monitorear archivos de registro (logs) en busca de patrones sospechosos, como múltiples intentos fallidos de autenticación, y tomar medidas preventivas para bloquear las direcciones IP de los posibles atacantes.
Vamos a instalarlo y configurarlo para evitar y blindar nuestro servidor contra posibles ataques. Se implementará protección para SSH, monitoreo de accesos sospechosos en Nginx e integración de Firewalld para bloquear accesos.
Primero vamos a instalarlo con el siguiente comando:
[root@sunken]# dnf install fail2ban -yEn Fail2ban debemos respetar el siguiente esquema para tener una idea de cómo funciona y configurarlo correctamente. El
jail.localtoma las configuraciones de cada servicio en eljail.d. El nombre de cada servicio configurado tiene una extensión.confy nosotros crearemos un.confque funcionará como filtro para el servidor Nginx:Para configurarlo vamos a crear el archivo
.localen la siguiente ruta:[root@sunken]# vi /etc/fail2ban/jail.localAhora procedemos a pegar las siguientes configuraciones en nuestro archivo
jail.local. Asegúrate de no guardar con comentarios:Guardamos y salimos. Ahora vamos a crear nuestro filtro de protección para Nginx:
[root@sunken]# vi /etc/fail2ban/filter.d/nginx-http-badbot.confAhora, para no tener problemas al activar nuestro servicio de fail2ban, otorgamos permisos para
rc.localque es usado para ejecutar scripts personalizados durante el arranque del sistema:[root@sunken]# chmod +x /etc/rc.d/rc.localEjecutamos:
[root@sunken]# systemctl start firewalldConfiguración del Firewall
Iniciamos sesión con nuestro usuario y accedemos como superusuario para activar nuestra conexión SSH y terminar de configurar de manera correcta.
En el siguiente comando podemos observar que no tenemos conexión porque nuestro puerto SSH y los demás puertos para el servidor de Nginx no están agregados. Para ello vamos a agregarlos:
[root@sunken]# sudo firewall-cmd --list-allLo vamos a agregar con los siguientes comandos:
Ahora como podemos observar tenemos los siguientes puertos agregados y levantados de manera correcta:
[root@sunken]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: cockpit dhcpv6-client ssh ports: [NUM_PORT_SSH]/tcp 80/tcp 443/tcp protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:Ahora ejecutamos los siguientes comandos para levantar los servicios y dejarlos funcionando por defecto:
Verificamos que nuestras configuraciones estén funcionando correctamente con los siguientes comandos:
Si queremos desbloquear (unban) una IP, podemos ejecutar el siguiente comando, en el cual solo reemplazamos el nombre del servicio del que queremos remover el bloqueo:
[root@sunken]# sudo fail2ban-client set nginx-http-badbot unbanip x.x.x.xTransferencia de Archivos
Para la siguiente sección debemos recordar cómo realizar la transferencia de archivos. A continuación, se presentan ejemplos de cómo transferir archivos desde y hacia nuestro servidor.
Descargar archivos desde el servidor
scp -P [NUM_PORT_SSH] sunken@[IP_SERVER]:/etc/fail2ban/jail.local "C:\"Subir archivos al servidor
scp -P [NUM_PORT_SSH] -r "C:\directoryProjectDeploy\dist\name-project\browser\*" sunken@[IP_SERVER]:/var/www/name.online/Configuración del Servidor Nginx
Ahora instalaremos nuestro servidor Nginx. Si instalamos desde nuestro gestor de paquetes por defecto nos instalará una versión desactualizada del paquete, la cual no requerimos ya que somos unos masters y no queremos manejarnos con versiones desactualizadas.
Como se ve a continuación:
Obviamente necesitamos la versión actual pero estable. En este caso vamos a realizar los siguientes cambios en nuestro sistema para obtener los paquetes actuales y no tener ningún problema. Me apoyé en la documentación oficial de:
Aquí podrán encontrar la documentación exacta según su distribución.
Instalación y Configuración
En el archivo, podremos observar el

[appstream]. El parámetroenabledestará en 1; vamos a reemplazarlo por el valor de 0.[root@sunken]# vi /etc/yum.repos.d/nginx.repoAgregamos lo siguiente:
He indicado, con el parámetro
priority=1, que se dé prioridad al primer repositorio, que contiene la versión estable. En el segundo, solo lo dejé activado.[root@sunken]# yum install nginx --enablerepo=nginx-stableAl terminar, podemos verificar la instalación:
Configuración del Servidor Nginx Aplicando Medidas de Seguridad y HTTP/3
Ahora procedemos con el levantamiento, ejecución y verificación de nuestro servidor. Para eso ejecutamos los siguientes comandos:
Procedemos a editar el archivo principal de configuración:
[root@sunken]# vi /etc/nginx/nginx.confPueden reemplazar la configuración predeterminada con la siguiente:
Configuración del Dominio
Ahora creemos la configuración de Nginx para tu dominio. Crea el archivo:
[root@sunken]# vi /etc/nginx/conf.d/name.online.confAgrega estas configuraciones temporales para generar el certificado SSL:
Preparación para el Certificado SSL
Ahora podemos proceder con la generación de nuestro certificado SSL.
Configura los registros DNS de tu dominio:
Agrega un registro A que apunte a la IP de tu servidor, si quieres www, agrega un CNAME para www que apunte a tu dominio principal
Instalación del Certificado SSL
Continuamos con la instalación del certificado SSL siguiendo la documentación oficial de Certbot. Procedemos a ejecutar los siguientes comandos:
[root@sunken]# ln -s /snap/bin/certbot /usr/bin/certbotCon esto ya podremos generar el certificado, pero habrá un problema con FIPS. En este caso no lo requerimos.
Para solucionarlo, vamos a crear un archivo que omita el uso del paquete FIPS y proceda con la generación del certificado:
[root@sunken]# vi /etc/ssl/openssl_no_fips.cnfAgregamos el siguiente contenido:
Ahora, tras guardar el archivo, vamos a verificar que la configuración de nuestro servidor Nginx esté correcta con los siguientes comandos:
[root@sunken]# nginx -t[root@sunken]# nginx -s reloadAhora generamos el certificado apuntando a la carpeta de nuestro servidor al cual queremos agregar el certificado, usando el archivo recién creado. Para ello ejecutamos el siguiente comando:
[root@sunken]# OPENSSL_CONF=/etc/ssl/openssl_no_fips.cnf certbot --nginx -d name.online -d www.name.onlineEl proceso de generación del certificado te pedirá:
Ejemplo de la salida del comando:
Felicidades 🎉, ya tienes tu servidor implementado con un certificado SSL. Aunque este es gratuito y solo valida la propiedad del dominio, si requieres otro tipo de certificado, procura informarte cuál necesita tu modelo de negocio. Puedes adquirir certificados comerciales en diferentes páginas como www.digicert.com, que usa Facebook.
Configuración Final Nginx
Después de haber generado el certificado, debes reemplazar la configuración temporal con la configuración que se verá a continuación.
Volvemos a ingresar en el archivo
name.online.conf:[root@sunken]# vi /etc/nginx/conf.d/name.online.confEliminamos todo el contenido y pegamos la siguiente configuración:
Despliegue de la Aplicación
Ahora creamos el directorio en donde vamos a subir nuestra aplicación o página web, este será el lugar donde vivirá todo nuestro contenido:
¡Bien! Aquí ya puedes subir el build de tu aplicación. En mi caso, uso Angular para construir mis aplicaciones y páginas web porque me encanta su arquitectura. Para subir los archivos desde tu máquina local a tu servidor, usa el siguiente comando:
Por última parte, ahora verificamos que Nginx no tenga errores:
[root@sunken]# nginx -tSi todo está bien y no hay errores, procedemos a reiniciar el servidor Nginx:
[root@sunken]# systemctl restart nginxPara asegurarnos de que todo está marchando como debe, comprobamos que el servidor esté corriendo de manera correcta con el siguiente comando:
[root@sunken]# systemctl status nginx¡Y listo! Ahora podemos ingresar a nuestro dominio en el navegador y comprobar que todo esté funcionando de manera correcta. No olvides verificar que el certificado SSL se haya implementado correctamente - deberías ver el candadito en la barra de direcciones de tu navegador. Si todo salió bien, ¡felicidades! Ya tienes tu aplicación corriendo de manera segura en tu servidor. :D
Protección contra Ataques DDoS
¡Excelente! Ahora vamos a dar un plus más de seguridad a nuestro servidor implementando protección contra ataques DDoS. Vamos a ser más restrictivos y limitar a solo 20 conexiones simultáneas (más seguro para aplicaciones pequeñas y medianas).
Primero configuramos nuestro firewall:
¿Qué hace cada parte de este comando? Te lo explico:
--connlimit-above 10: Limita a 20 conexiones por IP--connlimit-mask 32: Aplica el límite a cada IP individual--dport 80y--dport 443: Aplica para conexiones HTTP y HTTPS-j REJECT: Rechaza las conexiones que superen el límiteAhora vamos con la configuración del kernel. Abre el archivo:
[root@sunken]# vi /etc/sysctl.confAgrega estas configuraciones y te explico cada sección:
Aplicamos los cambios al kernel:
[root@sunken]# sysctl -pPor último, configuramos los límites de recursos del sistema:
[root@sunken]# vi /etc/security/limits.confAgregamos al final (después de "# End of file"):
¡Y ahora sí! Necesitamos reiniciar el servidor para que todos los cambios surtan efecto:
[root@sunken]# reboot🚀 ¡Servidor Desplegado y Blindado con Éxito!
¡Y así llegamos al final coders! Espero que esta guía les haya ayudado a configurar su servidor web Linux de manera segura y profesional. Como pudieron ver, hemos implementado las mejores prácticas y recomendaciones para que puedan desplegar sus aplicaciones o páginas web de la mejor manera posible. Si les gustó la guía, ¡apóyenme con una estrella y reaccionando a la discusión!
Recuerden que este es un proyecto vivo y seguiré brindando soporte y actualizaciones a medida que lo requieran. ¿Encontraste algún error? ¿Tienes sugerencias? ¡No dudes en abrir un issue! Entre todos podemos hacer que esta guía sea cada vez mejor.
Si deseas apoyarme para seguir brindando soporte a esta guía y crear más contenido como este, ¡te agradecería un montón por tu hamburguesa! 🍔
¡Feliz coding y que sus servidores sean tan seguros como Fort Knox! 💪
📑 Quick Links
All reactions