Páginas

Buscar este blog

viernes, 16 de octubre de 2026

Restaurar red tras resume ACPI en FreeBSD

Objetivo

Ejecutar automáticamente un script al despertar el equipo de suspensión (S3) para restaurar:

  • Ethernet con IP fija
  • Reglas de pf
  • Ratón USB
  • Cliente NFS

Piezas necesarias

Pieza Ruta
Script de restauración /usr/local/sbin/resume-network.sh
Regla de devd /etc/devd/resume-network.conf
Log del script /var/log/resume-network.log
Syslog (logger) /var/log/messages

1️⃣ Crear el script

doas vim /usr/local/sbin/resume-network.sh

Puntos clave:

  • Shebang: #!/bin/sh
  • PATH completo al inicio (devd lo ejecuta con PATH mínimo):
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
export PATH

Redirigir toda la salida a un log para depurar:

exec >> /var/log/resume-network.log 2>&1
  • Función log() que escribe a archivo y a syslog
log() {
    echo "[$(date '+%F %T')] $*"
    logger -t resume-network "$*"
}
  • Usar rutas absolutas en comandos críticos (/sbin/pfctl, /usr/local/bin/wg-quick, etc.).
  • Esperar a que el enlace esté active antes de reasignar IP.
  • Al reasignar IP fija: borrar primero la IP previa y borrar la ruta por defecto antes de volver a añadirla.

Dar permisos:

doas chmod +x /usr/local/sbin/resume-network.sh

2️⃣ Script completo

#!/bin/sh
# =========================================================
# /usr/local/sbin/resume-network.sh
# Restaura Ethernet (em0, IP fija), ratón USB y NFS
# tras un resume ACPI.
# (WireGuard y qBittorrent excluidos)
# =========================================================

# PATH completo: devd ejecuta los scripts con un PATH mínimo
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
export PATH

LOG="/var/log/resume-network.log"
exec >> "$LOG" 2>&1

# Función para loguear en archivo y en syslog
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
    logger -t resume-network "$*"
}

log "=== $(date) - Resume detectado ==="

# ---------------------------------------------------------
# 1. Ethernet: reactivar em0 y aplicar IP fija
# ---------------------------------------------------------
sleep 3

ifconfig em0 down
sleep 1
ifconfig em0 up

# Esperar a que el enlace esté activo (hasta 15s)
i=0
status=""
while [ $i -lt 15 ]; do
    status=$(ifconfig em0 | awk '/status:/ {print $2}')
    [ "$status" = "active" ] && break
    sleep 1
    i=$((i + 1))
done

log "em0 status=$status tras ${i}s"

if [ "$status" != "active" ]; then
    log "ERROR - em0 sin enlace tras ${i}s"
    exit 1
fi

# Eliminar IP previa (si existe) y reaplicar IP fija y ruta
ifconfig em0 inet 192.168.88.50 delete 2>/dev/null
ifconfig em0 inet 192.168.88.50 netmask 255.255.255.0
route delete default 2>/dev/null
route add default 192.168.88.1

log "Ethernet OK (IP fija y ruta activas)"

# ---------------------------------------------------------
# 2. Recargar pf para limpiar estados obsoletos
# ---------------------------------------------------------
/sbin/pfctl -f /etc/pf.conf 2>/dev/null
log "pf recargado"

# ---------------------------------------------------------
# 3. Verificar conectividad con reintentos
# ---------------------------------------------------------
connected=0
for attempt in 1 2 3; do
    if ping -c 1 -t 3 192.168.88.1 >/dev/null 2>&1; then
        connected=1
        break
    fi
    sleep 2
done

if [ "$connected" != "1" ]; then
    log "ERROR - sin conectividad a la puerta de enlace"
    exit 1
fi
log "Conectividad verificada tras ${attempt} intento(s)"

# ---------------------------------------------------------
# 4. Reactivar ratón USB
# ---------------------------------------------------------
if kldstat -q -m ums 2>/dev/null; then
    kldunload ums 2>/dev/null
    sleep 1
    kldload ums
    log "módulo ums recargado"
elif kldstat -q -m uhid 2>/dev/null; then
    kldunload uhid 2>/dev/null
    sleep 1
    kldload uhid
    log "módulo uhid recargado"
else
    log "ni ums ni uhid cargados, ratón sin cambios"
fi

# Reiniciar moused si está corriendo
if pgrep -q moused; then
    service moused restart 2>/dev/null || {
        pkill -f moused 2>/dev/null
        sleep 1
        service moused start 2>/dev/null
    }
    log "moused reiniciado"
fi

# ---------------------------------------------------------
# 5. Reiniciar el cliente NFS
# ---------------------------------------------------------
service nfsclient restart
log "nfsclient reiniciado"

# Opcional: remontar sistemas NFS si se quedan colgados
# mount -a -t nfs
# log "sistemas NFS remontados"

log "=== $(date) - Resume completado ==="
exit 0

3️⃣ Crear la regla de devd

# cat /etc/devd/resume-network.conf 
notify 100 {
    match "system"      "ACPI";
    match "subsystem"   "Resume";
    action "/usr/local/sbin/resume-network.sh";
};

Aplicar cambios

doas service devd restart

Comprobar que devd ve el evento

Verifica que el subsystem sea exactamente el correcto. Algunos equipos emiten Resume y otros resume. Para ver qué llega:

doas devd -d

Suspende y despierta el equipo. Si no aparece el evento ACPI/Resume, ajusta la regla con el subsystem que realmente emita tu hardware (puedes verlo también en /var/log/messages).

4️⃣ Probar sin suspender

Ejecuta el script manualmente como root:

doas sh -x /usr/local/sbin/resume-network.sh

Y revisa el log:

tail -f /var/log/resume-network.log

5️⃣ Depurar tras un resume real

Log propio del script:

tail -n 50 /var/log/resume-network.log
add net default: gateway 192.168.88.1
[2026-10-16 15:02:49] Ethernet OK (IP fija y ruta activas)
[2026-10-16 15:02:49] pf recargado
[2026-10-16 15:02:51] Conectividad verificada tras 1 intento(s)
[2026-10-16 15:02:51] ni ums ni uhid cargados, ratón sin cambios
Starting default moused.
[2026-10-16 15:02:51] moused reiniciado
NFS access cache time=60
[2026-10-16 15:02:51] nfsclient reiniciado
[2026-10-16 15:02:51] === Fri Oct 16 15:02:51 CEST 2026 - Resume completado ===
[2026-10-16 15:03:28] === Fri Oct 16 15:03:28 CEST 2026 - Resume detectado ===
[2026-10-16 15:03:36] em0 status=active tras 2s

add net default: gateway 192.168.88.1
[2026-10-16 15:03:37] Ethernet OK (IP fija y ruta activas)
[2026-10-16 15:03:37] pf recargado
[2026-10-16 15:03:42] Conectividad verificada tras 2 intento(s)
[2026-10-16 15:03:42] ni ums ni uhid cargados, ratón sin cambios
Starting default moused.
[2026-10-16 15:03:42] moused reiniciado
NFS access cache time=60
[2026-10-16 15:03:42] nfsclient reiniciado
[2026-10-16 15:03:42] === Fri Oct 16 15:03:42 CEST 2026 - Resume completado ===
[2026-10-16 18:34:14] === Fri Oct 16 18:34:14 CEST 2026 - Resume detectado ===
[2026-10-16 18:34:23] em0 status=active tras 2s

add net default: gateway 192.168.88.1
[2026-10-16 18:34:23] Ethernet OK (IP fija y ruta activas)
[2026-10-16 18:34:23] pf recargado
[2026-10-16 18:34:26] Conectividad verificada tras 1 intento(s)
[2026-10-16 18:34:26] ni ums ni uhid cargados, ratón sin cambios
Starting default moused.
[2026-10-16 18:34:26] moused reiniciado
NFS access cache time=60
[2026-10-16 18:34:26] nfsclient reiniciado
[2026-10-16 18:34:26] === Fri Oct 16 18:34:26 CEST 2026 - Resume completado ===
[2026-10-16 21:58:08] === Fri Oct 16 21:58:08 CEST 2026 - Resume detectado ===
[2026-10-16 21:58:16] em0 status=active tras 2s

add net default: gateway 192.168.88.1
[2026-10-16 21:58:17] Ethernet OK (IP fija y ruta activas)
[2026-10-16 21:58:17] pf recargado
[2026-10-16 21:58:22] Conectividad verificada tras 2 intento(s)
[2026-10-16 21:58:22] ni ums ni uhid cargados, ratón sin cambios
Starting default moused.
[2026-10-16 21:58:22] moused reiniciado
NFS access cache time=60
[2026-10-16 21:58:22] nfsclient reiniciado
[2026-10-16 21:58:22] === Fri Oct 16 21:58:22 CEST 2026 - Resume completado ===

Mensajes que ha escrito devd y el script vía logger:

grep resume /var/log/messages
Oct 16 21:58:08 solaris resume-network[18841]: === Fri Oct 16 21:58:08 CEST 2026 - Resume detectado ===
Oct 16 21:58:16 solaris resume-network[18862]: em0 status=active tras 2s
Oct 16 21:58:17 solaris resume-network[18871]: Ethernet OK (IP fija y ruta activas)
Oct 16 21:58:17 solaris resume-network[18877]: pf recargado
Oct 16 21:58:22 solaris resume-network[18891]: Conectividad verificada tras 2 intento(s)
Oct 16 21:58:22 solaris resume-network[18898]: ni ums ni uhid cargados, ratón sin cambios
Oct 16 21:58:22 solaris resume-network[18929]: moused reiniciado
Oct 16 21:58:22 solaris resume-network[18945]: nfsclient reiniciado
Oct 16 21:58:22 solaris resume-network[18951]: === Fri Oct 16 21:58:22 CEST 2026 - Resume completado ===

Errores frecuentes

Síntoma Causa Solución
Nada ocurre al despertar & al final del action Quitarlo
Nada ocurre al despertar subsystem distinto (resume vs Resume) Ajustar en el .conf
Script falla silenciosamente Comando no encontrado (logger, route, …) Añadir PATH completo
IP fija no se aplica La IP ya estaba asignada ifconfig em0 inet X delete antes
Ratón no vuelve Módulo incorrecto cargado Probar ums, uhid, usbhid
NFS colgado service nfsclient restart no remonta Añadir umount -f + mount -a

Comandos útiles de referencia

service devd restart            # recargar reglas
devd -d                         # ver eventos en directo
ifconfig em0                    # ver estado del enlace
netstat -rn                     # ver rutas
pfctl -s info                   # estado de pf
kldstat                         # módulos cargados
mount | grep nfs                # montajes NFS activos

Todo el flujo en un solo vistazo: script → regla devd → restart → log → depuración.

FreeBSD es genial!.

jueves, 15 de octubre de 2026

Cheatsheet RouterOS — Proyecto ax³

Qué es esta entrada

Resumen de comandos útiles de RouterOS y del cliente SSH, agrupados por tema y con comentarios. Todo lo que aparece aquí es lo que se usó realmente durante el Proyecto ax³: la migración del hAP ac² al hAP ax³ con monopuesto de O2, policy routing con ProtonVPN, DNS con Pi-Hole y Unbound, y backups.

Cómo usar esta entrada: usa el índice para saltar al bloque que necesites. Cada bloque de código tiene un botón Copiar en la esquina superior derecha. Los comandos están pensados para pegarse en la terminal de RouterOS (New Terminal en WinBox o SSH) o en el cliente (FreeBSD/Linux/Windows).

Índice

SSH y acceso remoto

# Ver la configuración SSH actual
/ip ssh print

# Permitir autenticación por contraseña
/ip ssh set password-authentication=yes

# Solo permitir contraseña a usuarios SIN clave (recomendado tras importar claves)
/ip ssh set password-authentication=yes-if-no-key

# Forzar algoritmos criptográficos modernos (AES-GCM, ChaCha20, Ed25519)
/ip ssh set strong-crypto=yes

# Ver las claves SSH importadas de los usuarios
/user ssh-keys print

# Ver detalle (incluye fingerprint)
/user ssh-keys print detail

# Importar una clave pública a un usuario
/user ssh-keys import public-key-file=mikrotik_axe.pub user=carlos

# Eliminar una clave por índice
/user ssh-keys remove 1

# Eliminar una clave por fingerprint (más seguro)
/user ssh-keys remove [find fingerprint="SHA256:..."]
Valores de password-authentication:
  • yes — Login por contraseña siempre permitido.
  • no — Nunca permitido, solo clave SSH.
  • yes-if-no-key — Solo si el usuario no tiene clave asociada. Recomendado tras importar las claves.

