<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Elber</title>
    <description>The latest articles on DEV Community by Elber (@elbernv).</description>
    <link>https://dev.to/elbernv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F927625%2Ffadf0fc3-3450-46bb-8297-a83530ee73a4.jpeg</url>
      <title>DEV Community: Elber</title>
      <link>https://dev.to/elbernv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elbernv"/>
    <language>en</language>
    <item>
      <title>Configuración de VPS: Seguridad Base</title>
      <dc:creator>Elber</dc:creator>
      <pubDate>Mon, 02 Feb 2026 00:29:47 +0000</pubDate>
      <link>https://dev.to/elbernv/configuracion-de-vps-seguridad-base-9h4</link>
      <guid>https://dev.to/elbernv/configuracion-de-vps-seguridad-base-9h4</guid>
      <description>&lt;h3&gt;
  
  
  Contexto y Objetivos
&lt;/h3&gt;

&lt;p&gt;El propósito de este documento es establecer una línea base de seguridad (hardening) para cualquier instancia VPS recién aprovisionada. Independientemente del proveedor (DigitalOcean, AWS, etc.), la configuración por defecto ("defaults") suele priorizar la compatibilidad sobre la seguridad, lo cual es inaceptable para un entorno de producción.&lt;/p&gt;

&lt;p&gt;Este tutorial abarca múltiples conceptos de forma ejecutiva para lograr un despliegue rápido y seguro. Más adelante publicaré artículos técnicos detallados desglosando la arquitectura y configuración profunda de cada herramienta (SSH, Fail2Ban, UFW, etc.).&lt;/p&gt;

&lt;p&gt;Vamos a cerrar vectores de ataque comunes, establecer políticas de acceso estricto y configurar herramientas de monitoreo activo antes de siquiera pensar en desplegar aplicaciones.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Actualización y Sincronización
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1. Actualización de Paquetes
&lt;/h3&gt;

&lt;p&gt;No tiene sentido configurar seguridad sobre dependencias obsoletas. Actualizamos los repositorios y parches del sistema operativo inmediatamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2. Zona Horaria y NTP
&lt;/h3&gt;

&lt;p&gt;Para un &lt;em&gt;debugging&lt;/em&gt; efectivo, los logs deben estar sincronizados con tu tiempo local. Correlacionar incidentes con logs en UTC desfasados es ineficiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Configurar Timezone (Ej: Venezuela)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;timedatectl set-timezone America/Caracas

&lt;span class="c"&gt;# Verificar consistencia&lt;/span&gt;
timedatectl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aseguramos que el demonio de sincronización de tiempo esté activo para evitar &lt;em&gt;drifts&lt;/em&gt; que afecten la validación de certificados SSL o TOTP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;timedatectl set-ntp on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Gestión de Identidad y Accesos (IAM)
&lt;/h2&gt;

&lt;p&gt;El uso directo de &lt;code&gt;root&lt;/code&gt; es una mala práctica crítica. Vamos a crear un usuario operativo y bloquear el acceso administrativo directo.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1. Usuario Sudoer
&lt;/h3&gt;

&lt;p&gt;Creamos un usuario con capacidad de escalamiento de privilegios (&lt;code&gt;sudo&lt;/code&gt;) para tareas administrativas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reemplaza 'deployer' por tu usuario estándar&lt;/span&gt;
adduser deployer
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;deployer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Validación:&lt;/strong&gt; Antes de continuar, loguéate como el nuevo usuario (&lt;code&gt;su - deployer&lt;/code&gt;) y verifica que puedes ejecutar comandos con privilegios (&lt;code&gt;sudo whoami&lt;/code&gt;). Si responde &lt;code&gt;root&lt;/code&gt;, procede.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Configuración del Servicio SSH
&lt;/h2&gt;

&lt;p&gt;El puerto 22 es el objetivo principal de los &lt;em&gt;scanners&lt;/em&gt; automatizados. Vamos a cambiar la configuración por defecto para mitigar ataques de fuerza bruta y deshabilitar autenticación por contraseña.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1. Llaves SSH (Algoritmo Ed25519)
&lt;/h3&gt;

