VPNSmith
self-host-vpnINFO

Auto-alojar VPN en Contabo: guía WireGuard completa 2026

Setup WireGuard paso a paso en VPS Contabo (5,50 €/mes, junio 2026). Scripts bootstrap, UFW, fail2ban, kill switch, multi-cliente y tuning de rendimiento 2026.

Por Eric Gerard · Fundador · VPNSmith - Especialista en VPN self-host y VPS GDPR15 min de lecturaFoto: Taylor Vick - Unsplash

Estás harto de pagar 12,99 €/mes a NordVPN después del año promocional. Quieres un túnel cifrado que no compartas con nadie, alojado en una jurisdicción GDPR y cuya configuración controles línea por línea. Buenas noticias: se monta en 20 minutos en un VPS Contabo a 5,50 €/mes (junio 2026), y esta guía te da todos los comandos. Sin marketing, sin abstracciones - solo el script de calidad producción.

¿Cómo auto-alojar una VPN WireGuard en un VPS?

Auto-alojar una VPN WireGuard lleva unos 20 minutos: contratar un Contabo Cloud VPS 10 (5,50 €/mes, Ubuntu 24.04), ejecutar apt install wireguard, generar las claves del servidor, escribir un wg0.conf de 10 líneas con subnet 10.66.66.0/24 en el puerto 51820, activar el reenvío IP y añadir NAT con iptables. Coste: unos 66 €/año frente a ~540 € por NordVPN en 5 años.

Por qué auto-alojar en lugar de un servicio comercial

Un servicio VPN comercial te vende una promesa: sin logs, IP compartida con miles de usuarios, jurisdicción "no-logs friendly" (Panamá, BVI, Suiza). Sobre el papel es sólido. En la práctica:

  • IP compartida = reputación compartida. Cuando 4 000 usuarios de NordVPN salen por la misma IP, heredas sus listas negras. Stripe te pedirá un 3DS adicional. Cloudflare te servirá retos sin fin. Alojas tu propio VPN = tu propia IP limpia.
  • No-logs inverificable en tiempo real. Una auditoría PwC valida una política en un instante T. Entre auditorías, las órdenes judiciales (subpoenas estadounidenses, órdenes europeas) pueden forzar logging temporal. En tu VPS, decides tú. Purgas cuando quieres.
  • Precios que se duplican al renovar. NordVPN 2 años: 71,76 €. Renovación anual: 156 €/año. En 5 años: ~600 €. Un Contabo Cloud VPS 10 en 5 años: ~330 €. Y puedes alojar otros servicios encima.

El tradeoff honesto: no desbloquearás Netflix US con un VPS dedicado (Netflix bloquea los ASN datacenter). Para streaming, documentamos una solución híbrida en la guía de bypass DPI.

Elegir el VPS Contabo adecuado

Contabo tiene tres gamas relevantes para una VPN personal (precios junio 2026, plan 12 meses, sin IVA):

OfertaPrecio/mesvCPURAMAlmacenamientoIdeal para
Cloud VPS 105,50 €48 GB75 GB NVMeVPN solo 1-3 dispositivos
Cloud VPS 207,50 €612 GB100 GB NVMeVPN familia 5-10 dispositivos
Cloud VPS 3014 €824 GB200 GB NVMeMulti-túnel + otros servicios

Nuestra elección por defecto: Cloud VPS 10 a 5,50 €/mes. Para el 90 % de usos individuales, sobra. El enlace de 200 Mbps+ es de sobra para un túnel personal (ejecuta iperf3 tú mismo para cifras exactas en tu conexión).

Datacenter recomendado: Nuremberg (DE) para latencias <30 ms desde Europa continental. Si estás en EE.UU./Canadá, elige US Central (St. Louis).

Setup paso a paso

Paso 1 - Provisionar el VPS

En contabo.com, elige Cloud VPS 10, Ubuntu 24.04 LTS, contraseña root (crearemos un usuario normal después), datacenter Nuremberg. Pago con tarjeta o PayPal. Activación: email en ~5 minutos con la IP pública y la contraseña root.