Usuarios

# Listar todos los usuarios
/user print

# Habilitar un usuario y asignarle contraseña
/user set admin disabled=no password="TuContraseñaSegura"

# Asignar grupo (full = control total)
/user set admin disabled=no group=full password="TuContraseñaSegura"

# Dejar un usuario sin contraseña (solo entrará con clave SSH)
/user set carlos password=""

# Deshabilitar un usuario temporalmente
/user set carlos disabled=yes

Backups

# Backup binario (restaurable, incluye todo)
/system backup save name=ax3-2026-10-15-produccion

# Backup con contraseña (recomendado si sale del router)
/system backup save name=ax3-2026-10-15-produccion password="clave"

# Export legible (.rsc, sin contraseñas)
/export compact file=ax3-2026-10-15-produccion

# Export con datos sensibles (¡cuidado con dónde se guarda!)
/export file=ax3-2026-10-15-produccion show-sensitive

# Listar archivos existentes
/file print

# Filtrar por nombre
/file print where name~"ax3-2026"

# Restaurar un backup binario
/system backup load name=ax3-2026-10-15-produccion.backup

# Reiniciar el router
/system reboot
Nomenclatura recomendada: ax3-AAAA-MM-DD-HHMM-<estado>.ext. Ejemplo: ax3-2026-10-15-1730-pre-monopuesto.backup. Guardar siempre una copia fuera del router (en tormenta, por ejemplo, con ZFS y snapshots).

Firewall — Filter

# Ver reglas
/ip firewall filter print
/ip firewall filter print detail
/ip firewall filter print stats

# Permitir LAN → WAN (con prioridad antes del drop final)
/ip firewall filter add chain=forward in-interface-list=LAN out-interface-list=WAN \
    action=accept comment="Permitir LAN a WAN"

# Permitir LAN → VPN
/ip firewall filter add chain=forward in-interface-list=LAN out-interface=proton-vpn \
    action=accept comment="Permitir LAN a VPN"

# Colocar una regla antes de otra
/ip firewall filter add ... place-before=[find comment="Drop todo lo dems"]

# Mover una regla después de crearla
/ip firewall filter move [find comment~"Permitir LAN a VPN"] \
    destination=[find comment~"Drop todo lo dems"]

# Activar/desactivar temporalmente el log de una regla
/ip firewall filter set [find comment~"Drop todo lo demás"] log=yes log-prefix="DROP: "

# Resetear contadores
/ip firewall filter reset-counters [find]

Firewall — Mangle (policy routing)

# Ver reglas y contadores
/ip firewall mangle print
/ip firewall mangle print stats

# Excluir tráfico LAN del marcado (debe ir PRIMERO)
/ip firewall mangle add chain=prerouting dst-address-list=lan-directa \
    action=return comment="No marcar tráfico LAN"

# Mover la regla de exclusión al principio
/ip firewall mangle move [find comment~"No marcar"] \
    destination=[find comment~"Marcar conexin de xiaomi"]

# Marcar la conexión de un dispositivo
/ip firewall mangle add chain=prerouting src-address=192.168.88.51 in-interface=bridge \
    action=mark-connection new-connection-mark=solaris-vpn passthrough=yes \
    comment="Marcar conexión de solaris"

# Enrutar por VPN según la marca de conexión
/ip firewall mangle add chain=prerouting connection-mark=solaris-vpn \
    action=mark-routing new-routing-mark=via-vpn passthrough=no \
    comment="Enrutar solaris por VPN"

# MSS para PPPoE (MTU 1492)
/ip firewall mangle add chain=forward protocol=tcp tcp-flags=syn \
    out-interface=pppoe-o2 action=change-mss new-mss=1452 passthrough=yes \
    comment="MSS para PPPoE"

# MSS para túnel WireGuard (MTU 1420)
/ip firewall mangle add chain=forward protocol=tcp tcp-flags=syn \
    out-interface=proton-vpn action=change-mss new-mss=1380 passthrough=yes \
    comment="MSS para túnel WireGuard"
Orden crítico: la regla "No marcar tráfico LAN" debe ir antes de cualquier mark-connection o mark-routing. Si no, el tráfico hacia Pi-Hole, Unbound o cualquier host local se marcará con via-vpn y se enviará por el túnel, rompiendo el DNS sin motivo aparente.

Firewall — NAT

# Ver reglas
/ip firewall nat print
/ip firewall nat print stats

# Masquerade general (salida por PPPoE)
/ip firewall nat add chain=srcnat action=masquerade src-address=192.168.88.0/24 \
    out-interface=pppoe-o2 comment="NAT general por PPPoE"

# Masquerade para el túnel (debe ir ANTES que la general)
/ip firewall nat add chain=srcnat action=masquerade src-address=192.168.88.0/24 \
    out-interface=proton-vpn comment="NAT para ProtonVPN"

# Masquerade para acceder al HGU (activar solo cuando se necesite)
/ip firewall nat add chain=srcnat action=masquerade src-address=192.168.88.0/24 \
    out-interface=ether1 disabled=yes comment="NAT para entrar al HGU O2"

# Resetear contadores
/ip firewall nat reset-counters 2

Listas de direcciones e interfaces

# Ver lista de direcciones
/ip firewall address-list print

# Añadir red a la lista "lan-directa"
/ip firewall address-list add list=lan-directa address=192.168.88.0/24 \
    comment="LAN principal"
/ip firewall address-list add list=lan-directa address=192.168.1.0/24 \
    comment="LAN del HGU O2"
/ip firewall address-list add list=lan-directa address=10.2.0.0/24 \
    comment="Red interna ProtonVPN"

# Ver miembros de listas de interfaces
/interface list member print

# Añadir interfaz a la lista WAN
/interface list member add list=WAN interface=proton-vpn

Rutas

# Ver todas las rutas
/ip route print

# Ver rutas de la tabla via-vpn
/ip route print where routing-table=via-vpn

# Ver solo la ruta por defecto
/ip route print where dst-address=0.0.0.0/0

# Salida por ProtonVPN
/ip route add dst-address=0.0.0.0/0 gateway=proton-vpn routing-table=via-vpn \
    distance=1 comment="Salida por ProtonVPN"

# Kill switch: blackhole si el túnel cae
/ip route add dst-address=0.0.0.0/0 type=blackhole routing-table=via-vpn \
    distance=2 comment="Kill switch"
Kill switch por blackhole: si el túnel está arriba, la ruta 1 (distance=1) está activa y la 2 nunca se usa. Si el túnel cae, la ruta 1 se vuelve inactiva y entra la 2 (blackhole), descartando el tráfico marcado. No hay fuga posible hacia la WAN normal.

DHCP y PPPoE

# Ver red DHCP configurada
/ip dhcp-server network print

# Forzar DNS a Pi-Hole
/ip dhcp-server network set [find] dns-server=192.168.88.244

# Ver pool DHCP
/ip pool print

# Cambiar rango del pool
/ip pool set default-dhcp ranges=192.168.88.10-192.168.88.254

# Ver cliente PPPoE
/interface pppoe-client print detail

# Monitorizar la sesión PPPoE
/interface pppoe-client monitor [find] once

# Asegurar que PPPoE añade ruta por defecto
/interface pppoe-client set [find name=pppoe-o2] add-default-route=yes

# DHCP client de ether1 sin añadir ruta (evita doble NAT)
/ip dhcp-client set [find interface=ether1] add-default-route=no
Doble NAT: si el DHCP client de ether1 tiene add-default-route=yes, RouterOS instalará una ruta 0.0.0.0/0 via 192.168.1.1 que reintroduce el NAT del HGU. Debe estar siempre en no.

DNS

# Ver configuración DNS del router
/ip dns print

# Desactivar el resolver del router (los clientes usan Pi-Hole)
/ip dns set allow-remote-requests=no
Cadena DNS: clientes → Pi-Hole (192.168.88.244) → Unbound (192.168.88.160) → resolución recursiva. El router no participa. Por eso allow-remote-requests debe estar en no: si se activa, se salta Pi-Hole y Unbound.

WireGuard

# Ver interfaces WireGuard
/interface wireguard print

# Ver peers
/interface wireguard peers print

# Ver detalle (endpoint, allowed IPs, última conexión)
/interface wireguard peers print detail

# Ping por el túnel
/ping 10.2.0.1 count=3 interface=proton-vpn

Diagnóstico y monitorización

# Ver interfaces activas y sus MTU
/interface print

# Ver direcciones IP asignadas
/ip address print

# Ver conexiones activas con marca VPN
/ip firewall connection print where connection-mark~"vpn"

# Ver conexiones de una IP concreta
/ip firewall connection print where src-address~"192.168.88.51"

# Ver conexiones al Pi-Hole
/ip firewall connection print where dst-address~"192.168.88.244"

# Ver logs de PPPoE
/log print where topics~"pppoe"

# Ver logs de firewall con prefijo concreto
/log print where message~"DROP-OTROS"

# Ver contadores de mangle
/ip firewall mangle print stats

# Activar Safe Mode (revierte cambios si se pierde la sesión)
/system safe-mode

Cliente — comandos útiles

# Generar par de claves ed25519
ssh-keygen -t ed25519 -f ~/.ssh/mikrotik_axe -C "carlos@mikrotik-ax3"

# Ver fingerprint de una clave pública
ssh-keygen -lf ~/.ssh/mikrotik_axe.pub

# Limpiar entrada antigua de known_hosts
ssh-keygen -R 192.168.88.1

# Subir clave pública al router
scp ~/.ssh/mikrotik_axe.pub carlos@192.168.88.1:/mikrotik_axe.pub

# Conectar con clave específica
ssh -i ~/.ssh/mikrotik_axe carlos@192.168.88.1

# Debug de conexión SSH
ssh -v -i ~/.ssh/mikrotik_axe carlos@192.168.88.1

# Descargar backups
scp carlos@192.168.88.1:/ax3-2026-10-15-produccion.backup .
scp carlos@192.168.88.1:/ax3-2026-10-15-produccion.rsc .

# Ver IP pública actual
curl -s ifconfig.me

# Probar fugas DNS
nslookup whoami.akamai.net
nslookup dnsleaktest.com

~/.ssh/config (cliente)

Host mikrotik-ax3
    HostName 192.168.88.1
    User carlos
    IdentityFile ~/.ssh/mikrotik_axe
    IdentitiesOnly yes

Host mikrotik-admin
    HostName 192.168.88.1
    User admin

Con eso:

ssh mikrotik-ax3
scp archivo.bin mikrotik-ax3:/

Comandos de rescate

# Ver reglas de mangle en orden (lo primero al depurar policy routing)
/ip firewall mangle print

# Ver si las reglas tienen tráfico (contadores)
/ip firewall mangle print stats

# Ver si hay rutas en la tabla via-vpn
/ip route print where routing-table=via-vpn

# Ver el peer WireGuard activo
/interface wireguard peers print

# Resetear una interfaz
/interface wireguard disable proton-vpn
/interface wireguard enable proton-vpn

# Resetear conexiones de una IP (útil tras cambiar política)
/ip firewall connection remove [find src-address~"192.168.88.51"]

# Ver qué cae en el drop final
/ip firewall filter set [find comment~"Drop todo lo demás"] log=yes
/log print where message~"DROP"
/ip firewall filter set [find comment~"Drop todo lo demás"] log=no

Buenas prácticas aplicadas

Elemento Valor correcto
strong-cryptoyes
password-authenticationyes-if-no-key (tras importar claves)
FasttrackDeshabilitado (rompe policy routing)
allow-remote-requests (DNS)no
DHCP client de ether1add-default-route=no
PPPoE clientadd-default-route=yes
Kill switch VPNRuta blackhole en tabla via-vpn
Regla de exclusión LANPrimera en prerouting
MSS1452 para PPPoE, 1380 para túnel
Backups.backup + .rsc, copia externa en tormenta

Arquitectura de referencia

O2 / Internet
   │
Fibra óptica
   │
┌──────────────────────────┐
│ MitraStar GPT-2541GNAC   │
│ MONOPUESTO               │
│ VoIP: teléfono fijo      │
└────────────┬─────────────┘
             │ Ethernet / PPPoE
             ▼