&lt;p&gt;Olvida RSA. Usaremos &lt;strong&gt;Ed25519&lt;/strong&gt; por su performance y menor tamaño de llave. Si ya dispones de un par de llaves generado bajo este algoritmo, este paso es opcional; puedes reutilizar tu llave pública existente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;En tu máquina local:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"admin@infrastructure"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.2. Instalación de la Llave (En el VPS)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ADVERTENCIA CRÍTICA:&lt;/strong&gt; No realices estos pasos como usuario &lt;code&gt;root&lt;/code&gt;. Debes estar logueado con el usuario creado en el paso 2.1 (&lt;code&gt;su - deployer&lt;/code&gt;). Si instalas la llave en el directorio de root, no podrás acceder con tu usuario operativo tras deshabilitar las contraseñas, lo que resultará en un bloqueo total del acceso.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.ssh
&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ~/.ssh
nano ~/.ssh/authorized_keys &lt;span class="c"&gt;# Pega tu llave pública aquí&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.3. Configuración del Daemon (sshd_config)
&lt;/h3&gt;

&lt;p&gt;Una vez instalada la llave en el usuario operativo, procedemos a restringir el daemon. Esto se hace con privilegios de superusuario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro del archivo, localiza y modifica (o añade al final) las siguientes directivas. Asegúrate de que no tengan el símbolo &lt;code&gt;#&lt;/code&gt; al inicio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;Port&lt;/span&gt; &lt;span class="m"&gt;2965&lt;/span&gt;                   &lt;span class="c1"&gt;# Security by obscurity (filtra el ruido de bots básicos)&lt;/span&gt;
&lt;span class="k"&gt;PermitRootLogin&lt;/span&gt; &lt;span class="no"&gt;no&lt;/span&gt;          &lt;span class="c1"&gt;# Bloqueo total a root&lt;/span&gt;
&lt;span class="k"&gt;PasswordAuthentication&lt;/span&gt; &lt;span class="no"&gt;no&lt;/span&gt;   &lt;span class="c1"&gt;# Solo llaves públicas&lt;/span&gt;
&lt;span class="k"&gt;PubkeyAuthentication&lt;/span&gt; &lt;span class="no"&gt;yes&lt;/span&gt;
&lt;span class="k"&gt;X11Forwarding&lt;/span&gt; &lt;span class="no"&gt;no&lt;/span&gt;            &lt;span class="c1"&gt;# Reducir superficie de ataque&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reiniciamos el servicio para aplicar cambios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; A partir de este punto, el acceso es &lt;code&gt;ssh -p 2965 deployer@&amp;lt;IP&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Seguridad Activa y Firewall
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1. Fail2Ban (Intrusion Prevention)
&lt;/h3&gt;

&lt;p&gt;Configuramos Fail2Ban para monitorear logs de autenticación y banear IPs que presenten comportamiento anómalo (fuerza bruta).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;fail2ban &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creamos una configuración local para proteger nuestro puerto SSH personalizado en &lt;code&gt;/etc/fail2ban/jail.d/sshd.local&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[sshd]&lt;/span&gt;
&lt;span class="py"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2965&lt;/span&gt;
&lt;span class="py"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sshd&lt;/span&gt;
&lt;span class="py"&gt;logpath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/var/log/auth.log&lt;/span&gt;
&lt;span class="py"&gt;maxretry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;findtime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;600&lt;/span&gt;
&lt;span class="py"&gt;bantime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3600  # 1 hora de ban inicial&lt;/span&gt;
&lt;span class="py"&gt;banaction&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ufw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aplicamos y verificamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart fail2ban
&lt;span class="nb"&gt;sudo &lt;/span&gt;fail2ban-client status sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.2. Firewall (UFW)
&lt;/h3&gt;

&lt;p&gt;Implementamos una política de "Deny All" por defecto. Solo abrimos lo estrictamente necesario.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Resetear reglas previas&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nt"&gt;--force&lt;/span&gt; reset

&lt;span class="c"&gt;# 2. Políticas por defecto&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default deny incoming
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default allow outgoing

&lt;span class="c"&gt;# 3. Allow SSH (CRÍTICO: Usar el puerto custom configurado)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 2965/tcp

&lt;span class="c"&gt;# 4. Habilitar&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Validación final:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw status numbered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Próximos Pasos
&lt;/h3&gt;

&lt;p&gt;Con esto tenemos una infraestructura base segura. El servidor está blindado contra ataques básicos de diccionario y escaneos de puertos estándar.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>security</category>
      <category>vps</category>
    </item>
  </channel>
</rss>