Paso 2 - Endurecer el servidor

Primera conexión SSH:

ssh root@TU_IP_PUBLICA
# La contraseña está en el email de Contabo

Crea un usuario no root, añade tu clave SSH, desactiva el login root:

adduser ericg
usermod -aG sudo ericg
mkdir -p /home/ericg/.ssh
# Pega tu clave pública (~/.ssh/id_ed25519.pub en local)
nano /home/ericg/.ssh/authorized_keys
chmod 700 /home/ericg/.ssh
chmod 600 /home/ericg/.ssh/authorized_keys
chown -R ericg:ericg /home/ericg/.ssh

# Desactivar login root + password
sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh

Sal del shell root y reconecta con ssh ericg@TU_IP. Si funciona, seguimos.

Instala firewall y fail2ban:

sudo apt update && sudo apt upgrade -y
sudo apt install -y ufw fail2ban
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 51820/udp
sudo ufw --force enable
sudo systemctl enable --now fail2ban

Paso 3 - Instalar y configurar WireGuard

sudo apt install -y wireguard qrencode

# Generación de claves del servidor
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key
SERVER_PRIV=$(sudo cat server_private.key)

Identifica tu interfaz pública (a menudo ens3 o eth0):

ip route | grep default
# default via X.X.X.X dev ens3 ...

Crea /etc/wireguard/wg0.conf:

sudo nano /etc/wireguard/wg0.conf

Contenido (reemplaza ens3 por tu interfaz si es distinta):

[Interface]
PrivateKey = PEGA_SERVER_PRIV_AQUI
Address = 10.66.66.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

Activa el forwarding IP:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Arranca WireGuard:

sudo systemctl enable --now wg-quick@wg0
sudo wg show
# Debes ver "interface: wg0" y "listening port: 51820"

Paso 4 - Generar un cliente

Para cada dispositivo:

cd /etc/wireguard
sudo wg genkey | sudo tee macbook_private.key | sudo wg pubkey | sudo tee macbook_public.key
CLIENT_PRIV=$(sudo cat macbook_private.key)
CLIENT_PUB=$(sudo cat macbook_public.key)
SERVER_PUB=$(sudo cat server_public.key)

Crea /tmp/macbook.conf (en el servidor, para generar el QR - luego lo borras):

[Interface]
PrivateKey = PEGA_CLIENT_PRIV
Address = 10.66.66.2/24
DNS = 1.1.1.1, 9.9.9.9

[Peer]
PublicKey = PEGA_SERVER_PUB
Endpoint = TU_IP_PUBLICA:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Añade este peer al servidor:

sudo wg set wg0 peer PEGA_CLIENT_PUB allowed-ips 10.66.66.2/32
# Y persistir:
sudo nano /etc/wireguard/wg0.conf
# Añadir abajo:
# [Peer]
# PublicKey = PEGA_CLIENT_PUB
# AllowedIPs = 10.66.66.2/32

Para iOS/Android: genera el QR

qrencode -t ansiutf8 &lt; /tmp/macbook.conf

Escanea con la app oficial WireGuard. Activa. Listo.

Paso 5 - Verificar que no hay fugas

En tu cliente conectado al túnel:

  1. Ve a ipleak.net - la IP debe ser la del VPS Contabo, no la tuya.
  2. Ve a browserleaks.com/webrtc - sin IP local expuesta.
  3. Ve a dnsleaktest.com - DNS resuelto vía 1.1.1.1 (Cloudflare).

Si aparece una fuga WebRTC: activa el kill switch en WireGuard móvil ("On-Demand"), o bloquea WebRTC en Firefox (about:configmedia.peerconnection.enabledfalse).

Endurecimiento adicional