┌──────────────────────────┐
│ hAP ax³                  │
│ PPPoE + NAT + Firewall   │
│ WireGuard + ProtonVPN    │
│ Policy routing           │
└────────────┬─────────────┘
             │
       192.168.88.0/24
             │
   ├── tormenta   .160  FreeBSD 14.5 (Unbound, NFSv4, Kerberos, ZFS, Samba)
   ├── solaris    .51   FreeBSD 14.5
   ├── raspberry  .244  Raspberry Pi 3B + Pi-Hole
   └── demás dispositivos

Cadena DNS: clientes → Pi-Hole (.244) → Unbound (.160) → recursivo


Cheatsheet de Proyecto ax³. Última actualización: 2026-10-15.

FreeBSD es genial!.

martes, 13 de octubre de 2026

Proyecto ax³ — Índice de la serie

Proyecto ax³

Durante los próximos tres artículos documento la sustitución del router principal de casa —un MikroTik hAP ac²— por un MikroTik hAP ax³, aprovechando la ocasión para reorganizar por completo la red: eliminar el doble NAT, montar WireGuard con ProtonVPN, montar policy routing por dispositivo y dejar el DNS en manos de Pi-Hole y Unbound.

La serie está pensada como una guía reproducible. El hilo conductor es sencillo: nada se toca hasta que lo nuevo está probado. El hAP ac² sigue funcionando exactamente igual durante todo el proceso y solo se apaga cuando el ax³ ya está listo para entrar en producción.

Serie completa:
  • Parte 1 — Qué cambia y por qué.
    Objetivo, comparativa hAP ac² vs hAP ax³, arquitectura final y distribución de servicios.
    Leer Parte 1 →
  • Parte 2 — Preparar el ax³ sin tocar la red.
    RouterOS y firmware, red de laboratorio aislada 192.168.50.0/24, configuración base, firewall y backups.
    Leer Parte 2 →
  • Parte 3 — Monopuesto, VPN y corte final.
    PPPoE de O2, MitraStar en monopuesto, WireGuard + ProtonVPN, policy routing, kill switch, DNS con Pi-Hole y Unbound, migración final y plan de reversión.
    Leer Parte 3 →

Arquitectura final

O2 / Internet
   │
Fibra óptica
   │
┌──────────────────────────────────┐
│ MitraStar GPT-2541GNAC           │
│ MONOPUESTO                       │
│ SIN NAT                          │
│ Teléfono ─── VoIP                │
└────────────┬─────────────────────┘
             │ Ethernet / PPPoE
             ▼
┌──────────────────────────────────┐
│ hAP ax³                          │
│ PPPoE + NAT + Firewall           │
│ WireGuard + ProtonVPN            │
│ Policy routing                   │
└────────────┬─────────────────────┘
             │
       192.168.88.0/24
             │
   ├── tormenta      192.168.88.160   FreeBSD 14.5 (Unbound, NFSv4, Kerberos, ZFS, Samba)
   ├── solaris       192.168.88.51    FreeBSD 14.5
   ├── raspberry     192.168.88.244   Raspberry Pi 3B + Pi-Hole
   └── demás dispositivos

Puntos clave del proyecto

  • Sin doble NAT: el MitraStar pasa a monopuesto y el ax³ recibe la IP pública por PPPoE.
  • Sin cortes: el hAP ac² sigue en producción hasta el corte final.
  • DNS propio: clientes → Pi-Hole (raspberry.casa.lan) → Unbound (tormenta.casa.lan).
  • VPN por dispositivo: policy routing con mark-connection + mark-routing y kill switch por blackhole.
  • Reversión ensayada: vuelta al hAP ac² en menos de 10 minutos si algo falla.
Filosofía de la serie: el objetivo no es solo migrar, sino poder volver atrás si algo falla. Esa garantía es lo que convierte un cambio de router en un proyecto controlado y no en una tarde de emergencia.

Empezar a leer

Material complementario: Cheatsheet RouterOS — Proyecto ax³
Todos los comandos usados en la serie, agrupados por tema y listos para copiar.
FreeBSD es genial!.

Proyecto ax³ (3/3) — Monopuesto, VPN y corte final

Proyecto ax³ (3/3) — Monopuesto, VPN y corte final
Serie completa: Índice · Parte 1 · Parte 2 · Parte 3

Referencia de comandos: Cheatsheet RouterOS — Proyecto ax³

Introducción

En la Parte 1 definimos el objetivo, la comparativa y la arquitectura. En la Parte 2 dejamos el hAP ax³ completamente preparado en la red aislada 192.168.50.0/24, con RouterOS y firmware actualizados, DHCP funcionando, Wi-Fi 6 configurado, firewall básico y backups en orden.

En esta tercera y última parte se hace el corte real: configurar el PPPoE de O2, poner el MitraStar en monopuesto, integrar WireGuard con ProtonVPN, montar el policy routing, cerrar el DNS con Pi-Hole y Unbound, migrar a 192.168.88.0/24 y apagar el hAP ac².

Esta es la parte con riesgo real. Hasta aquí todo eran pruebas aisladas. A partir de este punto, un error puede dejar la red sin Internet. Antes de empezar, ten a mano el bloque de reversión que está al final de este artículo y asegúrate de haberlo leído entero.

Fase 5 — Internet O2 y monopuesto

El objetivo de esta fase es que el hAP ax³ reciba directamente la IP pública por PPPoE, eliminando el doble NAT que hoy existe entre el MitraStar y el router. Para ello, el MitraStar pasa a modo monopuesto.

Arquitectura final

O2 / Internet
   │
Fibra óptica
   │
┌──────────────────────────────────┐
│ MitraStar GPT-2541GNAC           │
│ MONOPUESTO                       │
│ SIN NAT                          │
│ Teléfono ─── VoIP                │
└────────────┬─────────────────────┘
             │ Ethernet / PPPoE
             ▼
┌──────────────────────────────────┐
│ hAP ax³                          │
│ PPPoE + NAT + Firewall           │
│ WireGuard + ProtonVPN            │
│ Policy routing                   │
└────────────┬─────────────────────┘
             │
       192.168.88.0/24
             │
   ├── tormenta      192.168.88.160   FreeBSD 14.5 (Unbound, NFSv4, Kerberos, ZFS, Samba)
   ├── solaris       192.168.88.51    FreeBSD 14.5
   ├── raspberry     192.168.88.244   Raspberry Pi 3B + Pi-Hole
   └── demás dispositivos

Datos PPPoE de O2

Usuario:    adslppp@telefonicanetpa
Contraseña: adslppp

Notas sobre el MitraStar GPT-2541GNAC

Este HGU tiene un comportamiento específico que conviene documentar antes de tocarlo. En monopuesto, delega la conexión de Internet al router neutro mediante PPPoE, pero sigue gestionando la VoIP del teléfono fijo. Es exactamente lo que queremos.

Modelo / Board IDGPT-2541GNAC
FirmwareES_g7.12_100VNJ0b73
Build230705_2059 → 5 de julio de 2023
Bootloader1.0.41-117.134
Wireless driver6.37.14.4803.cpe4.14L04Apatch1.0
Recomendaciones críticas para el monopuesto:
  • Usar la opción «Monopuesto» de la interfaz básica del MitraStar.
  • No intentar construir el bridge manualmente desde la interfaz avanzada.
  • Hay reportes de bugs si se manipulan VLAN desde el menú avanzado.
  • En monopuesto, el HGU entrega el PPPoE sin etiquetar.
  • Por tanto, no configurar VLAN 6 en el MikroTik.
Atención con la VoIP: existen casos documentados con este firmware en los que el teléfono deja de funcionar a los pocos minutos de activar monopuesto. Si ocurre, la solución reportada es acceder a la configuración avanzada del HGU, editar la interfaz WAN de VoIP y habilitar las opciones Enable IGMP Multicast Proxy y Enable IGMP Multicast Source. No dar el cambio por bueno hasta que hayan pasado al menos 48 horas sin incidencias.

Configurar el cliente PPPoE en el ax³

  1. Conectar el cable del MitraStar al puerto ether1 del ax³.
  2. WinBox → PPP → Interface → + → PPPoE Client.
  3. Configurar:
    • Name: pppoe-o2
    • Interface: ether1
    • User: adslppp@telefonicanetpa
    • Password: adslppp
    • Add Default Route: sí
    • Use Peer DNS: no
  4. Apply → OK.

Comprobar que la sesión levanta:

/interface pppoe-client monitor [find] once
/log print where topics~"pppoe"

Activar el monopuesto en el MitraStar

  1. Acceder al MitraStar por su interfaz web.
  2. Ir a la sección básica de configuración WAN.
  3. Activar la opción «Monopuesto».
  4. Guardar y esperar el reinicio del HGU.
  5. Comprobar en el ax³ que la sesión PPPoE obtiene una IP pública.
  6. Verificar que el teléfono fijo sigue registrando correctamente.
Decisión clave sobre el DHCP client de ether1: el ax³ mantiene un DHCP client activo en ether1 para obtener una IP en la LAN del HGU (192.168.1.0/24), lo que permite acceder a la interfaz web del MitraStar si hace falta. Pero ese cliente debe tener add-default-route=no. Si lo activamos, RouterOS añade una ruta 0.0.0.0/0 via 192.168.1.1 que reintroduce el doble NAT que acabamos de eliminar.
/ip dhcp-client set [find interface=ether1] add-default-route=no
/interface pppoe-client set [find name=pppoe-o2] add-default-route=yes

Verificar que la única ruta por defecto es la del PPPoE:

/ip route print where dst-address=0.0.0.0/0

Debe aparecer una sola ruta por defecto en la tabla main:

DAv 0.0.0.0/0  gateway=pppoe-o2  distance=1

Fase 6 — VPN, DNS y policy routing

Con Internet funcionando en el ax³, ya se puede montar el resto de la infraestructura: WireGuard, ProtonVPN, policy routing, kill switch y DNS definitivo. Esta fase es la más delicada del proyecto, porque cualquier error aquí no rompe la red entera, pero sí deja dispositivos sin Internet de forma difícil de diagnosticar.

WireGuard y ProtonVPN

ProtonVPN ofrece configuración WireGuard lista para importar. Desde el panel de ProtonVPN se genera un archivo con clave privada, clave pública del servidor, endpoint y AllowedIPs. Se importa directamente en RouterOS:

WireGuard → Interface → + → Import from file

Comprobar que el túnel levanta:

/interface wireguard print
/interface wireguard peers print
/ping 10.2.0.1 count=3 interface=proton-vpn
Detalle importante: verificar que el campo AllowedIPs del peer incluye 0.0.0.0/0. Si solo incluye rangos parciales, algunos destinos no pasarán por la VPN aunque los marques con routing-mark.

Policy routing: el patrón correcto

El objetivo es que cada dispositivo pueda salir por WAN normal o por ProtonVPN según una política definida. En RouterOS esto se hace combinando tres piezas:

  1. Marcar la conexión al primer paquete (chain prerouting).
  2. Marcar el routing de todos los paquetes de esa conexión.
  3. Una tabla de rutas alternativa que envía lo marcado por el túnel.
Error común: marcar directamente routing-mark en prerouting sin marcar antes la conexión. Funciona en el 90% de los casos, pero falla con NAT, con retorno asimétrico y cuando una conexión se reutiliza. El patrón robusto es siempre primero marcar conexión, después marcar routing.

Estructura final de las reglas de mangle

0     No marcar tráfico LAN          dst-address-list=lan-directa
1-2   Dummy (dinámicas)
3     change-mss 1452                out-interface=pppoe-o2
4     Marcar conexión de xiaomi      src-address=192.168.88.252
5     Marcar conexión de solaris     src-address=192.168.88.51
6     Enrutar xiaomi por VPN         connection-mark=xiaomi-vpn
7     Enrutar solaris por VPN        connection-mark=solaris-vpn
8     change-mss 1380                out-interface=proton-vpn

Paso 1 — Address-list con las redes que NO se marcan

Antes de cualquier regla de marcado, hay que excluir el tráfico destinado a la propia LAN. Si no, el tráfico hacia Pi-Hole, Unbound o cualquier host local se marca con via-vpn, y como la tabla via-vpn no tiene ruta a 192.168.88.0/24, esas consultas se van por el túnel en lugar de entregarse localmente. El síntoma es desconcertante: parece que "no hay Internet", pero el ping por IP funciona.

/ip firewall address-list
add list=lan-directa address=192.168.88.0/24 comment="LAN principal"
add list=lan-directa address=192.168.1.0/24  comment="LAN del HGU O2"
add list=lan-directa address=10.2.0.0/24     comment="Red interna ProtonVPN"

Y la regla de exclusión, al principio de prerouting:

/ip firewall mangle
add chain=prerouting dst-address-list=lan-directa action=return \
    comment="No marcar tráfico LAN"
Si place-before=0 falla (RouterOS no acepta referencias a reglas dinámicas), añade la regla al final y muévela después con move [find comment~"No marcar"] destination=[find comment~"Marcar conexin de xiaomi"]. Lo importante es que esté antes de cualquier mark-connection o mark-routing.

Paso 2 — Marcar conexión por dispositivo

/ip firewall mangle
add chain=prerouting src-address=192.168.88.252 in-interface=bridge \
    action=mark-connection new-connection-mark=xiaomi-vpn passthrough=yes \
    comment="Marcar conexión de xiaomi"

add chain=prerouting src-address=192.168.88.51 in-interface=bridge \
    action=mark-connection new-connection-mark=solaris-vpn passthrough=yes \
    comment="Marcar conexión de solaris"

El passthrough=yes es importante: después de marcar la conexión, el paquete sigue evaluándose contra las reglas siguientes, que serán las que lean esa marca.

Paso 3 — Enrutar por VPN según la marca de conexión

/ip firewall mangle
add chain=prerouting connection-mark=xiaomi-vpn \
    action=mark-routing new-routing-mark=via-vpn passthrough=no \
    comment="Enrutar xiaomi por VPN"

add chain=prerouting connection-mark=solaris-vpn \
    action=mark-routing new-routing-mark=via-vpn passthrough=no \
    comment="Enrutar solaris por VPN"

El passthrough=no ahorra ciclos de CPU: una vez marcado el routing, no hace falta seguir evaluando más reglas de mangle.

Paso 4 — Tabla de rutas con kill switch por blackhole

La tabla via-vpn debe tener dos rutas: una activa por el túnel y otra blackhole de respaldo. Si el túnel cae, la activa desaparece y entra la blackhole, que descarta el tráfico marcado. Es un kill switch a nivel de routing, sin necesidad de reglas de firewall adicionales.

/ip route
add dst-address=0.0.0.0/0 gateway=proton-vpn routing-table=via-vpn distance=1 \
    comment="Salida por ProtonVPN"
add dst-address=0.0.0.0/0 type=blackhole routing-table=via-vpn distance=2 \
    comment="Kill switch: descartar si el túnel cae"
Por qué funciona: si el túnel está arriba, la ruta 1 está activa y la 2 nunca se usa. Si el túnel cae, la ruta 1 se vuelve inactiva y la 2 entra en juego, descartando el tráfico marcado. No hay fuga posible hacia la WAN normal.

Paso 5 — MSS por interfaz

El MSS (Maximum Segment Size) es el tamaño máximo de payload TCP. Si se configura mal, se produce fragmentación o drops silenciosos: algunas webs cargan, otras se quedan colgadas, y parece que "no hay Internet" cuando en realidad es un problema de MTU.

/ip firewall mangle
add chain=forward protocol=tcp tcp-flags=syn out-interface=pppoe-o2 \
    action=change-mss new-mss=1452 passthrough=yes \
    comment="MSS para PPPoE (MTU 1492)"

add chain=forward protocol=tcp tcp-flags=syn out-interface=proton-vpn \
    action=change-mss new-mss=1380 passthrough=yes \
    comment="MSS para túnel WireGuard (MTU 1420)"
Interfaz MTU MSS Fórmula
pppoe-o2 1492 1452 1492 − 40 (IP+TCP)
proton-vpn 1420 1380 1420 − 40 (IP+TCP)
bridge (LAN) 1500 1460 1500 − 40 (IP+TCP)
Error frecuente: usar un único MSS de 1452 para todo el tráfico. Para el tráfico que sale por PPPoE es correcto, pero para el que sale por el túnel es demasiado alto. Los paquetes grandes se fragmentan o se descartan silenciosamente, y el síntoma es exactamente el de "webs a medio cargar".

Paso 6 — Regla de forward para el tráfico del túnel

El firewall del ax³ tiene una regla que acepta el tráfico de LAN hacia WAN, pero el túnel proton-vpn normalmente no está en la lista WAN. Sin una regla específica, el tráfico que sale por el túnel cae en el Drop todo lo demás y se descarta.

/ip firewall filter
add chain=forward in-interface-list=LAN out-interface=proton-vpn \
    action=accept comment="Permitir LAN a VPN" \
    place-before=[find comment="Drop todo lo dems"]

Paso 7 — DNS con Pi-Hole y Unbound

Clientes de la LAN
   │
   ▼
Pi-Hole (raspberry.casa.lan / 192.168.88.244)
   │
   ▼
Unbound (tormenta.casa.lan / 192.168.88.160)
   │
   ▼
Resolución recursiva directa (sin DNS externos)

En el ax³, dos ajustes complementarios:

# 1. El DHCP entrega solo Pi-Hole como DNS
/ip dhcp-server network
set [find] dns-server=192.168.88.244

# 2. El router no actúa como resolver DNS
/ip dns
set allow-remote-requests=no
Allow Remote Requests debe estar desactivado. Si se activa, el router abre un resolver en 192.168.88.1:53 que se salta Pi-Hole y Unbound. Eso rompe el filtrado y puede filtrar metadatos al ISP si el router reenvía al DNS del operador.

Verificación final del policy routing

/ip firewall mangle print stats
Regla Debe tener paquetes Comentario
No marcar tráfico LAN ✅ Ping a Pi-Hole, Unbound, etc.
Marcar conexión de xiaomi ✅ Primer paquete de cada conexión
Marcar conexión de solaris ✅ Primer paquete de cada conexión
Enrutar xiaomi por VPN ✅ Todos los paquetes de la conexión
Enrutar solaris por VPN ✅ Todos los paquetes de la conexión
MSS túnel WireGuard ✅ Solo paquetes SYN que salen por el túnel
Diferencia esperada entre marca y enrutamiento: la regla "Marcar conexión" solo actúa sobre el primer paquete de cada conexión, la "Enrutar por VPN" sobre todos. Por eso la segunda siempre tiene más paquetes. Si ves lo contrario, algo va mal.

Prueba real desde un cliente VPN

# Desde solaris
ping -c 3 192.168.88.244   # Pi-Hole (debe funcionar)
ping -c 3 1.1.1.1          # Internet por IP (por el túnel)
ping -c 3 google.com       # DNS (por Pi-Hole)
curl -s ifconfig.me        # IP pública (debe ser de ProtonVPN)
Resultado esperado: curl ifconfig.me devuelve una IP distinta a la de O2 (que es la que devolverá desde cualquier dispositivo que NO esté en la lista de clientes VPN).

Kill switch: prueba real

  1. Deshabilitar la interfaz WireGuard:
    /interface wireguard disable proton-vpn
  2. Desde solaris, comprobar que no tiene Internet:
    ping -c 3 1.1.1.1
  3. Comprobar que sigue teniendo acceso a la LAN:
    ping -c 3 192.168.88.244
  4. Volver a habilitar la interfaz:
    /interface wireguard enable proton-vpn
  5. Comprobar que recupera Internet por el túnel:
    curl -s ifconfig.me

Fase 7 — Corte final

Llegados a este punto, el ax³ funciona en 192.168.50.0/24 con Internet, PPPoE, VPN, policy routing y DNS completo. Solo falta el cambio final: apagar el ac² y migrar el ax³ a 192.168.88.0/24.

O2 monopuesto
      │
      ▼
   hAP ax³
      │
192.168.88.0/24
      │
tormenta + solaris + raspberry + resto de LAN

Preparativos antes del corte

  1. Backup completo del hAP ac² exportado y descargado.
  2. Backup completo del hAP ax³ exportado y descargado.
  3. Capturas de la configuración actual del MitraStar.
  4. Confirmar que el hAP ac² está apagado pero accesible físicamente.
  5. Ventana de mantenimiento acordada con quien use la red.

Pasos del corte

  1. Apagar el hAP ac² y desconectarlo de la red.
  2. En el ax³, cambiar la IP LAN de 192.168.50.1/24 a 192.168.88.1/24.
  3. Actualizar el DHCP Network a 192.168.88.0/24.
  4. Actualizar el pool DHCP a 192.168.88.10-192.168.88.254.
  5. Conectar el ax³ al switch de la LAN.
  6. Comprobar desde un cliente:
    • IP recibida por DHCP.
    • Puerta de enlace 192.168.88.1.
    • Acceso a Internet.
    • Resolución DNS vía Pi-Hole.

Comprobaciones post-corte

# Desde un cliente de la LAN
curl -s ifconfig.me           # Debe devolver la IP pública de O2

# Desde el ax³
/ip route print where dst-address=0.0.0.0/0
/interface pppoe-client monitor [find] once
/ip firewall mangle print stats
  • Internet normal funcionando.
  • Internet por ProtonVPN funcionando en los clientes marcados.
  • Policy routing por dispositivo correcto.
  • Kill switch bloqueando fugas.
  • DNS sin fugas: clientes → Pi-Hole → Unbound.
  • NFSv4, Kerberos, ZFS y Samba accesibles desde clientes.
  • VoIP del MitraStar operativa.
  • Rendimiento Wi-Fi 6 correcto.
Estado final alcanzado: el hAP ax³ es el router de producción, sale directamente por la IP pública de O2 vía PPPoE (sin doble NAT), el MitraStar está en monopuesto gestionando la VoIP, y el hAP ac² queda apagado con su configuración intacta, listo para volver a entrar en servicio si algo falla.

Plan de reversión

Regla de oro: nunca se desmonta nada antes de tener confirmado que el nuevo estado funciona. El hAP ac² no se apaga, no se resetea y no se reconfigura hasta que el ax³ lleve al menos 48 horas funcionando en producción sin incidencias.

Puntos de retorno

Punto de no retorno Síntoma Acción de reversión
Antes de monopuesto Todo funciona con doble NAT Nada que revertir. Seguir probando.
Tras activar monopuesto VoIP deja de funcionar Volver a modo router en el MitraStar
Tras activar monopuesto El ax³ no levanta PPPoE Volver a modo router en el MitraStar
Tras el corte final Fallo grave en el ax³ Reenchufar el ac² tal cual estaba
Tras el corte final Fugas DNS o kill switch roto Volver al ac² y revisar reglas

Caso 1 — La VoIP deja de funcionar tras monopuesto

Síntoma: el teléfono fijo registra correctamente al principio y deja de funcionar a los pocos minutos. Es un bug conocido de determinadas versiones de firmware MitraStar, entre ellas la ES_g7.12_100VNJ0b73.
  1. Acceder al MitraStar por su interfaz web.
  2. Ir a la opción de Monopuesto en la interfaz básica.
  3. Desactivarla y volver a modo router.
  4. Confirmar que el teléfono vuelve a registrar.
  5. El hAP ax³ seguirá funcionando detrás del MitraStar, pero volveremos a tener doble NAT.

Alternativa si se quiere insistir en monopuesto:

  • Acceder a la configuración avanzada del HGU.
  • Editar la interfaz WAN de VoIP.
  • Habilitar Enable IGMP Multicast Proxy y Enable IGMP Multicast Source.
  • Guardar y comprobar que el teléfono vuelve a registrar.

Caso 2 — El ax³ no levanta PPPoE

Diagnóstico rápido:

/interface pppoe-client monitor [find] once
/log print where topics~"pppoe"

Comprobaciones:

  1. Usuario y contraseña exactos:
    Usuario:    adslppp@telefonicanetpa
    Contraseña: adslppp
  2. Que el MitraStar esté realmente en monopuesto.
  3. Que el cable salga del puerto correcto del MitraStar hacia ether1.
  4. Que no haya VLAN configurada en ether1.
  5. Que ether1 no esté dentro del bridge.

Caso 3 — Corte final: hay que volver al hAP ac²

Requisito previo: el hAP ac² debe estar apagado pero físicamente accesible y con su configuración intacta.
  1. Apagar el hAP ax³.
  2. Desconectar el cable que va del MitraStar al ether1 del ax³.
  3. Reconectar el hAP ac² exactamente como estaba.
  4. Encender el hAP ac².
  5. Esperar 60–90 segundos.
  6. Comprobar desde un cliente: IP, puerta de enlace, Internet, DNS.
  7. Si el MitraStar sigue en monopuesto, volverlo a modo router.

Caso 4 — Fugas DNS o kill switch roto

# Fuga DNS
nslookup whoami.akamai.net
nslookup dnsleaktest.com

# Kill switch (con el túnel caído)
ping 1.1.1.1
curl ifconfig.me