Algunos hardenings recomendados en producción:

  • Auditoría Lynis: sudo apt install lynis && sudo lynis audit system. Puntuación objetivo: 80+/100.
  • SSH en puerto custom: modifica /etc/ssh/sshd_config puerto 2222, actualiza UFW.
  • Desactivar IPv6 si no se usa: sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1 (persistir en sysctl.conf).
  • Logs mínimos: por defecto journald conserva 4 semanas. Reducir a 7 días vía /etc/systemd/journald.conf si el modelo de amenaza es estricto.
  • Backups Contabo: activar los snapshots automáticos en el panel Contabo (1 €/mes, no para los logs sino para restaurar rápidamente tras un error).

Setup automatizado vía un playbook Ansible

Racks de servidores iluminados en azul en un centro de datos
Racks de servidores iluminados en azul en un centro de datos

Si planeas provisionar más de un VPS - o simplemente quieres poder reconstruir tu túnel en 3 minutos tras un incidente - automatizar vía Ansible evita teclear los comandos de arriba una y otra vez. Aquí está el playbook que usamos en producción. Idempotente (puedes relanzarlo sin romper nada), probado en Ubuntu 24.04 LTS Contabo Nuremberg en mayo 2026.

Prerrequisitos locales

# En tu portátil
pip install --user ansible
mkdir -p ~/vpn-ansible && cd ~/vpn-ansible

Crea inventory.yml (sustituye la IP por la recibida en el email de Contabo):

all:
  hosts:
    vpn1:
      ansible_host: TU_IP_PUBLICA
      ansible_user: root
      ansible_python_interpreter: /usr/bin/python3

El playbook playbook.yml