Reversión inmediata:

  1. Desactivar temporalmente el policy routing en el ax³.
  2. Dejar todo el tráfico saliendo por la WAN normal.
  3. Confirmar que Internet vuelve a funcionar.
  4. Revisar reglas de firewall, marcas de routing y DNS antes de reactivar.

Caso 5 — El ax³ se queda inaccesible

Reglas preventivas:

  • WinBox por MAC siempre disponible.
  • Safe Mode activado antes de tocar firewall o interfaces:
    /system safe-mode

Si aun así queda inaccesible:

  1. Conectar el portátil a un puerto LAN del ax³.
  2. WinBox → Neighbors → entrar por MAC.
  3. Si tampoco aparece, resetear el ax³ y restaurar el último backup.

Checklist de reversión

  • ☐ Capturas de la configuración del MitraStar guardadas.
  • ☐ Backup del hAP ac² exportado y descargado.
  • ☐ Backup del hAP ax³ exportado y descargado.
  • ☐ Cable del MitraStar etiquetado (WAN, LAN).
  • ☐ Procedimiento de reversión impreso o accesible desde el móvil.
  • ☐ hAP ac² accesible físicamente, apagado pero listo para reconectar.
  • ☐ Ventana de mantenimiento acordada.
  • ☐ Ensayo previo del corte y de la reversión hecho antes del día real.
Filosofía del plan: el objetivo no es que no falle nada, sino que si falla algo, en menos de 10 minutos todo el mundo esté navegando como antes. La migración se hace cuando se puede permitir el lujo de fallar; no cuando no hay margen.

Pendientes por aclarar

  • Confirmar que la VoIP del MitraStar se mantiene operativa durante 48 horas.
  • Definir política final de DNS: Pi-Hole como único DNS para clientes, Unbound como resolver recursivo aguas arriba.
  • Definir reservas DHCP fijas en 192.168.88.0/24 para tormenta, solaris y raspberry.
  • Documentar qué dispositivos van por ProtonVPN y cuáles por WAN normal.
  • Valorar migrar de reglas por IP a address-list=vpn-clients cuando la lista de dispositivos VPN crezca.

Checklist final del proyecto

  • ☐ hAP ac² sigue funcionando hasta el corte final.
  • ☐ hAP ax³ actualizado: RouterOS y firmware al mismo nivel.
  • ☐ Backup inicial del ax³.
  • ☐ IP LAN temporal: 192.168.50.1/24.
  • ☐ DHCP Network temporal: 192.168.50.0/24.
  • ☐ Pool temporal: 192.168.50.10-192.168.50.254.
  • ☐ Portátil en 192.168.50.254.
  • ☐ WinBox por MAC funcionando.
  • ☐ Configuración base: bridge, DHCP, Wi-Fi 6, firewall, NAT.
  • ☐ PPPoE O2: adslppp@telefonicanetpa / adslppp.
  • ☐ MitraStar en monopuesto.
  • ☐ VoIP operativa tras monopuesto.
  • ☐ WireGuard + ProtonVPN funcionando.
  • ☐ Policy routing por dispositivo con mark-connection + mark-routing.
  • ☐ Exclusión LAN (lan-directa) al principio del mangle.
  • ☐ MSS por interfaz: 1452 para PPPoE, 1380 para túnel.
  • ☐ Regla de forward LAN → VPN.
  • ☐ Kill switch por blackhole probado con túnel caído.
  • ☐ DNS sin fugas: clientes → Pi-Hole → Unbound.
  • ☐ allow-remote-requests=no en /ip dns.
  • ☐ DHCP entrega solo 192.168.88.244 como DNS.
  • ☐ NFSv4, Kerberos, ZFS y Samba accesibles.
  • ☐ Corte final a 192.168.88.0/24.
  • ☐ IP pública confirmada desde cliente (curl ifconfig.me).
  • ☐ 48 horas de observación antes de retirar el ac² definitivamente.
Serie: este artículo cierra Proyecto ax³. Viene de la Parte 1 — Qué cambia y por qué y de la Parte 2 — Preparar el ax³ sin tocar la red.

Volver al índice de la serie · Cheatsheet RouterOS
FreeBSD es genial!.

Proyecto ax³ (2/3) — Preparar el ax³ sin tocar la red

Proyecto ax³ (2/3) — Preparar el ax³ sin tocar la red
Serie completa: Índice · Parte 1 · Parte 2 · Parte 3

Referencia de comandos: Cheatsheet RouterOS — Proyecto ax³

Introducción

En la Parte 1 vimos el objetivo, la comparativa entre el hAP ac² y el hAP ax³ y la arquitectura final del proyecto. En esta segunda parte entramos en materia: cómo preparar el hAP ax³ completamente aislado de la red de producción, sobre una red temporal 192.168.50.0/24, sin tocar en ningún momento el hAP ac² ni el MitraStar.

La idea es sencilla: durante toda esta fase, el ax³ no tiene salida a Internet y no conoce la red 192.168.88.0/24. Es un laboratorio cerrado, con un único portátil conectado por cable, donde se construye el router desde cero.

Fase 0 — Estado de seguridad

Antes de tocar nada del ax³, hay que garantizar que la red de producción queda intacta. Esto implica tres reglas que no se negocian.

  • No tocar la red actual 192.168.88.0/24.
  • El hAP ac² sigue funcionando exactamente como hasta ahora.
  • El hAP ax³ se prepara aislado: no se conecta al hAP ac² ni al MitraStar.
hAP ac² ─── RED ACTUAL 192.168.88.0/24 ─── TODO NORMAL

hAP ax³ ─── portátil ─── SIN WAN
Precaución crítica: no conectar el ax³ al hAP ac² ni al MitraStar durante toda esta fase. Si ambos routers tienen la misma red (192.168.88.0/24) en el mismo segmento, se producirán conflictos de DHCP y de puerta de enlace difíciles de diagnosticar.
Ventana de trabajo: esta fase se puede hacer en cualquier momento, sin prisa y sin afectar a nadie. No hay ventana de mantenimiento porque nada de la red real se toca.

Fase 1 — Primer contacto con el hAP ax³

Sacamos el ax³ de la caja, lo conectamos a un portátil por cable y comprobamos su estado de fábrica. Nada más. Sin configuración, sin cambios.

Conexión física

  1. Conectar la alimentación.
  2. Conectar un cable Ethernet del portátil a un puerto LAN del ax³ (no al puerto WAN/Internet).
  3. No conectar nada al puerto WAN del ax³.
  4. Encender el equipo y esperar a que arranque.

Primer acceso

Comprobar la IP que ha recibido el portátil:

# Windows
ipconfig

# FreeBSD / Linux
ifconfig
route -n get default

Entrar por WinBox o WebFig:

WebFig:  http://192.168.88.1
WinBox:  Neighbors → seleccionar el ax³ → Connect
Acceso por MAC: si el ax³ no responde por IP, WinBox permite conectarse por dirección MAC desde la pestaña Neighbors, siempre que el portátil esté en el mismo segmento L2. Es la vía recomendada cuando se cambia la IP LAN y no queremos perder la sesión.

Revisión inicial

  • Versión de RouterOS.
  • Firmware del RouterBOARD.
  • Interfaces detectadas.
  • Configuración de fábrica (bridge, DHCP, Wi-Fi por defecto).
  • Conectividad local (ping al gateway).
  • Primer backup.

Hacer el primer backup desde WinBox:

Files → Backup → nombre: ax3-inicial.backup

Y descargarlo al portátil antes de continuar:

Files → seleccionar el .backup → Download

Fase 2 — RouterOS y firmware

En este proyecto, RouterOS ya estaba actualizado a 7.21.5, pero el firmware del RouterBOARD seguía en 7.20.8. Hay que igualarlos: RouterOS y firmware deben coincidir para evitar comportamientos extraños.

Actualizar RouterOS (si hiciera falta)

System → Packages → Check For Updates → Download & Install
System → Reboot

Actualizar firmware del RouterBOARD

System → RouterBOARD → Upgrade → Confirmar
System → Reboot

Tras el reinicio, volver a System → RouterBOARD y comprobar:

Current Firmware:  7.21.5
Upgrade Firmware:  7.21.5
No saltes este paso. Un desajuste entre RouterOS y firmware es una fuente silenciosa de bugs. Si ambos no coinciden, no continúes con la Fase 3.

Segundo backup

Después de actualizar, hacer un nuevo backup y descargarlo:

Files → Backup → nombre: ax3-post-upgrade.backup

Fase 3 — Red de laboratorio aislada

El ax³ sale de fábrica con 192.168.88.1/24, exactamente la misma red que la red de producción. Para evitar cualquier confusión, lo movemos temporalmente a 192.168.50.0/24.

LAN laboratorio:  192.168.50.0/24
hAP ax³:          192.168.50.1
PC:               192.168.50.254
Truco clave: antes de cambiar la IP, conectar WinBox por MAC. Así, aunque se pierda la conectividad IP al cambiar la dirección, la sesión no se cae.

MAC del ax³ en este equipo:

D0:EA:11:DF:9B:80

Cambiar la IP LAN del ax³

  1. WinBox → IP → Addresses.
  2. Buscar 192.168.88.1/24.
  3. Editar.
  4. Cambiar a 192.168.50.1/24.
  5. Mantener la interfaz exactamente igual (probablemente bridge).
  6. Apply → OK.

WinBox puede perder momentáneamente la conexión IP. No cerrar la ventana.

Configurar el portátil

En Windows 10, configurar manualmente:

IP:             192.168.50.254
Máscara:        255.255.255.0
Puerta enlace:  (vacía)
DNS:            (vacío)

Reconectar WinBox por MAC y comprobar que el router sigue accesible.

Corregir el DHCP heredado de fábrica

El ax³ trae de fábrica una red DHCP en 192.168.88.0/24 que ya no tiene sentido. Hay que moverla a la nueva red del laboratorio.

IP → DHCP Server → Networks:

Address:  192.168.50.0/24
Gateway:  192.168.50.1
DNS:      192.168.50.1

IP → Pool, editar default-dhcp:

192.168.50.10-192.168.50.254

Comprobar en IP → DHCP Server → DHCP que el servidor DHCP está asociado al bridge y activo.

Estado al terminar la Fase 3: el ax³ vive en 192.168.50.0/24, el portátil tiene IP fija 192.168.50.254, y WinBox se conecta por MAC. Todavía no hay Internet, no hay firewall, no hay Wi-Fi configurado.

Fase 4 — Configuración base del hAP ax³

Con el laboratorio en marcha, ya se puede construir el router pieza a pieza. Todo esto se hace sin WAN, sin Internet, sin conexión al MitraStar. Es preparación pura.

Elementos a configurar

  • Contraseña del router (usuario admin o usuario nuevo).
  • Bridge LAN y asignación de puertos.
  • Servidor DHCP en 192.168.50.0/24.
  • Wi-Fi 6 (SSID, contraseña, canales, bandas 2.4 / 5 GHz).
  • Firewall básico (input, forward, NAT).
  • Estructura de interfaces: ether1 como WAN, resto en bridge LAN.
  • Listas de direcciones LAN y WAN para reglas de firewall.
  • Reglas de seguridad iniciales.
  • Backups periódicos.

Estructura recomendada de interfaces

ether1          → WAN  (sin bridge)
ether2..ether5  → LAN  (dentro del bridge)
wlan1 / wlan2   → LAN  (dentro del bridge)
No configurar todavía:
  • PPPoE en ether1.
  • VLAN 6 (el MitraStar en monopuesto entrega PPPoE sin etiquetar).
  • WireGuard / ProtonVPN.
  • Policy routing.
  • DNS definitivo (Pi-Hole / Unbound).
Todo eso es Parte 3.

Firewall básico

Reglas mínimas que deben quedar activas antes de la Parte 3:

input:
  - accept established,related
  - accept ICMP desde LAN
  - accept WinBox desde LAN
  - drop all from WAN
  - drop all invalid

forward:
  - accept established,related
  - accept LAN → WAN
  - drop all invalid

nat:
  - masquerade out-interface=ether1
Antes de tocar el firewall, activar Safe Mode:
/system safe-mode
Si se pierde la sesión por una regla mal puesta, RouterOS revierte los cambios automáticamente al reiniciar.

Backup tras la configuración base

Files → Backup → nombre: ax3-base-192.168.50.backup

Descargarlo al portátil. Guardarlo junto al resto de backups de la serie.

Reversión: el ax³ se queda inaccesible

Durante la Parte 2, la red de producción no corre ningún riesgo: el ax³ está aislado. El único escenario de reversión posible es perder el acceso al ax³ mientras se configura.

Buena noticia: RouterOS es muy difícil de dejar inaccesible si se siguen dos reglas: WinBox por MAC siempre disponible, y Safe Mode activado antes de tocar firewall o interfaces.

Si se pierde la sesión

  1. Conectar el portátil a un puerto LAN del ax³.
  2. WinBox → pestaña Neighbors.
  3. Conectar por MAC (D0:EA:11:DF:9B:80).
  4. Si la sesión se perdió por un cambio en firewall, RouterOS habrá revertido automáticamente al reiniciar (Safe Mode).
  5. Si no aparece por MAC, mantener pulsado el botón Reset durante el arranque para volver a configuración de fábrica y restaurar el último backup.
Restaurar un backup:
Files → seleccionar el .backup → Restore → Reboot
Y volver a aplicar la IP 192.168.50.1/24 si hiciera falta.

Qué viene en la Parte 3

Con el ax³ actualizado, en 192.168.50.1/24, con DHCP funcionando, Wi-Fi 6 configurado, firewall básico y backups en orden, la Parte 3 entra en el terreno delicado.

  • Fase 5 — Internet o2 y monopuesto: PPPoE, datos de conexión y notas del MitraStar GPT-2541GNAC.
  • Fase 6 — WireGuard con ProtonVPN, policy routing, kill switch y DNS con Pi-Hole + Unbound.
  • Fase 7 — Corte final: apagar el ac², migrar a 192.168.88.0/24 y pruebas de producción.
  • Bloque de reversión completo con los 5 casos, checklist y filosofía del proyecto.
Idea clave: al terminar la Parte 2, el ax³ está listo para entrar en producción, pero todavía no ha visto Internet. El único riesgo real empieza en la Parte 3, y es ahí donde el plan de reversión deja de ser teoría.
Serie: este artículo es la Parte 2 de Proyecto ax³. Viene de la Parte 1 — Qué cambia y por qué y continúa en la Parte 3 — Monopuesto, VPN y corte final.

Volver al índice de la serie · Cheatsheet RouterOS
FreeBSD es genial!.

Proyecto ax³ (1/3) — Qué cambia y por qué

Proyecto ax³ (1/3) — Qué cambia y por qué
Serie completa: Índice · Parte 1 · Parte 2 · Parte 3

Referencia de comandos: Cheatsheet RouterOS — Proyecto ax³

Introducción

Este es el primero de una serie de tres artículos en los que documento la sustitución del router principal de casa —un MikroTik hAP ac²— por un MikroTik hAP ax³, aprovechando la ocasión para reorganizar por completo la red: separar servicios, eliminar el doble NAT, integrar VPN por WireGuard con ProtonVPN y dejar el DNS en manos de Pi-Hole y Unbound.

La serie está pensada como una guía reproducible, no como un simple “cambio de router”. El hilo conductor es sencillo: nada se toca hasta que lo nuevo está probado. El hAP ac² permanece funcionando exactamente igual durante todo el proceso y solo se desconecta cuando el ax³ ya está listo para entrar en producción.

Objetivo

  • Sustituir el MikroTik hAP ac² por un hAP ax³.
  • Mantener el hAP ac² funcionando exactamente como ahora durante todo el proceso.
  • Preparar y probar el hAP ax³ aislado, inicialmente en 192.168.50.0/24.
  • Al final del proyecto:
    • o2/MitraStar en monopuesto.
    • El hAP ax³ establece PPPoE y recibe la IP pública.
    • LAN final: 192.168.88.0/24.
    • Sin doble NAT.
  • Redistribuir los servicios clave:
    • Router, NAT, firewall, DHCP y policy routing en el hAP ax³.
    • WireGuard + ProtonVPN en el hAP ax³.
    • DNS con Pi-Hole en Raspberry Pi y Unbound en FreeBSD.
    • NFSv4, Kerberos, ZFS y Samba en tormenta.
Estrategia general: el hAP ac² permanece intacto. El hAP ax³ se construye desde cero, en paralelo, sobre una red temporal aislada (192.168.50.0/24). Solo se produce el corte cuando todo está probado y hay un plan de reversión ensayado.

Comparativa hAP ac² vs hAP ax³

Antes de justificar la migración, conviene ver qué cambia realmente entre los dos equipos. La diferencia no es solo Wi-Fi 6: hay un salto generacional claro en CPU, RAM, almacenamiento y en la licencia de RouterOS.

Característica MikroTik hAP ac² MikroTik hAP ax³
Estándar Wi-Fi Wi-Fi 5 (802.11a/b/g/n/ac) Wi-Fi 6 (802.11a/b/g/n/ac/ax)
Velocidad inalámbrica AC1200 (300 + 867 Mbps) AX1800 (574 + 1200 Mbps)
Antenas Internas (2.5 dBi) Externas alta ganancia (3.3 / 5.5 dBi)
CPU IPQ-4018, 4 núcleos 716 MHz, 32-bit IPQ-6010, 4 núcleos hasta 1.8 GHz, 64-bit
RAM 128 MB 1 GB
Almacenamiento 16 MB Flash 128 MB NAND
Ethernet 5 × Gigabit 4 × Gigabit + 1 × 2.5 Gigabit
USB 1 × USB 2.0 tipo A 1 × USB 3.0 tipo A
PoE-out No Sí, en Ether1, Passive PoE
Licencia RouterOS Nivel 4 Nivel 6 (completa)
Diseño Compacto vertical / horizontal Sobremesa con antenas externas

Los puntos decisivos para este proyecto son tres: la CPU de 64 bits (necesaria para WireGuard y policy routing sin ahogos), la RAM de 1 GB (imprescindible si se manejan muchas reglas y listas) y la licencia RouterOS Nivel 6, que desbloquea funciones avanzadas que el ac² no tiene.

Arquitectura

Situación actual

Hoy todo depende del hAP ac², que hace de router, firewall, DHCP y punto de acceso. Detrás, en la misma red 192.168.88.0/24, conviven los equipos de casa: tormenta (FreeBSD 14.5, con Unbound, NFSv4, Kerberos, ZFS y Samba), solaris (también FreeBSD 14.5) y la Raspberry Pi con Pi-Hole.

INTERNET
   │
Router o2 (MitraStar GPT-2541GNAC)
   │
hAP ac²
   │
192.168.88.0/24
   │
   ├── tormenta        192.168.88.160   FreeBSD 14.5 (Unbound, NFSv4, Kerberos, ZFS, Samba)
   ├── solaris         192.168.88.51    FreeBSD 14.5
   ├── raspberry       192.168.88.244   Raspberry Pi 3B + Pi-Hole
   └── demás dispositivos

Situación final deseada

El MitraStar pasa a modo monopuesto: delega la conexión de Internet al router neutro mediante PPPoE y se queda únicamente gestionando la VoIP del teléfono fijo. El hAP ax³ pasa a ser el router real de la casa, con IP pública, firewall, NAT, WireGuard, ProtonVPN y policy routing. El DNS se delega en Pi-Hole y Unbound.

o2 / Internet
   │
Fibra óptica
   │
┌─────────────────────────┐
│ MitraStar GPT-2541GNAC  │
│ MONOPUESTO              │
│ SIN NAT                 │
│ Teléfono ─── VoIP       │
└────────────┬────────────┘
             │ Ethernet / PPPoE
             ▼
┌─────────────────────────┐
│ hAP ax³                 │
│ PPPoE + NAT + Firewall  │
│ WireGuard + ProtonVPN   │
│ Policy routing          │
└────────────┬────────────┘
             │
       192.168.88.0/24
             │
   ├── tormenta      192.168.88.160   FreeBSD 14.5 (Unbound, NFSv4, Kerberos, ZFS, Samba)
   ├── solaris       192.168.88.51    FreeBSD 14.5
   ├── raspberry     192.168.88.244   Raspberry Pi 3B + Pi-Hole
   └── demás dispositivos
Ventaja principal del monopuesto: el hAP ax³ recibe directamente la IP pública por PPPoE. Se elimina por completo el doble NAT entre el MitraStar y el router, lo que simplifica firewall, redirecciones de puertos, VPN entrante y diagnóstico de red.

Distribución de servicios

El reparto de responsabilidades es deliberado: el router se queda con lo que debe ser siempre del router (red, firewall, NAT, VPN), la Raspberry Pi se encarga del filtrado DNS con Pi-Hole, y tormenta se queda con lo que se beneficia de un sistema operativo completo (DNS recursivo con Unbound, almacenamiento, autenticación).

Servicio hAP ax³ tormenta
Router / NAT✅
Firewall✅
DHCP✅
Unbound❌✅
WireGuard✅
ProtonVPN✅
Policy routing✅
NFSv4
✅
Kerberos
✅
ZFS
✅
Samba
✅

Servicios adicionales que no viven en el hAP ax³ ni en tormenta:

Servicio Host IP Sistema
Pi-Hole raspberry.casa.lan 192.168.88.244 Raspberry Pi 3B

Inventario de la red:

  • tormenta.casa.lan → 192.168.88.160 — FreeBSD 14.5. Unbound, NFSv4, Kerberos, ZFS, Samba.
  • solaris.casa.lan → 192.168.88.51 — FreeBSD 14.5. Cliente de la red.
  • raspberry.casa.lan → 192.168.88.244 — Raspberry Pi 3B con Pi-Hole.
Cadena DNS prevista: los clientes consultan a Pi-Hole (raspberry.casa.lan), y Pi-Hole reenvía a Unbound (tormenta.casa.lan), que resuelve de forma recursiva. Así se combina el filtrado de Pi-Hole con la resolución recursiva de Unbound, sin depender de DNS externos.

Qué viene en la Parte 2

Con el objetivo y la arquitectura ya claros, la Parte 2 entra en materia: cómo preparar el hAP ax³ completamente aislado de la red actual, en 192.168.50.0/24, sin tocar nada del hAP ac² ni del MitraStar.

  • Primer contacto con el ax³: comprobaciones, RouterOS y firmware.
  • Red de laboratorio aislada en 192.168.50.0/24.
  • Acceso por MAC con WinBox para no perder la sesión.
  • Configuración base: bridge, DHCP, Wi-Fi 6, firewall y NAT.
Filosofía de la serie: el objetivo no es solo migrar, sino poder volver atrás en menos de 10 minutos si algo falla. Esa garantía es lo que convierte un cambio de router en un proyecto controlado.
Serie: este artículo es la Parte 1 de Proyecto ax³. Continúa en la Parte 2 — Preparar el ax³ sin tocar la red.

Volver al índice de la serie · Cheatsheet RouterOS
FreeBSD es genial!.

jueves, 8 de octubre de 2026

Por qué ipconfig /renew no cambia la IP en Windows 10 (y cómo forzarlo)

ipconfig /renew no cambia de subred por sí solo. Solo le pide al DHCP que le asigne una IP, pero:

  • Si la IP está configurada como estática, /release y /renew la ignoran.
  • Si el adaptador aún no detecta la nueva red (o hay un DHCP antiguo aún alcanzable), Windows renueva el mismo lease.
  • Windows asocia perfiles de red por la MAC del gateway; si cree que sigue en la misma red, mantiene la IP.
Escenario típico: el equipo conserva una IP de la red antigua (192.168.1.54) cuando debería estar en la nueva (192.168.88.0/24).

Paso 0 — Verificar si es DHCP o estática

Get-NetIPConfiguration
Get-NetIPAddress -AddressFamily IPv4
Get-NetAdapter

Si en PrefixOrigin aparece Manual, es IP estática: hay que quitarla antes de seguir.

Paso 1 — Quitar IP estática (si existe)

Sustituye "Ethernet" por el nombre real del adaptador:

Remove-NetIPAddress -InterfaceAlias "Ethernet" -Confirm:$false
Remove-NetRoute -InterfaceAlias "Ethernet" -Confirm:$false
Set-NetIPInterface -InterfaceAlias "Ethernet" -Dhcp Enabled
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ResetServerAddresses

Para Wi-Fi:

Remove-NetIPAddress -InterfaceAlias "Wi-Fi" -Confirm:$false
Remove-NetRoute -InterfaceAlias "Wi-Fi" -Confirm:$false
Set-NetIPInterface -InterfaceAlias "Wi-Fi" -Dhcp Enabled
Set-DnsClientServerAddress -InterfaceAlias "Wi-Fi" -ResetServerAddresses

Paso 2 — Liberar y limpiar cachés

ipconfig /release
ipconfig /flushdns
arp -d *
nbtstat -R

Paso 3 — Reiniciar el cliente DHCP (clave)