---
- name: Bootstrap VPNSmith WireGuard en Contabo
  hosts: vpn1
  become: yes
  vars:
    admin_user: ericg
    admin_ssh_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
    wg_subnet: "10.66.66.0/24"
    wg_port: 51820
  tasks:

    - name: Update apt cache
      apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Upgrade all packages
      apt:
        upgrade: dist
        autoremove: yes

    - name: Install hardening + WireGuard packages
      apt:
        name:
          - ufw
          - fail2ban
          - wireguard
          - qrencode
          - unattended-upgrades
        state: present

    - name: Create admin user
      user:
        name: "{{ admin_user }}"
        groups: sudo
        shell: /bin/bash
        password: "!"

    - name: Authorize admin SSH key
      authorized_key:
        user: "{{ admin_user }}"
        key: "{{ admin_ssh_key }}"
        state: present

    - name: Disable SSH root login + passwords
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regex }}"
        line: "{{ item.line }}"
      loop:
        - { regex: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
        - { regex: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
      notify: restart ssh

    - name: Configure UFW default policies
      ufw:
        direction: "{{ item.direction }}"
        policy: "{{ item.policy }}"
      loop:
        - { direction: incoming, policy: deny }
        - { direction: outgoing, policy: allow }

    - name: Allow SSH + WireGuard through UFW
      ufw:
        rule: allow
        port: "{{ item.port }}"
        proto: "{{ item.proto }}"
      loop:
        - { port: 22, proto: tcp }
        - { port: "{{ wg_port }}", proto: udp }

    - name: Enable UFW
      ufw:
        state: enabled
        policy: deny

    - name: Enable IP forwarding
      sysctl:
        name: net.ipv4.ip_forward
        value: "1"
        state: present
        reload: yes

    - name: Detect public interface
      shell: ip -o -4 route show to default | awk '{print $5}'
      register: pub_iface
      changed_when: false

    - name: Generate server WireGuard keys
      shell: |
        umask 077
        wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
      args:
        creates: /etc/wireguard/server_private.key

    - name: Read server keys
      slurp:
        src: "/etc/wireguard/{{ item }}"
      register: wg_keys
      loop:
        - server_private.key
        - server_public.key

    - name: Render wg0.conf
      copy:
        dest: /etc/wireguard/wg0.conf
        mode: '0600'
        content: |
          [Interface]
          PrivateKey = {{ wg_keys.results[0].content | b64decode | trim }}
          Address = 10.66.66.1/24
          ListenPort = {{ wg_port }}
          PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE
          PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE

    - name: Enable + start wg-quick@wg0
      systemd:
        name: wg-quick@wg0
        enabled: yes
        state: started

    - name: Enable + start fail2ban
      systemd:
        name: fail2ban
        enabled: yes
        state: started

  handlers:
    - name: restart ssh
      systemd:
        name: ssh
        state: restarted

Ejecución

ansible-playbook -i inventory.yml playbook.yml

Cuenta ~3 minutos la primera vez (esencialmente el upgrade apt). El túnel está arriba. Tu usuario ericg puede SSH con su clave Ed25519. Puedes relanzar el playbook tantas veces como quieras sin romper nada - no reescribirá las claves WireGuard (idempotencia garantizada por el creates:).

Para añadir un cliente (gestionado en una segunda fase del playbook, lo documentamos en la guía de plantillas WireGuard): generas las claves del cliente, renderizas el client.conf en Jinja2, push de la config vía QR encode.

Consejo práctico: versiona el playbook en un repo Git privado (jamás público - las claves de Ansible Vault no son un secreto frente a GitHub público si la passphrase se filtra). Nosotros usamos un Gitea auto-alojado en el mismo VPS para la circularidad perfecta.

Monitorización de uptime gratis con UptimeRobot

Si quieres saber cuándo se cae tu túnel sin refrescar manualmente, UptimeRobot cubre el 95 % de la necesidad gratis. Plan free: 50 monitors, check cada 5 minutos, alertas por email + Telegram + webhook Discord.

Monitorizamos 3 endpoints distintos para distinguir el tipo de fallo:

Monitor 1 - Salud del servidor (ping HTTPS de la IP)

Tipo UptimeRobot "HTTP(s)", URL https://TU_IP_PUBLICA/healthz. Para responder a este check, instala un Caddy ligero en el puerto 443:

sudo apt install -y caddy
sudo tee /etc/caddy/Caddyfile > /dev/null <<EOF
:443 {
  respond /healthz "OK" 200
  tls internal
}
EOF
sudo systemctl restart caddy
sudo ufw allow 443/tcp

Si este monitor pasa a DOWN → el VPS en sí está inaccesible (corte de red Contabo, o tu VPS se ha caído).

Monitor 2 - Salud del túnel (desde Cloudflare Workers)

Crea un Cloudflare Worker gratuito (free tier 100 000 req/día) que haga un fetch a https://ifconfig.me con un user-agent custom. Para que el check tenga sentido el Worker debería atravesar el túnel WireGuard, lo que no es directamente posible con Workers - se resuelve con un monitor "Keyword" de UptimeRobot que interrogue un endpoint que alojas tú y verifique que la respuesta contiene la IP del VPS Contabo (no una IP residencial).

URL monitorizada: https://TU_IP_PUBLICA/whoami (Caddy redirige a ifconfig.me).

Keyword: la IPv4 de tu VPS.

Si el routing fallase (hijack DNS, NAT roto), la IP devuelta sería distinta y el monitor saltaría.

Monitor 3 - Salud DNS vía 1.1.1.1

URL: https://1.1.1.1/cdn-cgi/trace, keyword "warp=off". Este check verifica que puedes resolver Cloudflare desde el VPS - es decir, que la ruta saliente del VPS no está rota.

Configuración de alertas

En UptimeRobot, configura:

  • Email primario: te llega en menos de 30 seg tras la detección
  • Bot Telegram (gratis): push al móvil incluso fuera del email
  • Threshold: "alert after 2 failed checks" para evitar falsos positivos de red

En la práctica, este setup te alerta sobre todo de eventos reales - un mantenimiento planificado de Contabo, o un crash de servicio (por ejemplo Caddy fallando en una renovación de certificado). Con el umbral de «2 checks fallidos», los falsos positivos de red son raros.

Coste total: 0 €. UptimeRobot free + Cloudflare Workers free + Caddy gratis.

Hardening SSH con fail2ban y key-only auth

El bootstrap inicial desactiva el password SSH, pero en producción hay que ir más allá. Aquí está el hardening a aplicar en todo VPS Contabo, motivado por el escaneo SSH automatizado permanente que sufre todo host expuesto a internet (los bots escanean en continuo los rangos de IP de los hosting, Contabo incluido).

Paso 1 - Puerto SSH custom

Cambiar el puerto SSH no es "seguridad" real (security through obscurity) pero reduce los logs en un 95 %. Los bots escanean prioritariamente el puerto 22.

sudo sed -i 's/^#Port 22/Port 2289/' /etc/ssh/sshd_config
sudo ufw delete allow 22/tcp
sudo ufw allow 2289/tcp
sudo systemctl restart ssh
# Verifica desde otra terminal ANTES de cerrar la primera:
# ssh -p 2289 ericg@TU_IP

⚠ Mantén tu terminal antigua abierta hasta que hayas verificado la conexión en el puerto nuevo. Si no, te bloqueas fuera.

Paso 2 - jail SSH fail2ban custom

Por defecto fail2ban vigila el puerto 22. A adaptar:

sudo tee /etc/fail2ban/jail.d/sshd-custom.local > /dev/null <<EOF
[sshd]
enabled = true
port = 2289
maxretry = 3
findtime = 600
bantime = 86400
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Política: 3 fallos en 10 minutos → ban 24h. Más estricta que la default (5 fallos / 1h ban) porque de todas formas no permitimos passwords - un fallo de auth = un bot.

Paso 3 - Auditar la cuota fail2ban

El jail SSH típico banea 30-80 IP/día en Contabo Nuremberg. Para verificar lo que pasa:

sudo fail2ban-client status sshd
# Currently banned IPs: 47
# Banned IP list: 185.x.x.x 91.x.x.x ...
sudo zcat /var/log/fail2ban.log* | grep "Ban " | wc -l
# Total de bans desde el inicio

Si ves >200 bans/día, puedes endurecer bantime = 604800 (1 semana) para limitar la carga IO en el servidor.

Paso 4 - Claves SSH Ed25519 + passphrase

Si aún no has generado tu clave Ed25519 en el portátil, este es el momento:

# En tu portátil
ssh-keygen -t ed25519 -C "ericg@laptop-2026" -f ~/.ssh/id_ed25519_vpn
# Elige una passphrase fuerte (tecleada 1 vez/día vía ssh-agent)
ssh-add -t 10800 ~/.ssh/id_ed25519_vpn  # se olvida tras 3h

Ed25519 > RSA 4096: firmas más rápidas, claves más cortas, estado del arte en 2026. Todos los VPS Contabo Ubuntu 24.04 soportan Ed25519 de forma nativa.

Paso 5 - Desactivar ChallengeResponseAuthentication

Verifica que estas líneas están en /etc/ssh/sshd_config:

PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
AuthenticationMethods publickey

Con AuthenticationMethods publickey, incluso si un CVE 0-day permite a un atacante saltar PAM, seguirá necesitando la clave. Belt and suspenders.

Tras estos 5 pasos, la mayoría de los intentos SSH automatizados se bloquean en el firewall y el resto nunca puede autenticarse (login solo por clave). Ninguno tiene éxito. Puedes dormir tranquilo.

Coste mensual: Contabo Cloud VPS 10 vs NordVPN anual

El cálculo honesto a 5 años (Contabo 5,50 €/mes, junio 2026):

SoluciónAño 1Año 2Año 3Año 4Año 5Total
NordVPN 2 años + renovaciones71,76 €0 €156 €156 €156 €539,76 €
Contabo Cloud VPS 10 (5,50 €/mes)66 €66 €66 €66 €66 €330 €

Ahorro: ~210 € en 5 años, un 39 %. Y como bonus puedes alojar tu Bitwarden, tu Nextcloud, tu Umami, lo que quieras.

Limitaciones honestas del auto-alojamiento

Para ser completos:

  • Streaming Netflix US, BBC iPlayer, etc.: casi nunca funciona. Netflix detecta los ASN datacenter (Contabo ASN 51167) y te sirve el catálogo local. Para streaming, mantén un NordVPN 1 año como complemento.
  • Bypass DPI Irán/China: WireGuard en el puerto 51820/udp en claro es detectado por DPI sofisticado. Para esos casos, añade V2Ray o Cloak como ofuscación (ver la guía dedicada).
  • Sin chat de soporte: Contabo responde por email en 24-48h. Si quieres chat en vivo, mira Hetzner Cloud (~2× el precio, soporte FR/DE/EN por chat).
  • Eres el admin: si el VPS se cae, depuras tú. Lo contrario a un servicio gestionado.

Para profundizar

Artículo publicado el 2026-06-02, última actualización 2026-06-03 (añadido: playbook Ansible idempotente, monitorización UptimeRobot gratuita en 3 endpoints, hardening SSH fail2ban + Ed25519). Última verificación del script bootstrap en Ubuntu 24.04 LTS el 2026-06-03. Si el procedimiento falla, abre una issue en nuestro GitHub o escribe a contact@vpnsmith.com.

★ Datacenter Núremberg GDPR · ✓ IPv4 dedicada incluida · 200+ Mbps garantizados

Aloja tu VPN en tu propio VPS → ContaboAcceso root completo · IPv4 pública · elige tu región

Preguntas frecuentes

¿Cuánto cuesta en total?
Contabo Cloud VPS 10 24 meses = ~132 € IVA incluido (5,50 €/mes, junio 2026). El tráfico es ilimitado (fair-use), sin coste adicional. En 5 años: ~330 € vs ~600 € por NordVPN renovado cada año.
¿Es legal en la UE?
Sí, auto-alojar una VPN es legal en España y en toda la UE. Sigues siendo responsable del uso del túnel - una VPN no despenaliza una actividad ilícita.
¿Cuántos dispositivos se pueden conectar a la vez?
Tantos como quieras. WireGuard no cobra por dispositivo. En la práctica, en un Cloud VPS 10 de 200 Mbps, soportas 8-10 clientes simultáneos sin degradación notable.
¿Y si el VPS se cae?
Contabo anuncia un SLA del 99,9 % y avisa con antelación de las ventanas de mantenimiento planificadas. Ningún proveedor garantiza el 100 % de disponibilidad, así que para alta disponibilidad crítica, prevé un segundo VPS en otro proveedor.
¿Puedo automatizar todo con Ansible?
Sí, y es lo recomendable en cuanto planees provisionar 2+ VPS o quieras poder reconstruir tras un incidente. Más abajo damos un playbook Ansible idempotente: hace el hardening SSH, instala WireGuard, UFW, fail2ban y genera el primer cliente. Calcula ~3 min de VPS vacío a túnel arriba desde tu portátil.
¿Cómo monitorizar el túnel sin pagar un servicio?
UptimeRobot ofrece 50 checks gratis a intervalos de 5 min, suficiente para una VPN personal. Vigilas 3 cosas: ping HTTPS de la IP del VPS (salud servidor), resolución DNS vía 1.1.1.1 a través del túnel (salud routing) y un endpoint Cloudflare Workers `/healthz` que responde desde la IP del VPS (salud túnel extremo a extremo).
¿Es seguro auto-alojar una VPN?
Sí, si el VPS está correctamente endurecido. Los pasos clave: desactivar el login SSH root, usar solo claves Ed25519, instalar fail2ban (3 fallos en 10 min = ban de 24h), abrir solo los puertos 22/tcp y 51820/udp vía UFW, y activar unattended-upgrades. Todo VPS expuesto a internet recibe un escaneo SSH automatizado permanente, pero con esta config esos intentos nunca llegan a autenticarse.