Este es el paso que casi siempre resuelve el problema. El servicio Dhcp mantiene el lease en memoria y, si no se reinicia, ipconfig /renew pide el mismo.
Restart-Service Dhcp -Force
Restart-Service Dnscache -Force

Paso 4 — Bajar y subir el adaptador

Disable-NetAdapter -Name "Ethernet" -Confirm:$false
Start-Sleep -Seconds 5
Enable-NetAdapter -Name "Ethernet" -Confirm:$false
Start-Sleep -Seconds 10
ipconfig /renew

Paso 5 — Borrar el lease en el registro

Windows guarda el último lease por adaptador. Si tras los pasos anteriores sigues viendo 192.168.1.54, hay que borrarlo a mano.

Haz un backup antes de tocar el registro. Este paso modifica claves de HKLM asociadas al adaptador.
Stop-Service Dhcp -Force

reg export "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces" "$env:USERPROFILE\Desktop\ifaces_backup.reg"

Identifica el GUID del adaptador:

Get-NetAdapter | Format-Table Name, InterfaceGuid, MacAddress

Y borra los valores DHCP cacheados:

$guid = "{TU-GUID-AQUI}"
Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\$guid" `
  -Name DhcpIPAddress,DhcpSubnetMask,DhcpDefaultGateway,DhcpNameServer,DhcpServer -ErrorAction SilentlyContinue

Start-Service Dhcp
ipconfig /renew

Paso 6 — Reset total de la pila TCP/IP (último recurso)

Esto reinicia toda la configuración de red del equipo. Usarlo solo si nada de lo anterior funciona.
netsh winsock reset
netsh int ip reset
netsh int ipv4 reset
netsh int ipv6 reset
Restart-Computer

Verificar el resultado

Get-NetIPConfiguration -InterfaceAlias "Ethernet" |
    Format-List InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer

Deberías ver una IP dentro de 192.168.88.0/24 y gateway 192.168.88.1.

Si aún no funciona: revisar la red

ComprobaciónQué buscar
Router 192.168.88.1DHCP activo y pool con direcciones libres
Otros DHCP en la redRouter viejo, AP en modo router, Windows con ICS
Puerto del switchQue no esté en una VLAN distinta a la del DHCP
802.1X / MAC filteringQue el puerto no esté rechazando el DHCP DISCOVER

Logs del cliente DHCP

Get-WinEvent -LogName "Microsoft-Windows-Dhcp-Client/Admin" -MaxEvents 20

Si en los eventos ves que sigue hablando con 192.168.1.1, el equipo aún ve la red antigua (VLAN mal, dos routers, o el AP en bridge con la red vieja).

Resumen práctico

Verificar que no sea IP estática → reiniciar servicio Dhcp → disable/enable del adaptador → si persiste, borrar los valores DHCP del registro para ese GUID y reiniciar.
En el 90% de los casos basta con reiniciar el servicio Dhcp y hacer un disable/enable del adaptador. El resto son casos de lease cacheado en registro o problemas en la propia red.
FreeBSD es genial!.

sábado, 3 de octubre de 2026

Backup Manual y Recuperación

FreeBSD 14.5

ZFS FreeBSD Copia de seguridad del servidor tormenta
ZFS FreeBSD Copia de seguridad del cliente solaris

Sistema: solaris y tormenta (FreeBSD 14.5)
Método: Backup manual a disco USB (Modelo B — USB guardado fuera)
Fecha: 2026-10-03

1. Introducción y filosofía

Este documento describe el sistema de backup manual a disco USB implementado en solaris y tormenta. Está diseñado para:

  • Ejecutarse manualmente cuando se conecta el disco USB.
  • Mantener los USB guardados fuera de las máquinas para protección ante ransomware y desastres locales.
  • Ser recuperable tanto para archivos individuales como para el sistema completo.
Filosofía del Modelo B: los USB no están conectados permanentemente. Se conectan solo cuando se va a hacer el backup, y después se guardan en otro lugar. Esto protege contra:
  • Ransomware que cifraría también el USB conectado.
  • Robo o incendio que afectaría a máquina y backup a la vez.
  • Errores humanos que borrarían el backup por accidente.

Estado del sistema

Elementosolaristormenta
Pool origenzrootzroot
Pool destino (USB)zbackupzbk
Dataset destinozbackup/recovery/solariszbk/tormenta
Etiqueta USBZFSBACKUPbackup1tb
Tamaño del pool origen~220 GB~312 GB
Script/root/bin/zfs-backup.sh/root/bin/zfs-backup.sh
Log/var/log/zfs-backup.log/var/log/zfs-backup.log
Retención origen7 snapshots7 snapshots
Retención destino30 snapshots30 snapshots

2. El script zfs-backup.sh

Script único que funciona en ambas máquinas, detectando automáticamente el hostname. Versión 2.4.

Ubicación

/root/bin/zfs-backup.sh

Contenido completo

#!/bin/sh
# zfs-backup.sh - Backup incremental de zroot a pool USB
# Versión: 2.4 (snapshot por dataset + export en error)
# Uso: sh /root/bin/zfs-backup.sh

set -e

# ========== CONFIGURACIÓN SEGÚN MÁQUINA ==========
HOSTNAME=$(hostname -s)
case "$HOSTNAME" in
    solaris)
        SRC_POOL="zroot"
        DST_POOL="zbackup"
        DST_DATASET="zbackup/recovery/solaris"
        USB_DEV="/dev/gpt/ZFSBACKUP"
        RETENTION_SRC=7
        RETENTION_DST=30
        ;;
    tormenta)
        SRC_POOL="zroot"
        DST_POOL="zbk"
        DST_DATASET="zbk/tormenta"
        USB_DEV="/dev/gpt/backup1tb"
        RETENTION_SRC=7
        RETENTION_DST=30
        ;;
    *)
        echo "Hostname no reconocido: $HOSTNAME" >&2
        exit 1
        ;;
esac

SNAP_PREFIX="snap"
SNAP_TODAY="${SNAP_PREFIX}-$(date +%Y%m%d)"
LOG="/var/log/zfs-backup.log"
LOCKFILE="/var/run/zfs-backup.lock"

# ========== VARIABLES DE ESTADO ==========
IMPORTED_BY_US=0

# ========== FUNCIONES ==========
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG"
}

die() {
    log "ERROR: $*"
    if [ "${IMPORTED_BY_US:-0}" -eq 1 ]; then
        log "Exportando pool $DST_POOL antes de salir..."
        zpool export "$DST_POOL" >> "$LOG" 2>&1 || log "Aviso: no se pudo exportar"
    fi
    rm -f "$LOCKFILE"
    exit 1
}

# ========== BLOQUEO ==========
if [ -f "$LOCKFILE" ]; then
    PID=$(cat "$LOCKFILE" 2>/dev/null)
    if kill -0 "$PID" 2>/dev/null; then
        echo "Ya hay una ejecución en curso (PID $PID)"
        exit 0
    fi
    rm -f "$LOCKFILE"
fi
echo $$ > "$LOCKFILE"

log "=========================================="
log "Iniciando backup en $HOSTNAME"
log "=========================================="

# ========== VERIFICAR POOL USB ==========
if ! zpool list "$DST_POOL" >/dev/null 2>&1; then
    log "Pool $DST_POOL no está importado. Intentando importar..."
    if [ ! -e "$USB_DEV" ]; then
        die "Disco USB $USB_DEV no encontrado. ¿Está conectado?"
    fi
    if ! zpool import "$DST_POOL" 2>>"$LOG"; then
        die "No se pudo importar el pool $DST_POOL"
    fi
    log "Pool $DST_POOL importado correctamente"
    IMPORTED_BY_US=1
else
    log "Pool $DST_POOL ya estaba importado"
    IMPORTED_BY_US=0
fi

# ========== CREAR SNAPSHOT DE HOY (dataset por dataset) ==========
log "Creando snapshot $SNAP_TODAY en todos los datasets (los que falten)..."

CREATED=0
SKIPPED=0
FAILED=0
for ds in $(zfs list -H -o name -r "$SRC_POOL" 2>/dev/null); do
    if zfs list -t snapshot "$ds@$SNAP_TODAY" >/dev/null 2>&1; then
        SKIPPED=$((SKIPPED + 1))
    else
        if zfs snapshot "$ds@$SNAP_TODAY" >> "$LOG" 2>&1; then
            CREATED=$((CREATED + 1))
        else
            log "  → error al crear $ds@$SNAP_TODAY"
            FAILED=$((FAILED + 1))
        fi
    fi
done
log "Snapshots: creados=$CREATED, ya existían=$SKIPPED, fallos=$FAILED"

if [ "$FAILED" -gt 0 ]; then
    log "AVISO: hubo $FAILED fallos al crear snapshots (se continúa)"
fi

# ========== DETECTAR ÚLTIMA SNAPSHOT EN DESTINO ==========
LAST_DST_SNAP=$(zfs list -t snapshot -H -o name -r "$DST_DATASET" 2>/dev/null \
    | grep '@snap-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' \
    | sort -r \
    | head -1 \
    | sed 's/.*@//')

if [ -z "$LAST_DST_SNAP" ]; then
    log "No hay snapshots previas en destino. Envío COMPLETO."
    zfs send -Rwcv "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío completo"

elif [ "$LAST_DST_SNAP" = "$SNAP_TODAY" ]; then
    log "Última snapshot en destino: $LAST_DST_SNAP"
    log "La snapshot $SNAP_TODAY ya está replicada. Nada que enviar."

elif ! zfs list -t snapshot "$SRC_POOL@$LAST_DST_SNAP" >/dev/null 2>&1; then
    log "AVISO: $LAST_DST_SNAP no existe en origen. Envío COMPLETO."
    zfs send -Rwcv "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío completo"

else
    log "Enviando incremental desde $LAST_DST_SNAP hasta $SNAP_TODAY"
    zfs send -Rwcv -i "$SRC_POOL@$LAST_DST_SNAP" "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío incremental"
fi

log "Envío completado correctamente"

# ========== FUNCIÓN DE RETENCIÓN ==========
apply_retention() {
    local root="$1"
    local label="$2"
    local ret="$3"

    log "Aplicando retención de $ret snapshots en $label..."

    zfs list -t snapshot -H -o name -r "$root" 2>/dev/null \
        | grep '@snap-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' \
        | sort -t@ -k1,1 -k2,2r \
        | awk -F@ -v r="$ret" '
            {
                ds = $1
                if (ds != prev_ds) { count = 0; prev_ds = ds }
                count++
                if (count > r) print $0
            }' \
        | while read snap; do
            log "Borrando $snap"
            zfs destroy "$snap" >> "$LOG" 2>&1 || log "  → error al borrar"
        done

    log "Retención en $label aplicada"
}

# ========== RETENCIÓN EN DESTINO (30 snapshots) ==========
apply_retention "$DST_DATASET" "destino" "$RETENTION_DST"

# ========== RETENCIÓN EN ORIGEN (7 snapshots) ==========
apply_retention "$SRC_POOL" "origen" "$RETENTION_SRC"

# ========== EXPORTAR POOL ==========
if [ "$IMPORTED_BY_US" -eq 1 ]; then
    log "Exportando pool $DST_POOL"
    zpool export "$DST_POOL" >> "$LOG" 2>&1 || log "Aviso: no se pudo exportar"
    log "Ya puedes desconectar el USB de forma segura"
fi

log "Backup completado con éxito"
log "=========================================="
rm -f "$LOCKFILE"

Características clave

ElementoDescripción
Detección automáticaUsa el hostname para elegir el pool y dataset correctos
Snapshot dataset por datasetEvita el fallo atómico de zfs snapshot -r
Detección de sincronizaciónSi ya está todo replicado, no envía nada
Incremental automáticoDetecta la última snapshot en destino y envía solo diferencias
Fallback a full sendSi no hay base común, hace envío completo automáticamente
Retención independiente7 snapshots en origen, 30 en destino
Export automáticoSi el script importó el USB, lo exporta al terminar
Logging completoTodo se registra en /var/log/zfs-backup.log
LockfileEvita ejecuciones simultáneas

3. Ejecución manual paso a paso

Cuándo ejecutar: semanalmente (recomendado domingo por la tarde), o siempre que haya cambios importantes que se quieran respaldar.

Paso 1 — Conectar el USB

Conectar el disco USB (ZFSBACKUP en solaris, backup1tb en tormenta) a la máquina correspondiente. Esperar unos segundos a que el sistema lo detecte.

ls -la /dev/gpt/ZFSBACKUP    # En solaris
ls -la /dev/gpt/backup1tb    # En tormenta

Debe aparecer el device node. Si no aparece, probar con otro puerto USB o revisar dmesg:

dmesg | tail -20

Paso 2 — Ejecutar el script

sh /root/bin/zfs-backup.sh
Importante: NO ejecutar el script si no se está seguro de que el USB está conectado. Si no lo está, el script fallará limpiamente sin tocar nada.

Paso 3 — Verificar el resultado

tail -30 /var/log/zfs-backup.log

Debe verse al final:

[XX:XX:XX] Backup completado con éxito
[XX:XX:XX] ==========================================

Paso 4 — Desconectar el USB

Si el script importó el pool, lo habrá exportado automáticamente. Se verá en el log:

[XX:XX:XX] Ya se puede desconectar el USB de forma segura

Verificar que el pool está exportado:

zpool list

El pool de backup (zbackup o zbk) no debe aparecer en la lista. Si aparece, exportarlo manualmente antes de desconectar:

zpool export zbackup    # En solaris
zpool export zbk        # En tormenta

sync

Paso 5 — Guardar el USB en lugar seguro

Una vez exportado y sincronizado, se puede retirar el cable USB y guardarlo donde corresponda (fuera de casa, caja fuerte, casa de un familiar, etc.).

¡Backup completado! El proceso completo tarda típicamente entre 1 y 15 minutos dependiendo de cuántos datos hayan cambiado desde el último backup.

4. Interpretación del log

Ejemplo de ejecución exitosa (con cambios)

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup no está importado. Intentando importar...
[2026-10-03 18:30:02] Pool zbackup importado correctamente
[2026-10-03 18:30:02] Creando snapshot snap-20261003 en todos los datasets (los que falten)...
[2026-10-03 18:30:02] Snapshots: creados=18, ya existían=0, fallos=0
[2026-10-03 18:30:03] Última snapshot en destino: snap-20261002
[2026-10-03 18:30:03] Enviando incremental desde snap-20261002 hasta snap-20261003
[2026-10-03 18:32:15] Envío completado correctamente
[2026-10-03 18:32:15] Aplicando retención de 30 snapshots en destino...
[2026-10-03 18:32:15] Retención en destino aplicada
[2026-10-03 18:32:15] Aplicando retención de 7 snapshots en origen...
[2026-10-03 18:32:15] Retención en origen aplicada
[2026-10-03 18:32:15] Exportando pool zbackup
[2026-10-03 18:32:16] Ya puedes desconectar el USB de forma segura
[2026-10-03 18:32:16] Backup completado con éxito
[2026-10-03 18:32:16] ==========================================

Ejemplo de ejecución sin cambios

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup ya estaba importado
[2026-10-03 18:30:00] Creando snapshot snap-20261003 en todos los datasets (los que falten)...
[2026-10-03 18:30:00] Snapshots: creados=18, ya existían=0, fallos=0
[2026-10-03 18:30:00] Última snapshot en destino: snap-20261003
[2026-10-03 18:30:00] La snapshot snap-20261003 ya está replicada. Nada que enviar.
[2026-10-03 18:30:00] Envío completado correctamente
[2026-10-03 18:30:00] Aplicando retención de 30 snapshots en destino...
[2026-10-03 18:30:00] Retención en destino aplicada
[2026-10-03 18:30:00] Aplicando retención de 7 snapshots en origen...
[2026-10-03 18:30:00] Retención en origen aplicada
[2026-10-03 18:30:00] Backup completado con éxito
[2026-10-03 18:30:00] ==========================================

Ejemplo de error (USB no conectado)

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup no está importado. Intentando importar...
[2026-10-03 18:30:00] ERROR: Disco USB /dev/gpt/ZFSBACKUP no encontrado. ¿Está conectado?
Este error es normal si se ejecuta el script sin el USB conectado. No corrompe nada. Simplemente conectar el USB y volver a ejecutar.

5. Política de retención

El script aplica automáticamente dos políticas distintas:

UbicaciónSnapshots conservadosRazón
Origen (zroot)7Liberar espacio en el NVMe. Solo se necesitan los últimos días para incrementales.
Destino (USB)30Histórico más largo. El USB tiene más espacio y es el "archivo".

Ajustar la retención

Si se quieren cambiar los valores, editar el script:

ee /root/bin/zfs-backup.sh

Buscar las líneas:

RETENTION_SRC=7
RETENTION_DST=30

Y modifícalas a los valores se preferencia. Por ejemplo, para guardar más histórico en el USB:

RETENTION_SRC=7
RETENTION_DST=60
Espacio: cada snapshot diaria ocupa entre 50 MB y varios GB según lo que cambie. Con 30 snapshots en destino, asegurarse de que el USB tiene espacio suficiente (consultar con zpool list).

6. Recuperación de archivos individuales

Escenario: se ha borrado un archivo por error o se quiere recuperar una versión anterior de algo.

Paso 1 — Conectar el USB y localizar el snapshot

# Conectar el USB de backup
zpool import zbackup        # En solaris
zpool import zbk            # En tormenta

# Ver snapshots disponibles
zfs list -t snapshot -r zbackup/recovery/solaris | grep 'snap-2026'

Paso 2 — Montar el snapshot en un punto temporal

mkdir -p /mnt/snap
mount -t zfs zbackup/recovery/solaris/home/carlos@snap-20261002 /mnt/snap

Ahora /mnt/snap contiene el contenido de /home/carlos tal como estaba en esa fecha.

Paso 3 — Buscar y copiar el archivo

# Ver qué hay
ls -la /mnt/snap/

# Copiar el archivo deseado
cp /mnt/snap/documento.txt /home/carlos/documento_recuperado.txt

Paso 4 — Desmontar y exportar

umount /mnt/snap
rmdir /mnt/snap

zpool export zbackup        # En solaris
zpool export zbk            # En tormenta

sync
Ventaja sobre el método .gz: con el backup ZFS solo montas el snapshot y accedes a los archivos directamente. No hay que descomprimir 300 GB para sacar un documento.

7. Recuperación completa del sistema

Escenario: el NVMe del sistema ha fallado o necesitas reinstalar FreeBSD desde cero.

ATENCIÓN: Este procedimiento borra todo el contenido del disco actual. Asegurarse de tener el backup antes de empezar.

Paso 1 — Arrancar desde USB de FreeBSD

Insertar el USB de instalación, arrancar la máquina desde él, y elegir "Shell" en lugar de instalar.

Paso 2 — Identificar discos

geom disk list
camcontrol devlist

Paso 3 — Preparar el disco destino

gpart destroy -F nda0
gpart create -s gpt nda0
gpart add -t efi -a 1m -s 260m -l EFI nda0
gpart add -t freebsd-boot -a 1m -s 512k -l BOOT nda0
gpart add -t freebsd-swap -a 1m -s 16g -l SWAP nda0
gpart add -t freebsd-zfs -a 1m -l ZFS nda0
newfs_msdos -F 32 -c 1 /dev/nda0p1

Paso 4 — Crear el pool zroot

zpool create -o ashift=12 \
             -O compression=lz4 \
             -O atime=off \
             -O mountpoint=none \
             -R /mnt \
             zroot /dev/gpt/ZFS

Paso 5 — Importar el USB de backup

zpool import zbackup        # En solaris
zpool import zbk            # En tormenta

Paso 6 — Restaurar el sistema

zfs send -Rwcv zbackup/recovery/solaris@snap-20261003 \
    | zfs receive -Fduv zroot

Paso 7 — Configurar el bootfs

zpool set bootfs=zroot/ROOT/default zroot
zpool get bootfs zroot

Paso 8 — Copiar el cargador UEFI

mkdir -p /mnt2
mount_msdosfs /dev/nda0p1 /mnt2
mkdir -p /mnt2/efi/boot
cp /mnt/zroot/ROOT/default/boot/loader.efi /mnt2/efi/boot/bootx64.efi
umount /mnt2
rmdir /mnt2

Paso 9 — Ajustar propiedades de montaje

zfs set mountpoint=/ zroot/ROOT/default
zfs set mountpoint=/home zroot/home
zfs set mountpoint=/usr zroot/usr
zfs set mountpoint=/var zroot/var
zfs set mountpoint=/tmp zroot/tmp

zpool set altroot= zroot
zpool set cachefile=/boot/zfs/zpool.cache zroot

Paso 10 — Exportar y reiniciar

zpool export zbackup
zpool export zbk

reboot

Paso 11 — Verificar

freebsd-version
zpool status zroot
zfs list -r zroot | head -20

8. Recuperación del dataset cifrado

El dataset zroot/nfsv4/secifrado en tormenta está cifrado con ZFS native encryption.

Guardar la clave en al menos 3 sitios distintos:
  • Gestor de contraseñas (Bitwarden, KeePass, etc.).
  • Papel en caja fuerte.
  • USB de emergencia separado del USB de backup.

Ver el contenido de la clave

base64 /etc/zfs/secifrado.key

Restaurar la clave

echo 'TU_CLAVE_EN_BASE64' | base64 -d > /etc/zfs/secifrado.key
chmod 400 /etc/zfs/secifrado.key
chown root:wheel /etc/zfs/secifrado.key
ls -la /etc/zfs/secifrado.key

Montar el dataset cifrado

zfs mount zroot/nfsv4/secifrado
ls -la /nfsv4/secifrado/
Recomendación: una vez al año, haz una prueba real de recuperación del dataset cifrado en una máquina de prueba.

9. Checklist y rutinas

Rutina semanal (domingo)

  • [ ] Conectar USB ZFSBACKUP a solaris
  • [ ] Ejecutar sh /root/bin/zfs-backup.sh
  • [ ] Verificar log: tail -20 /var/log/zfs-backup.log
  • [ ] Confirmar "Backup completado con éxito"
  • [ ] Desconectar USB y guardarlo en lugar seguro
  • [ ] Repetir con USB backup1tb en tormenta

Rutina mensual

  • [ ] Verificar snapshots recientes en los USB
  • [ ] Comprobar espacio disponible: zpool list
  • [ ] Revisar el log en busca de errores: grep "ERROR" /var/log/zfs-backup.log

Rutina semestral

  • [ ] Prueba de restauración de un archivo aleatorio.
  • [ ] Verificar integridad del pool USB: zpool scrub zbackup
  • [ ] Comprobar que las claves de cifrado siguen accesibles.

Apéndice A — Comandos útiles

Ver estado de los pools

zpool list
zpool status
zpool status -v

Ver snapshots

# Todos los snapshots del pool
zfs list -t snapshot -r zroot

# Solo los snapshots diarios (formato snap-YYYYMMDD)
zfs list -t snapshot -r zroot | grep 'snap-2026'

# Contar snapshots por dataset
zfs list -t snapshot -r zroot | awk -F@ '{print $1}' | sort | uniq -c

Comprobar integridad

zpool scrub zroot
zpool scrub zbackup
zpool status

Ver procesos de backup en curso

ps aux | grep -E "zfs (send|receive)" | grep -v grep
tmux ls

Reconectar a una sesión tmux

tmux attach -t backup_usb

Apéndice B — Solución de problemas

Error: "Pool zbackup no está importado"

ls -la /dev/gpt/ZFSBACKUP
zpool import zbackup
sh /root/bin/zfs-backup.sh

Error: "cannot create snapshot ... dataset already exists"

Causa: alguno de los datasets ya tiene la snapshot de hoy. La versión 2.4 del script ya maneja esto dataset por dataset.

Error: "cannot send ... encrypted dataset"

Causa: falta el flag -w en zfs send.

Solución: usar -Rwcv en lugar de -Rcv.

El USB no se puede exportar (pool is busy)

lsof | grep zbackup
fuser -m /zbackup

zfs unmount -a
zpool export -f zbackup

Backup incompleto o corrupto

zpool scrub zbackup
zpool status zbackup

Apéndice C — Glosario

TérminoSignificado
PoolConjunto de discos gestionados por ZFS como una unidad
DatasetSistema de archivos dentro de un pool
SnapshotImagen inmutable de un dataset en un momento concreto
Full sendEnvío completo de un dataset a otro pool
Incremental sendEnvío solo de los cambios desde una snapshot base
RetenciónNúmero de snapshots que se conservan antes de borrar las más antiguas
ashiftTamaño de sector usado por ZFS (12 = 4096 bytes)
-w (raw)Envío de bloques cifrados sin descifrar
BEBoot Environment — entorno de arranque de FreeBSD
tmux

Multiplexor de terminal (permite sesiones persistentes)

 

FreeBSD es genial!.