Páginas

Mostrando entradas con la etiqueta Seguridad. Mostrar todas las entradas
Mostrando entradas con la etiqueta Seguridad. Mostrar todas las entradas

miércoles, 18 de marzo de 2026

FileBrowser con Tailscale HTTPS Habilitado en FreeBSD 14.3

Fuente:

https://tailscale.com/docs/reference/examples/serve
https://tailscale.com/docs/how-to/quickstart
https://tailscale.com/docs/features/access-control
https://filebrowser.org/cli/filebrowser-config-init.html
https://filebrowser.org/cli/filebrowser-users-add.html

Instalar FileBrowser

pkg install filebrowser
which filebrowser
filebrowser version
File Browser v2.52.0/c11c986b7382a5c1f18d83ee7e6093dc0544cff9

Crear esttructura de directorios


Directorio para archivos compartidos

mkdir -p /home/carlos/fileserver

Directorio para configuracion

mkdir -p /home/carlos/.config/filebrowser

Iniciarlizar la base de datos de FileBrowser

filebrowser config init -d /home/carlos/.config/filebrowser/filebrowser.db

Crear usuario administrador

filebrowser users add carlos tu_contraseña_segura \
  --perm.admin \
  --perm.create \
  --perm.delete \
  --perm.download \
  --perm.execute \
  --perm.modify \
  --perm.rename \
  --perm.share \
  -d /home/carlos/.config/filebrowser/filebrowser.db

Explicación de permisos:

--perm.admin → Acceso administrativo completo
--perm.create → Crear archivos y carpetas
--perm.delete → Eliminar archivos
--perm.download → Descargar archivos
--perm.execute → Ejecutar comandos
--perm.modify → Modificar archivos
--perm.rename → Renombrar archivos/carpetas
--perm.share → Compartir enlaces públicos

Crear usuario adicional con permisos limitados


Detener completamente filebrowser

sudo service FileBrowser stop  
sudo pkill -9 filebrowser
filebrowser users add invitado password123 \
  --perm.download \
  --scope /home/carlos/fileserver/publico \
  -d /home/carlos/.config/filebrowser/filebrowser.db
 

Comprobar configuracion

 filebrowser config cat -d /home/carlos/.config/filebrowser/filebrowser.db
 

Ver usuarios

  
  filebrowser users ls -d /home/carlos/.config/filebrowser/filebrowser.db
  

Crear archivo /home/carlos/.config/filebrowser/config.json

  {
  "port": 8080,
  "baseURL": "",
  "address": "0.0.0.0",
  "log": "/home/carlos/.config/filebrowser/filebrowser.log",
  "database": "/home/carlos/.config/filebrowser/filebrowser.db",
  "root": "/home/carlos/fileserver"
}

Crear script de servicio rc.d sudo vim /usr/local/etc/rc.d/filebrowser

#!/bin/sh
# PROVIDE: filebrowser
# REQUIRE: NETWORKING DAEMON tailscaled
# KEYWORD: shutdown

. /etc/rc.subr

name="filebrowser"
desc="Web File Browser"
rcvar="${name}_enable"

load_rc_config $name

: ${filebrowser_enable:="NO"}
: ${filebrowser_runas:="carlos"}
: ${filebrowser_config:="/home/carlos/.config/filebrowser/config.json"}

procname="/usr/local/bin/${name}"
command="/usr/sbin/daemon"

command_args="-c -u ${filebrowser_runas} -t \"${desc}\" \
    ${procname} -c ${filebrowser_config}"

start_precmd="filebrowser_prestart"

filebrowser_prestart()
{
    log_file="/home/carlos/.config/filebrowser/filebrowser.log"
    if [ ! -f "${log_file}" ]; then
        touch "${log_file}"
        chown ${filebrowser_runas} "${log_file}"
        chmod 640 "${log_file}"
    fi
}

run_rc_command "$1"

Permisos correctos

sudo chmod 555 /usr/local/etc/rc.d/filebrowser

Habilitar FileBrowser en rc.conf

sudo sysrc filebrowser_enable="YES"

Comprobar

sudo service filebrowser status
filebrowser is running as pid 1918.
ls -ld /var/run/filebrowser
drwxr-xr-x  2 carlos wheel 3 Apr  3 09:21 /var/run/filebrowser
sudo cat /var/run/filebrowser/filebrowser.pid
1918
tail -10 /home/carlos/.config/filebrowser/filebrowser.log 
2026/04/02 23:57:05 Listening on [::]:8080
2026/04/03 08:40:10 Got signal: terminated
2026/04/03 08:40:10 Stopped serving new connections.
2026/04/03 08:40:10 Graceful shutdown complete.
2026/04/03 08:41:06 Listening on [::]:8080
2026/04/03 08:46:48 Got signal: terminated
2026/04/03 08:46:48 Stopped serving new connections.
2026/04/03 08:46:48 Graceful shutdown complete.
2026/04/03 08:47:40 Listening on [::]:8080
2026/04/03 09:21:27 Listening on [::]:8080

Verificar Tailscale

tailscale status
100.69.99.114  tornado  nombreusuario@  freebsd  - 

Si no está corriendo

sudo service tailscaled start
tailscale up

Recomendación de mantenimiento


Nunca vuelva a ejecutar tailscale up sin --hostname o sin haber hecho tailscale logout antes. Uso correcto:

tailscale logout
tailscale up --hostname=tornado

Actualizar reglas de PF

# ========================================
# Configuración PF para tornado.local.com
# ========================================

# MACROS (Variables)
ext_if = "wlan0"                      # Interfaz de red
tailscale_if = "tailscale0"
local_net = "192.168.88.0/24"         # Red local permitida
ssh_port = "22"                       # Puerto SSH
filebrowser_port = "8080"
filebrowser_https_port = "8443"
http_port = "80"
https_port = "443"

# --- OPCIONES ---
set skip on lo0                       # No filtrar loopback
set block-policy drop                 # Descartar paquetes bloqueados silenciosamente
set loginterface $ext_if              # Interfaz para estadísticas

# --- SCRUB (Normalización de paquetes) ---
scrub in all                          # Normalizar todo el tráfico entrante

# --- POLÍTICA PREDETERMINADA ---
block all                             # Bloquear todo por defecto

# --- REGLAS ANTISPOOF ---
antispoof quick for $ext_if           # Protección contra IP spoofing

# --- PERMITIR LOOPBACK ---
pass quick on lo0 all                 # Permitir todo en loopback

# --- PERMITIR TRÁFICO EN TAILSCALE ---
pass quick on $tailscale_if all keep state

# --- Solo permite TAILSCALE ---
pass in quick on $tailscale_if all keep state

# --- PERMITIR ICMP (ping) desde red local ---
pass in quick on $ext_if inet proto icmp from $local_net to any icmp-type { echoreq } keep state

# --- PERMITIR SSH SOLO DESDE RED LOCAL ---
pass in quick on $ext_if proto tcp from $local_net to ($ext_if) port $ssh_port keep state

# --- PERMITIR FILEBROWSER HTTP DESDE RED LOCAL ---
pass in quick on $ext_if proto tcp from $local_net to ($ext_if) port $filebrowser_port keep state

# --- PERMITIR FILEBROWSER HTTP DESDE TAILSCALE ---
pass in quick on $tailscale_if proto tcp to any port $filebrowser_port keep state

# --- PERMITIR FILEBROWSER HTTPS DESDE RED LOCAL ---
pass in quick on $ext_if proto tcp from $local_net to ($ext_if) port $filebrowser_https_port keep state

# --- PERMITIR FILEBROWSER HTTPS DESDE TAILSCALE ---
pass in quick on $tailscale_if proto tcp to any port $filebrowser_https_port keep state

# --- PERMITIR TRÁFICO SALIENTE ---
pass out quick on $ext_if all keep state

# --- LOGGING (opcional) ---
# pass in log on $ext_if proto tcp from $local_net to ($ext_if) port $ssh_port keep state

Recargar reglas

sudo pfctl -f /etc/pf.conf
sudo service pf reload

Iniciar filebrowser

sudo service filebrowser start

Estado de filebrowser

sudo service filebrowser status
Password:
filebrowser is running as pid 4721

Puerto de escucha

sudo sockstat -4l | grep 8080
carlos   filebrowse  1322 5   tcp46  *:8080

Acceder a FileBrowser


Desde la red local:

http://192.168.88.183:8080

Desde Tailscale HTTPS (desde cualquier lugar):

https://100.69.99.114:443
https://tornado.tail0788a4.ts.net

Credenciales

Usuario carlos
Contraseña tu_contraseña_segura

Ver logs de diagnóstico

tail -f /home/carlos/.config/filebrowser/filebrowser.log

Proceso filebrowser

 
ps aux | grep filebrowser    
carlos     5542   0.0  0.4 1270900 30200  -  I    23:57 \
0:05.52 /usr/local/bin/filebrowser -c /home/carlos/.config/filebrowser/config.json

Reglas PF activas

sudo pfctl -sr 
Password:
scrub in all fragment reassemble
block drop all
block drop in quick on ! wlan0 inet from 192.168.88.0/24 to any
block drop in quick inet from 192.168.88.183 to any
pass in quick on wlan0 inet proto tcp from 192.168.88.0/24 to \
(wlan0) port = ssh flags S/SA keep state
pass in quick on wlan0 inet proto tcp from 192.168.88.0/24 to \
(wlan0) port = http-alt flags S/SA keep state
pass in quick on wlan0 inet proto tcp from 192.168.88.0/24 to \
(wlan0) port = 8443 flags S/SA keep state
pass in quick on wlan0 inet proto icmp from 192.168.88.0/24 to \
any icmp-type echoreq keep state
pass out quick on wlan0 all flags S/SA keep state
pass quick on lo0 all flags S/SA keep state
pass quick on tailscale0 all flags S/SA keep state

IMPORTANTE: Detener FileBrowser antes de modificar la base de datos

sudo service filebrowser stop
sudo pkill -9 filebrowser

Cambiar contraseña de usuario

filebrowser users update carlos \
  --password nueva_contraseña \
  -d /home/carlos/.config/filebrowser/filebrowser.db

Habilitar branding personalizado

filebrowser config set \
  --branding.name "Servidor de Carlos" \
  --branding.disableExternal \
  -d /home/carlos/.config/filebrowser/filebrowser.db
  

Cambiar a tema oscuro por defecto

filebrowser config set \
  --theme dark \
  -d /home/carlos/.config/filebrowser/filebrowser.db
  

Reiniciar FileBrowser

sudo service filebrowser start  

Seguridad adicional


Deshabilitar registro público

filebrowser config set --signup false -d /home/carlos/.config/filebrowser/filebrowser.db
 

Configurar límite de sesión

filebrowser config set --auth.recaptcha.secret "" -d /home/carlos/.config/filebrowser/filebrowser.db

Copia de seguridad de configuración


Copia de seguridad de base de datos

cp /home/carlos/.config/filebrowser/filebrowser.db /home/carlos/.config/filebrowser/filebrowser.db.backup

Copia de seguridad de archivos

tar -czf /home/carlos/fileserver-backup-$(date +%Y%m%d).tar.gz /home/carlos/fileserver/

Resumen de comandos de gestión


Reiniciar servicio

sudo service filebrowser restart

Detener FileBrowser completamente

sudo service filebrowser stop
sudo pkill -9 filebrowser

Limpiar el pidfile

rm -f /var/run/filebrowser/filebrowser.pid

Iniciar FileBrowser limpiamente

sudo service filebrowser start 

Verificar que solo hay un proceso

sudo ps aux | grep "filebrowser"
carlos   1322  0.0  0.4 1279096 29736 v0- I   Sun23  1:11.45 \
/usr/local/bin/filebrowser -c /home/carlos/.config/filebrowser/config.json

Ver logs en tiempo real

tail -f /home/carlos/.config/filebrowser/filebrowser.log

Listar usuarios. Hay que detener FileBrowser antes

sudo service filebrowser stop
sudo pkill -9  filebrowser
filebrowser users ls -d /home/carlos/.config/filebrowser/filebrowser.db

Ver configuración completa

filebrowser config cat -d /home/carlos/.config/filebrowser/filebrowser.db

Navegador local

http://localhost:8080

Red local

http://192.168.88.183:8080

Acceso remoto desde Internet (con Tailscale conectado) Sin Tailscale no funcionará (esto es correcto por seguridad).

http://100.69.99.114:8080
https://https://tornado.tail0788a4.ts.net

Configuración completada exitosamente: FileBrowser instalado y configurando Autenticación habilitada (usuario: carlos) Acceso desde red local (192.168.88.0/24) Acceso remoto seguro vía Tailscale Firewall PF configurado correctamente Autoarranque habilitado (rc.conf)

Tailscale HTTPS (certificados automáticos de Tailscale)

Tailscale puede proporcionar certificados HTTPS válidos de forma automática para un nodo.

Esto generará certificados en /var/lib/tailscale/certs/ o /usr/local/tailscale/certs/. Si no existe el directorio, Tailscale los colocará en el directorio actual.

Obtener el nombre MagicDNS de su nodo

tailscale status

Desde cualquier dispositivo con Tailscale conectado

https://tornado.tail0788a4.ts.net

¡El certificado será válido y reconocido por todos los navegadores!

Usar Tailscale Serve (proxy HTTPS automático)

sudo tailscale serve --bg http://127.0.0.1:8080

Exponer FileBrowser con HTTPS automático en

https://tornado.tail0788a4.ts.net

No es necesario configurar nada más, Tailscale maneja todo el HTTPS

Comprobar

tailscale serve status
https://tornado.tail0788a4.ts.net (tailnet only)
|-- / proxy http://127.0.0.1:8080

Obtener su URL completa

tailscale status --json | grep tornado    
    "DNSName": "tornado.tail0788a4.ts.net.",
    "tornado.tail0788a4.ts.net"

Hacer permanente la configuración

Para que Tailscale Serve se mantenga después de reiniciar:

Crear un servicio rc.d

sudo vim /usr/local/etc/rc.d/tailscale_serve

#!/bin/sh
# PROVIDE: tailscale_serve
# REQUIRE: tailscaled filebrowser
# KEYWORD: shutdown

. /etc/rc.subr

name="tailscale_serve"
rcvar="tailscale_serve_enable"

load_rc_config $name

: ${tailscale_serve_enable:="NO"}

start_cmd="${name}_start"
stop_cmd="${name}_stop"

tailscale_serve_start()
{
    echo "Starting Tailscale Serve..."
    /usr/local/bin/tailscale serve --bg http://127.0.0.1:8080
}

tailscale_serve_stop()
{
    echo "Stopping Tailscale Serve..."
    /usr/local/bin/tailscale serve reset
}

run_rc_command "$1"

Otorgar permisos

sudo chmod +x /usr/local/etc/rc.d/tailscale_serve

Habilitar tailscale_serve

sudo sysrc tailscale_serve_enable="YES"
sudo service tailscale_serve start

Habilitar HTTPS y Serve en Tailscale


Ir a esta URL desde el navegador:

https://login.tailscale.com/admin/machines

Encontrar su máquina (por ejemplo, "tornado")

Hacer clic en los 3 puntos -> "Enable HTTPS"

En la página que se abre: Marcar "HTTPS certificates" (requerido) NO marque "Funnel" (a menos que quiera acceso público desde Internet)

Nota: Serve = Acceso solo desde tu Tailnet (privado) - Esto es lo que quiere

Hacer clic en "Enable HTTPS and Serve" o "Enable"

Volver a configurar Serve

sudo tailscale serve --bg http://127.0.0.1:8080

Debería funcionar sin errores

Verificar serve

tailscale serve status 
https://tornado.tail0788a4.ts.net (tailnet only)
|-- / proxy http://127.0.0.1:8080

Desde cualquier dispositivo con Tailscale

https://tornado.tail0788a4.ts.net

Cuando habilita HTTPS en Tailscale, el nombre de su dispositivo (tornado.tail0788a4.ts.net) se escribirá en un Certificate Transparency Log público. Esto es un requisito de Let's Encrypt y no se puede evitar. Esto NO expone:

Su IP
Sus archivos
El contenido de tu servidor

Solo registra:

El nombre del dispositivo (tornado.tail0788a4.ts.net)

Comprobar que MagicDNS está habilitado

sudo tailscale status --json | grep -i magic
    "InMagicSock": false,
  "MagicDNSSuffix": "tail0788a4.ts.net",
    "MagicDNSSuffix": "tail0788a4.ts.net",
    "MagicDNSEnabled": true
      "InMagicSock": true,
      "InMagicSock": true,
      "InMagicSock": true,
      "InMagicSock": true,

FileBrowser no arranca


Limpiar procesos

sudo pkill -9 filebrowser
rm -f /var/run/filebrowser/filebrowser.pid

Ver error exacto

filebrowser -c /home/carlos/.config/filebrowser/config.json
2026/03/27 09:17:02 Using config file: /home/carlos/.config/filebrowser/config.json
2026/03/27 09:17:02 Using database: /home/carlos/.config/filebrowser/filebrowser.db

Ver logs

  tail -50 /home/carlos/.config/filebrowser/filebrowser.log

Iniciar filebrowser manualmente

filebrowser -c /home/carlos/.config/filebrowser/config.json &

Configuración final completada

Elemento		  Valor
URL de acceso		  https://tornado.tail0788a4.ts.net
Certificado SSL 	  Let's Encrypt (válido, sin advertencias)
FileBrowser		  HTTP en localhost:8080
Tailscale Serve		  HTTPS proxy en puerto 443
Acceso			  Solo desde su Tailnet (privado)
Usuario			  carlos
Usuario no privilegiado	  invitado
https://gnulinuxcodigo.blogspot.com/2026/04/crear-rotacion-de-logs-filebrowser.html

FreeBSD es genial!.

lunes, 19 de enero de 2026

Crear conjunto de datos cifrado ZFS NFSv4 (tls)

Conjunto de datos cifrado

=> Cifrado NFS sobre TLS <=

En el servidor (tormenta.local.com)

Crear el keyfile para cifrado automático

Generar un keyfile seguro de 32 bytes (requerido para keyformat=raw):

dd if=/dev/urandom of=/etc/zfs/secifrado.key bs=32 count=1
chmod 400 /etc/zfs/secifrado.key

Este archivo contiene la clave binaria. Respaldar en un lugar seguro, su pérdida implica perder permanentemente el acceso al dataset.

Creación del dataset padre ZFS (no cifrado)

zfs create -o mountpoint=/nfsv4 zroot/nfsv4

A continuación crear el dataset hijo cifrado

zfs create -o encryption=aes-256-gcm -o \
keyformat=raw -o keylocation=file:///etc/zfs/secifrado.key -o \
mountpoint=/nfsv4/secifrado zroot/nfsv4/secifrado

Utiliza AES-256-GCM (recomendado por seguridad y rendimiento). El comando cargará la clave automáticamente durante la creación.

Verificar con el comando siguiente

zfs get encryption,keyformat,keylocation,mountpoint zroot/nfsv4/secifrado
NAME                   PROPERTY     VALUE                          SOURCE
zroot/nfsv4/secifrado  encryption   aes-256-gcm                    -
zroot/nfsv4/secifrado  keyformat    raw                            -
zroot/nfsv4/secifrado  keylocation  file:///etc/zfs/secifrado.key  local
zroot/nfsv4/secifrado  mountpoint   /nfsv4/secifrado               local

Configurar el desbloqueo automático en el arranque

Script rc.d personalizado que cargará la clave y montará el dataset después de importar los pools ZFS, pero antes de iniciar los servicios NFS (evita la intervención manual)

vim /usr/local/etc/rc.d/zfskeys
#############################################################
#!/bin/sh

# PROVIDE: zfskeys
# REQUIRE: zfs
# BEFORE: mountd
# KEYWORD: 

. /etc/rc.subr

name=zfskeys
rcvar=zfskeys_enable
start_cmd="${name}_start"

zfskeys_start() {
    zfs load-key zroot/nfsv4/secifrado
    zfs mount -a  # Montar cualquier dataset despues de cargar la clave
}

load_rc_config $name
run_rc_command "$1"
#############################################################

Convertir el archivo en ejecutable y habilitarlo

chmod +x /usr/local/etc/rc.d/zfskeys
sysrc zfskeys_enable="YES"

Esto permite que la clave se cargue desde el keyfile automáticamente al arranque, asumiendo que zroot raíz no está cifrado y el keyfile es accesible al inicio.

En caso de que zroot esté cifrado, ajustar el keyfile a un dataset no cifrado.

Archivo /etc/exports

#############################################################
V4: /nfsv4 -tls
---
/nfsv4/docs 	    -maproot=root -network 192.168.88.0/24
/nfsv4/secifrado    -maproot=root 192.168.88.51
---
#############################################################

Recargar configuración y reiniciar servicios

service mountd reload
service nfsd restart
service tlsservd restart

En el cliente (solaris.local.com)

service tlsclntd restart

Montar el recurso compartido NFSv4 con tls

mkdir /nizs4
mount -t nfs -o nfsv4,tls tormenta:/secifrado /nizs4

Montaje automático agregar en /etc/fstab

tormenta:/secifrado  /nizs4   nfs   rw,nfsv4,tls,noatime,bg   0  0

Seguridad: El keyfile permite desbloqueo sin intervención, mejor proteger (permisos 400, backups). Si el servidor es sustraido, el keyfile en disco permite acceso, considera almacenarlo en un dispositivo externo removible.

Reiniciar el servidor, comprobar que el dataset está montado y accesible via NFS desde el cliente.

Si TLS falla, comprobar logs (dmesg | grep tls, /var/log/messages). Verificar que los puertos NFS (2049/TCP) están abiertos en el firewall PF. Para depuración usar mount -vv

zfs mount | grep "secifrado" 
nfsstat -m
---
tormenta:/secifrado on /nizs4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,\
acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,\
wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,\
retrans=2147483647
---

Archivo /etc/exports

V4: /nfsv4 -tls
...
/nfsv4/secifrado     -maproot=root 192.168.88.51
FreeBSD es genial!.

martes, 16 de diciembre de 2025

Cifrado por Envoltorio (túnel) del tráfico NFSv4 con Wireguard FreeBSD 14.3

Implementar cifrado por envoltorio (Wireguard) y proteger conexiones NFS entre un servidor y su(s) cliente(s).

Objetivos:

NFSv4 puro y limpio (solo puerto 2049).
Acceso exclusivo a través del túnel WireGuard (cifrado punto a punto).
Imposible acceder a los recursos desde la LAN física (bloqueado por PF).
Montajes persistentes y estables en el cliente.
Todo seguro, mínimo y sin componentes innecesarios corriendo.

Cómo implementar el cifrado por envoltorio: WireGuard

El servidor NFSv4 corre FreeBSD 14.3 ZFS, red 192.168.88.0/24, dominio local.com, nombre de host tormenta.local.com, dirección IP 192.168.88.160, interfaz re0, cortafuegos PF.

El cliente es un portátil con sistema operativo FreeBSD 14.3 ZFS, dirección IP 192.168.88.51, nombre de host solaris.local.com, interfaz de red em0. El archivo /etc/exports actual

V4: /nfsv4 -tls
/nfsv4/dellhome     -maproot=root -network 192.168.88.0/24 
/nfsv4/poolrecovery -maproot=root -network 192.168.88.0/24 
/nfsv4/docs         -maproot=root -network 192.168.88.0/24 
/nfsv4/confsolaris  -maproot=root -network 192.168.88.0/24 
/nfsv4/conftormenta -maproot=root -network 192.168.88.0/24
root@tormenta:~ # zfs list | grep /nfsv4 
zroot/nfsv4 103G 212G 7.80G /nfsv4 
zroot/nfsv4/confsolaris 283M 212G 4.76M /nfsv4/confsolaris 
zroot/nfsv4/conftormenta 916K 212G 852K /nfsv4/conftormenta 
zroot/nfsv4/dellhome 56.6G 212G 56.6G /nfsv4/dellhome 
zroot/nfsv4/docs 7.80G 212G 7.80G /nfsv4/docs 
zroot/nfsv4/poolrecovery 1.88G 212G 1.88G /nfsv4/poolrecovery 

La idea es crear un túnel VPN punto a punto entre el servidor (tormenta.local.com, 192.168.88.160) y el cliente (solaris.local.com, 192.168.88.51). De esta forma, el tráfico NFS se enruta exclusivamente a través del túnel encriptado de WireGuard, y configurar el servidor NFS para que solo escuche en la IP del túnel (evitando accesos directos por la LAN).

Forzar el cifrado para NFS, ya que ambos hosts están en la misma red LAN (192.168.88.0/24). Usar IPs privadas para el túnel: 10.66.66.1/32 para el servidor y 10.66.66.2/32 para el cliente. No es necesario forwarding ni NAT, ya que es un túnel simple para cifrar el tráfico local.

Verificar que no haya conflictos con reglas PF existentes. Si se usa NFSv4 puro, no se necesita rpcbind ni mountd, lo que simplifica las cosas


Detener servicios TLS

root@tormenta:/home/carlos # service tlsservd status
tlsservd is running as pid 1278.
root@tormenta:/home/carlos # service tlsservd stop
Stopping tlsservd.
Waiting for PIDS: 1278.

root@solaris:~# service tlsclntd status
tlsclntd is running as pid 1596.
root@solaris:~# service tlsclntd stop
Stopping tlsclntd.
Waiting for PIDS: 1596, 1596.

Desactivar TLS

root@tormenta:/home/carlos # sysrc tlsservd_enable="NO"
tlsservd_enable: YES -> NO

root@solaris:~# sysrc tlsclntd_enable="NO"
tlsclntd_enable: YES -> NO

Instalar wireguard-tools en el servidor tormenta y el cliente solaris

pkg install wireguard-tools
sysrc wireguard_enable="YES"
sysrc wireguard_interfaces="wg0"

En el servidor tormenta Generar claves privadas y públicas

mkdir /usr/local/etc/wireguard
cd /usr/local/etc/wireguard

umask 077
wg genkey | tee server_priv.key | wg pubkey > server_pub.key
wg genkey | tee client_priv.key | wg pubkey > client_pub.key

ls -l /usr/local/etc/wireguard
-rw-------  1 root wheel  45 Dec 11 18:28 client_priv.key
-rw-r--r--  1 root wheel  45 Dec 11 18:28 client_pub.key
-rw-------  1 root wheel  45 Dec 11 18:27 server_priv.key
-rw-r--r--  1 root wheel  45 Dec 11 18:27 server_pub.key

Esto genera claves para servidor y cliente

Transferir las claves al cliente solaris (IP 192.168.88.51), usando scp

scp root@tormenta:/usr/local/etc/wireguard/client_priv.key /usr/local/etc/wireguard/client_priv.key
scp root@tormenta:/usr/local/etc/wireguard/client_pub.key /usr/local/etc/wireguard/client_pub.key

Asegurar permisos estrictos (chmod 600 *.key)

cd /usr/local/etc/wireguard/
chmod 600 *.key

ls -l /usr/local/etc/wireguard/
-rw-------  1 root wheel  45 Dec 11 18:30 client_priv.key
-rw-------  1 root wheel  45 Dec 11 18:31 client_pub.key

Configurar WireGuard en el servidor tormenta

Archivo /usr/local/etc/wireguard/wg0.conf

###########################################
[Interface]
Address = 10.66.66.1/32
PrivateKey = <contenido de server_priv.key>
ListenPort = 51820

[Peer]
PublicKey = <contenido de client_pub.key>
AllowedIPs = 10.66.66.2/32

Reemplazar las claves por las claves reales

[Interface]
Address = 10.66.66.1/32
PrivateKey = oPtSkHSk8zNe9d3Z6gExZro9Cf8BELoahgZDsrc/7mk=
ListenPort = 51820

# conexion con clientes
[Peer]
PublicKey = tuu6a6EAPrQTC0tPatWJx2qcS6fEPcg4Z0u/8vY1pTs= 
AllowedIPs = 10.66.66.2/32
###########################################

Habilitar e iniciar el servicio

sysrc wireguard_interfaces="wg0"
sysrc wireguard_enable="YES"
service wireguard start
|

Acvitar desactivar interfaz wg0

wg-quick up wg0
wg-quick down wg0

Comprobar con wg show, debería mostrar la interfaz wg0 levantada

root@tormenta:/home/carlos # wg show
interface: wg0
  public key: UYbDhuNsq0geqJdsVKThSnNLzdc2oHWgUT8Gb0G3VXU=
  private key: (hidden)
  listening port: 51820

peer: tuu6a6EAPrPTC0tPatWJx2qcS6fEPcg4Z0u/8vY1pTs=
  allowed ips: 10.66.66.2/32

Configurar WireGuard en el cliente (solaris)

Archivo /usr/local/etc/wireguard/wg0.conf
###########################################
[Interface]
Address = 10.66.66.2/32
PrivateKey = <contenido de client_priv.key>

[Peer]
PublicKey = <contenido de server_pub.key>
AllowedIPs = 10.66.66.1/32
Endpoint = 192.168.88.160:51820

Reemplazar con las claves reales

[Interface]
Address = 10.66.66.2/32
PrivateKey = sAvZnwh/8xrLLNTxBu75UfvUPB/AhFQTJsUGqYTfUU0=

[Peer]
PublicKey = UYbDhuNsq0geqWdsVKXhSnNLzdc2oHWgUT8Zb0G3VXU=
AllowedIPs = 10.66.66.1/32
Endpoint = 192.168.88.160:51820
###########################################
sysrc wireguard_interfaces="wg0"
sysrc wireguard_enable="YES"
service wireguard start

Levantar interfaz wg0

# wg-quick up wg0
[#] ifconfig wg create name wg0
[#] wg setconf wg0 /dev/stdin
[#] ifconfig wg0 inet 10.66.66.2/32 alias
[#] ifconfig wg0 mtu 1420
[#] ifconfig wg0 up
[#] route -q -n add -inet 10.66.66.1/32 -interface wg0
[+] Backgrounding route monitor

Comprobar wg show debería mostrar el peer conectado.

wg show
interface: wg0
  public key: tuu6a6EAPrPTC0tPatWJx2qcS6fEPcg4Z0u/8vY1pTs=
  listening port: 26481

peer: UYbDhuNsq0geqWdsVKThSnNLzdc2oHWgUT8Gb0G3VXU=
  endpoint: 192.168.88.160:51820
  allowed ips: 10.66.66.1/32
  

Reglas cortafuegos PF (tormenta)

# Regla PF Wireguard antes Anti-spoofing + bogons - permite solo desde el cliente
pass in quick on $lan_if proto udp from 192.168.88.51 to 192.168.88.160 port 51820 keep state
# permite todo dentro del tunel
pass in quick on wg0 keep state # <-- esta es la importante <-p>

Recargar PF

service pf reload 
pfctl -f /etc/pf.conf

Verificar ping, desde el cliente solaris

root@solaris:~# ping 10.66.66.1
PING 10.66.66.1 (10.66.66.1): 56 data bytes
64 bytes from 10.66.66.1: icmp_seq=0 ttl=64 time=0.463 ms
64 bytes from 10.66.66.1: icmp_seq=1 ttl=64 time=0.524 ms

--- 10.66.66.1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.463/0.494/0.524/0.031 ms

Verificar ping, desde el servidor tormenta

root@tormenta:~# ping -c2 10.66.66.2
PING 10.66.66.2 (10.66.66.2): 56 data bytes
64 bytes from 10.66.66.2: icmp_seq=0 ttl=64 time=0.429 ms
64 bytes from 10.66.66.2: icmp_seq=1 ttl=64 time=0.526 ms

--- 10.66.66.2 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.429/0.478/0.526/0.049 ms

ping bidireccional exitoso.

Configurar el cortafuegos PF en el servidor (tormenta)

Para permitir el tráfico WireGuard (UDP puerto 51820), agregar reglas a /etc/pf.conf. Asume que ya tienes PF configurado.

pass in quick on re0 proto udp from 192.168.88.51 to 192.168.88.160 port 51820 keep state

Recargar PF

service pf reload
pfctl -p /etc/pf.conf

Configurar NFSv4 para que solo escuche en la IP del túnel


En el servidor (tormenta), asegurar NFSv4 puro en /etc/rc.conf

nsf_server_enable="YES"
nfsv4_server_enable="YES"
nfs_server_flags="-h 10.66.66.1" # Bind sólo a la IP del túnel
nfsuserd_enable="YES" # necesario si se usa dominio

Iniciar servicios

service nfsd start
service nfsuserd start

Es es para que nfsd sólo escuche en 10.66.66.1, (no en 192.168.88.160).

Deshabilitar rpcbind_enable y mountd_enable, no son necesarios para NFSv4 puro.

Realizar los cambios en /etc/exports para restringir accesos sólo al cliente del túnel
(cambiar de red a host -network a -host).

############################################
V4: /nfsv4
/nfsv4/dellhome -maproot=root 10.66.66.2
/nfsv4/poolrecovery -maproot=root 10.66.66.2
/nfsv4/docs -maproot=root 10.66.66.2
/nfsv4/confsolaris -maproot=root 10.66.66.2
/nfsv4/conftormenta -maproot=root 10.66.66.2
############################################

Esto permite solo desde 10.66.66.2 (el cliente vía túnel).

Reiniciar NFS y nfsuserd

service nfsd restart
service nfsuserd restart

Montar NFS en el cliente (solaris) a través del tŕunel


En el cliente montar usando la IP del túnel del servidor, por ejemplo:

mount -t nfs -o nfsv4 10.66.66.1:/docs /mnt/docs

Para montajes persistentes, se utiliza /etc/fstab

10.66.66.1:/poolrecovery     /nisc4    nfs     rw,nfsv4,noatime,bg    0  	0
10.66.66.1:/confsolaris      /nics4    nfs     rw,nfsv4,noatime,bg	  0  	0
10.66.66.1:/conftormenta     /nits4    nfs     rw,nfsv4,noatime,bg	  0  	0
10.66.66.1:/docs             /nids4    nfs     rw,nfsv4,noatime,bg    0  	0
10.66.66.1:/dellhome 	     /nihs4    nfs     ro,nfsv4,noatime,bg	  0  	0

Consideraciones adicionales

Asi queda el archivo /etc/rc.conf (solaris)

$ gsed -e '/^#/d' -e '/^\s*$/d'

syslogd_flags="-ss"
clear_tmp_enable="YES"
hostname="solaris.local.com"
gateway_enable="NO"
ifconfig_em0="inet 192.168.88.51 netmask 255.255.255.0"
defaultrouter="192.168.88.1"
background_dhclient=YES
defaultroute_delay=3
defaultroute_carrier_delay=3
sshd_enable="NO"
ntpd_enable="YES"
ntpd_sync_on_start="YES"
powerd_enable="YES"
powerd_flags="-n hadp"
loader_conf_files="/boot/loader.conf /boot/loader.conf.local"
boot_efi_enable="YES"
webcamd_enable="YES"
moused_port=/dev/ums0
moused_enable="YES"
dumpdev="NO"
zfs_enable="YES"
dbus_enable="YES"
kld_list="i915kms"
nfs_client_enable="YES"
nfsuserd_enable="YES"
nfsv4_client_enable="YES"
nfsv4_domain="local.com"
tlsclntd_enable="NO"
hostid_enable="YES"
hostid_file="/etc/hostid"
autofs_enable="YES"
devd_enable="YES"
devfs_system_ruleset="system"
pf_enable="NO"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pflog_flags=""
wireguard_enable="YES"
wireguard_interface="wg0"
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
lightdm_enable="YES"
zerotier_enable="YES"
vm_dir="zfs:zroot/vm"
vm_list=""
vm_delay="3"
poudriered_enable="YES"
nginx_enable="YES"
memcached_enable="YES"
memcached_flags="-l localhost -m 8192"
jackett_enable="YES"
linux_enable="NO"
ubuntu_enable="YES"
Asi queda /etc/pf.conf
lan_if   = "re0"
lan_net  = "192.168.88.0/24"
lan_ip   = "192.168.88.160"  
ssh_port     = "{ 22 }"
vpn_if="wg0"

set block-policy return         # responde ICMP/TCP-RST a paquetes bloqueados
set ruleset-optimization none   # en FreeBSD 14 no usa "basic" ni "high-latency"
set skip on lo0

match in all scrub (no-df random-id max-mss 1440)
table <bruteforce> persist       # aquí meterá sshguard, pf-badhost, etc.

pass in quick on $lan_if from $lan_net to $lan_ip keep state
pass in quick on $lan_if proto udp from 192.168.88.51 to 192.168.88.160 port 51820 keep state
pass in quick on wg0 keep state # <-- esta es la importante

block in quick on ! $lan_if from $lan_net to any
block in quick on ! $lan_if from 192.168.0.0/16 to any
block in quick on ! $lan_if from 172.16.0.0/12 to any
block in quick on ! $lan_if from 10.0.0.0/8 to any
block in quick from any to { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, ::/128, 0.0.0.0/8 }
block in quick from <bruteforce>

pass quick on lo0all
pass out quick inet keep state
pass in on $lan_if inet proto icmp from $lan_net to $lan_ip icmp-type echoreq keep state
pass out on $lan_if inet proto icmp from $lan_ip to $lan_net icmp-type echorep keep state
pass in on $lan_if proto tcp from $lan_net to $lan_ip port $ssh_port flags S/SFRA keep state
pass quick on $lan_if proto { tcp udp } from $lan_net to $lan_ip port 53
pass out proto udp from any to port 123 keep state
block log all

Asi queda /etc/exports

$ gsed -e '/^#/d' -e '/^\s*$/d' /etc/exports
V4: /nfsv4
/nfsv4/dellhome		-maproot=root 10.66.66.2
/nfsv4/poolrecovery 	-maproot=root 10.66.66.2
/nfsv4/docs 		-maproot=root 10.66.66.2
/nfsv4/confsolaris 	-maproot=root 10.66.66.2
/nfsv4/conftormenta 	-maproot=root 10.66.66.2

Commprobaciones finales En el servidor tormenta no debe aparecer rpcbind ni statd

root@tormenta:/etc # ps aux | grep -E "(statd|rpcbind|nfs)"
root    1192   0.0  0.0 14140  2380  -  Is   09:34      0:00.00 nfsuserd: master (nfsuserd)
root    1194   0.0  0.0 14140  2384  -  I    09:34      0:00.02 nfsuserd: server (nfsuserd)
root    1195   0.0  0.0 14140  2384  -  S    09:34      0:00.02 nfsuserd: server (nfsuserd)
root    1196   0.0  0.0 14140  2380  -  I    09:34      0:00.00 nfsuserd: server (nfsuserd)
root    1197   0.0  0.0 14140  2384  -  I    09:34      0:00.01 nfsuserd: server (nfsuserd)
root    2398   0.0  0.0 13756  2472  -  Ss   12:23      0:00.01 nfsd: master (nfsd)
root    2399   0.0  0.0 13756  2756  -  S    12:23      0:00.08 nfsd: server (nfsd)

En el cliente solaris remontar directorios

root@solaris:~# umount /nisc4 /nics4 /nits4 /nids4 /nihs4
root@solaris:~# mount -a

root@solaris:~# mount | grep 10.66.66.1
10.66.66.1:/poolrecovery on /nisc4 (nfs, noatime, nfsv4acls)
10.66.66.1:/confsolaris on /nics4 (nfs, noatime, nfsv4acls)
10.66.66.1:/conftormenta on /nits4 (nfs, noatime, nfsv4acls)
10.66.66.1:/docs on /nids4 (nfs, noatime, nfsv4acls)

NFSv4 puro, solo puerto 2049 a través del túnel WireGuard, sin dependencias de rpcbind ni demonios extra.

FreeBSD es genial!.

sábado, 13 de diciembre de 2025

NFS sobre TLS FreeBSD 14.3

Configurar Cifrado NFS sobre TLS


El tráfico NFS está cifrado. Autenticación sigue siendo AUTH_SYS (UID/GID)

NFS sobre TLS proporciona cifrado en tránsito (cifrado del tráfico RPC/TLS) sin necesidad de Kerberos. Utiliza certificados X.509 (pueden ser auto-firmados para entornos locales).

Preparación (en el servidor y cliente) Resolución DNS correcta (tormenta.local.com -> 192.168.88.160)
El kernel en FreeBSD 14.3 soporta KTLS (está en Generic desde FreeBSD 13+)


En ambos dos editar /etc/rc.conf para habilitar los daemons TLS:

tlsservd_enable="YES"  # Demonio servidor TLS (necesario para mounts TLS)
tlsclntd_enable="YES"  # Demonio cliente TLS


En el servidor tormenta.local.com - 192.168.88.160


Instalar y configurar Unbound en el servidor


Generación y Colocación de Certificados


Generar los certificados y moverlos a la carpeta que tlsservd exige por defecto.

Crear directorio temporal para trabajar

mkdir -p /root/certs-work
cd /root/certs-work

Crear CA

openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=HomeLabRootCA"

Crear Certificado Servidor (tormenta)

openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr -subj "/CN=tormenta.local.com"
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Crear Certificado Cliente (solaris) - se usará luego

openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr -subj "/CN=solaris.local.com"
openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt

Instalacion en rutas por defecto del servidor


Crear el directorio

mkdir /etc/rpc.tlsservd

Copiar archivos con los nombres que FreeBSD espera:

cp server.crt /etc/rpc.tlsservd/cert.pem
cp server.key /etc/rpc.tlsservd/certkey.pem
cp ca.crt     /etc/rpc.tlsservd/cacert.pem

Crear lista de revocación vacía (necesaria por defecto)

touch /etc/rpc.tlsservd/crl.pem

Permisos estrictos

chmod 700 /etc/rpc.tlsservd
chmod 600 /etc/rpc.tlsservd/certkey.pem
chmod 444 /etc/rpc.tlsservd/cert.pem
chmod 444 /etc/rpc.tlsservd/cacert.pem

En el cliente (solaris.local.com) IP 192.168.88.51


Preparar directorios y certificados

mkdir /etc/rpc.tlsclntd

Copiar los archivos generados en tormenta hacia solaris y renombrarlos

scp tormenta.local.com:/root/certs-work/client.crt /etc/rpc.tlsclntd/cert.pem
scp tormenta.local.com:/root/certs-work/client.key /etc/rpc.tlsclntd/certkey.pem
scp tormenta.local.com:/root/certs-work/ca.crt /etc/rpc.tlsclntd/cacert.pem

Aplicar permisos estrictos

chmod 700 /etc/rpc.tlsclntd
chmod 600 /etc/rpc.tlsclntd/certkey.pem
chmod 444 /etc/rpc.tlsclntd/cert.pem
chmod 444 /etc/rpc.tlsclntd/cacert.pem
chmod 644 /etc/rpc.tlsclntd/crl.pem

client.crt Es el certificado público del cliente. Identifica quién es el cliente. client.key Es la clave privada del cliente. Nunca debe compartirse. Sirve para firmar la comunicación. cacert.pem Es el certificado de la Autoridad Certificadora. Sirve para que el cliente verifique que el servidor es confiable.

Es importante saber que cambiar la extensión del archivo no cambia su contenido, pero ayuda al software a entender qué formato esperar.

PEM (Privacy Enhanced Mail): Es el formato estándar de texto (Base64) que empieza con 
-----BEGIN CERTIFICATE-----

Verificar que la Clave Privada y el Certificado coinciden

Este es el paso más crítico. Ambos archivos deben tener el mismo "Módulo" (un identificador matemático único). Si los códigos hash que obtienes son idénticos, son pareja.

Ejecuta estos dos comandos:

# Extraer el módulo del certificado público
openssl x509 -noout -modulus -in cert.pem | openssl md5

# Extraer el módulo de la clave privada
openssl rsa -noout -modulus -in certkey.pem | openssl md5

Resultado esperado: Ambos comandos deben devolver exactamente la misma cadena de caracteres (ej. (stdin)= 68b19a0d...). Si son diferentes, esa clave no pertenece a ese certificado.

Verificar que el Certificado fue firmado por la CA

Ahora comprobaremos la cadena de confianza. Queremos confirmar que cert.pem es "hijo" legítimo de cacert.pem. Ejecutando

openssl verify -CAfile cacert.pem cert.pem
cert.pem: OK

Resultado esperado: Deberías ver un mensaje final que diga: cert.pem: OK

Comprobar validez de las fechas

openssl x509 -noout -dates -in cert.pem
notBefore=Dec  9 20:38:11 2025 GMT
notAfter=Dec  7 20:38:11 2035 GMT

Crear lista de revocación vacía (necesaria por defecto)

touch /etc/rpc.tlsservd/crl.pem

Modificar /etc/exports para requerir TLS

Solo la linea V4: puede tener opciones de seguridad.

V4: /nfsv4 -tls
/nfsv4/dellhome		-maproot=root -network 192.168.88.0/24
/nfsv4/poolrecovery 	-maproot=root -network 192.168.88.0/24
/nfsv4/docs 		-maproot=root -network 192.168.88.0/24
/nfsv4/confsolaris 	-maproot=root -network 192.168.88.0/24
/nfsv4/conftormenta 	-maproot=root -network 192.168.88.0/24

Aplicar cambios

service nfsuserd restart
service mountd restart
service nfsd restart

Cliente solaris.local.com (192.168.88.51)


Montar con TLS (temporal)

mount -t nfs -o nfsv4,tls tormenta.local.com:/docs /punto/de/montaje

Permanente (en /etc/fstab)

...
# nfs
tormenta:/poolrecovery    /nisc4    nfs     rw,nfsv4,tls,noatime,bg    	0  	0
tormenta:/confsolaris     /nics4    nfs     rw,nfsv4,tls,noatime,bg	0  	0
tormenta:/docs            /nids4    nfs     rw,nfsv4,tls,noatime,bg    	0  	0
tormenta:/dellhome 	  /nihs4    nfs     ro,nfsv4,tls,noatime,bg	0  	0
mount -a

Servidor - configuración de servicios /etc/rc.conf


NFS y RPC

nfs_server_enable="YES"
nfsv4_server_enable="YES"
nfsuserd_enable="YES"

TLS demonio (servidor)

sysrc tlsservd_enable="YES"

Habilitar Kernel TLS

sysctl kern.ipc.tls.enable=1
echo 'kern.ipc.tls.enable=1' >> /etc/sysctl.conf

Recomendación: La seguridad debe ser en capas (Defensa en profundidad): Firewall + Restricción de IP NFS + Certificados TLS.

sysrc statd_enable="YES"   # Para bloqueo de archivos (opcional pero recomendado)
sysrc lockd_enable="YES    # Para bloqueo de archivos 
sysrc mountd_flags="-r"    # Recarga automatica al compartir datasets

Iniciar servicios

service tlsservd start
service nfsuserd restart
service mountd restart
service nfsd restart

Cliente (solaris.local.com) Configuración (/etc/rc.conf)

nfs_client_enable="YES"
nfsv4_client_enable="YES"
nfsuserd_enable="YES"

# TLS demonio (cliente)
tlsclntd_enable="YES"

Iniciar servicios

service nfsclient start
service nfsuserd start

Habilitar Kernel TLS

sysctl kern.ipc.tls.enable=1
echo 'kern.ipc.tls.enable=1' >> /etc/sysctl.conf

Iniciar cliente

service nfsuserd start
service tlsclntd start

Prueba de montaje

mkdir -p /mnt/docs
mount -t nfs -o nfsv4,tls 192.168.88.160:/docs /mnt/docs

Verificar cifrado

root@solaris:~# nfsstat -m
tormenta:/docs on /nids4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,retrans=2147483647

Debe aparecer tls en las banderas (flags)

nfsstat -m
root@solaris:~# nfsstat -m
tormenta:/poolrecovery on /nisc4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,retrans=2147483647

tormenta:/confsolaris on /nics4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,retrans=2147483647

tormenta:/docs on /nids4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,retrans=2147483647

tormenta:/dellhome on /nihs4
nfsv4,minorversion=2,tcp,resvport,tls,nconnect=1,hard,cto,sec=sys,acdirmin=3,acdirmax=60,acregmin=5,acregmax=60,nametimeo=60,negnametimeo=60,rsize=65536,wsize=65536,readdirsize=65536,readahead=1,wcommitsize=16777216,timeout=120,retrans=2147483647

Regla simple:

tlsservd (TLS Server Daemon): Es para la máquina que OFRECE los archivos (el Servidor). Escucha las peticiones de cifrado entrantes.
tlsclntd (TLS Client Daemon): Es para la máquina que MONTA los archivos (el Cliente). Inicia la petición de cifrado hacia afuera.

Verificar con tcpdump que el tráfico NFS sobre TLS está cifrado

Una vez que el montaje NFS con TLS funciona correctamente, se puede confirmar que el tráfico está realmente cifrado ejecutando tcpdump en el servidor o en el cliente.

Comando básico (en servidor)

tcpdump -i re0 -nn port 2049

O más específico, ver sólo NFS

tcpdump -i re0 -nn port 2049 and host 192.168.88.51

Qué esperar

Si TLS está funcionado correctamente - cifrado activo Verás paquetes TCP en el puerto 2049 Después del handshake TLS inicial, todo el payload de los paquetes estará cifrado.

...
13:35:28.349050 IP 192.168.88.160.2049 > 192.168.88.51.773: Flags [P.], seq 469255:469785, ack 251188, win 29128, options [nop,nop,TS val 505937474 ecr 417283551], length 530
13:35:28.349301 IP 192.168.88.51.773 > 192.168.88.160.2049: Flags [.], ack 469785, win 4344, options 
...

No verás texto legible como nombre de archivos, rutas, ni datos de ficheros. Todo será binario cifrado.

Ejemplo típico de texto claro

NFS request xid ... read fh .../poolrecovery/backup-2025-12-10.gz offset 0 count 32768
Comando más detallado para ver el handshake TLS
tcpdump -i re0 -nn -s 0 -A port 2049
-i <interfaz>
-A imprime cada paquete en formato ASCII (crucial para leer contenido)
-n No convierte direcciones IP a nombres de host (más rápido)

En el cliente solaris echo 'Garantizar cifrado' > /nids4/prueba.txt no podrás ver ni el nombre del archivo ni su contenido.

...
14:10:09.830256 IP 192.168.88.160.2049 > 192.168.88.51.890: Flags [P.], seq 1:115, ack 162, win 29128, options [nop,nop,TS val 3871689747 ecr 1810578769], length 114
E....V..@.....X...X3...z.C........q.2......
...
tcpdump -i re0 -nn port 2049 -c 50

Genera activida en el cliente solaris

ls -ltr /nihs4
...
14:12:35.627829 IP 192.168.88.160.2049 > 192.168.88.51.698: Flags [.], ack 230, win 29128, options [nop,nop,TS val 1928012123 ecr 3657311778], length 0
14:12:35.628036 IP 192.168.88.160.2049 > 192.168.88.51.698: Flags [P.], seq 1:303, ack 230, win 
...

Si solo ves números de secuencia y longitudes, sin nombres de archivos -> cifrado Si ves rutas y operaciones NFS -> sin cifrado (TLS inactivo).

FreeBSD es genial!.

sábado, 6 de diciembre de 2025

FreeBSD 14.3 Cortafuegos PF

Sintaxis actualizada (FreeBSD 14 usa PF de OpenBSD 6.9–7.0 aproximadamente, hay cambios importantes).

# ====================== MACROS ======================
lan_if   = "re0"
zt_if    = "zt1ocu1pr8e2sac"
lan_net  = "192.168.88.0/24"
zt_net   = "192.168.192.0/24"
my_zt_ip = "192.168.192.204"
lan_ip   = "192.168.88.160"      # pon aquí la IP real de re0 si es fija

ssh_port     = "{ 22 }"
nfs_ports_tcp = "{ 111, 892, 2049 }"
nfs_ports_udp = "{ 111, 892 }"

# ====================== OPCIONES GLOBALES ======================
set block-policy return         # responde ICMP/TCP-RST a paquetes bloqueados
set ruleset-optimization none   # en FreeBSD 14 no usa "basic" ni "high-latency"
set skip on lo0
set skip on $zt_if              # ZeroTier ya tiene su propio cortafuegos interno

# Normalización moderna (recomendado)
match in all scrub (no-df random-id max-mss 1440)

# ====================== TABLAS ======================
table <bruteforce> persist       # aquí meterá sshguard, pf-badhost, etc.

# ====================== TRÁFICO CONFIABLE (LAN) =======================
pass in quick on $lan_if from $lan_net to $lan_ip keep state

# =================== EXCEPCIÓN PARA EL TÚNEL WIREGUARD ================
# Wireguard: handshake y todo el trafico dentro del tunel
pass in quick on $lan_if proto udp from 192.168.88.51 to 192.168.88.160 \
port 51820 keep state
pass in quick on wg0 keep state  # <-- esta es la importante

# ====================== REGLAS DE PROTECCIÓN BÁSICA ===================
# Anti-spoofing + bogons (bloqueo rápido)
block in quick on ! $lan_if from $lan_net to any
block in quick on ! $lan_if from 192.168.0.0/16 to any
block in quick on ! $lan_if from 172.16.0.0/12 to any
block in quick on ! $lan_if from 10.0.0.0/8 to any

block in quick from any to { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
10.0.0.0/8, ::/128, 0.0.0.0/8 }

# Bloqueo rápido de hosts en lista negra
block in quick from <bruteforce>

# ====================== LOOPBACK ======================
pass quick on lo0 all

# ====================== TRÁFICO SALIENTE (stateful) ======================
pass out quick inet keep state

# ====================== ICMP ======================
pass in on $lan_if inet proto icmp from $lan_net to $lan_ip icmp-type echoreq \
keep state
pass out on $lan_if inet proto icmp from $lan_ip to $lan_net icmp-type echorep \
keep state

# ====================== SSH CON PROTECCIÓN ======================
# Desde LAN (sin límite)
pass in on $lan_if proto tcp from $lan_net to $lan_ip port $ssh_port flags \
S/SFRA keep state

# Desde ZeroTier (con límite de tasa para evitar brute-force)
pass in on $zt_if proto tcp from $zt_net to $my_zt_ip port $ssh_port \
    flags S/SFRA keep state \
    (max-src-conn-rate 15/5, overload <bruteforce> flush global)

# ====================== DNS (Unbound local) ======================
pass quick on $lan_if proto { tcp udp } from $lan_net to $lan_ip port 53

# ====================== NTP cliente ======================
pass out proto udp from any to port 123 keep state

# ====================== NFS (solo LAN) ======================
pass in on $lan_if proto tcp from $lan_net to $lan_ip port $nfs_ports_tcp \
    flags S/SFRA keep state
pass in on $lan_if proto udp from $lan_net to $lan_ip port $nfs_ports_udp \
    keep state

# NFSv4 callback channel (solo desde clientes NFS de la LAN)
pass in on $lan_if proto tcp from $lan_net to $lan_ip port 3000:4000 \
    flags S/SFRA keep state

# ====================== ZeroTier (puerto de control) ======================
pass in quick on $zt_if proto udp from any to any port 9993

# ====================== BLOQUEO FINAL (por defecto) ======================
block log all

FreeBSD es genial!.

jueves, 3 de julio de 2025

VLAN Mikrotik Basado en Puertos

VLANs Mikrotik - Basada en Puertos. Tenemos dos routers Mikrotik (RouterOS).

Internet

El router Mikrotik esta conectado desde el puerto ehter1 (WAN_ether1) a uno de los puertos ethernet del router ISP, usando DHCP Client.

[admin@R1] /ip dhcp-client> print
Flags: X - disabled, I - invalid, D - dynamic 
 #   INTERFACE    USE-PEER-DNS ADD-DEFAULT-ROUTE STATUS      ADDRESS           
 0   ether1        yes          yes               bound       192.168.88.12/24  

Todos los puertos de un switch por defecto pertenecen a la la vlan 1. El switch necesita de un router para mover (forwarding) el tráfico entre las vlan. Eso permite la comunicacion entre diferentes VLAN.

Las VLAN ID solo aparecen en Switch administrables y funcionan en capa 2. La segmentación se produce en el Switch.

El Switch tiene una base de datos llamada tabla CAM donde realiza un seguimiento de cada computadora conectada:

- MAC Address
- Numero de Puerto
- VLAN ID - Solo en Switches Administrables

Las VLANs se utilizan se utilizan para segmentar una red, lo que permite mejorar la seguridad, el rendimiento y la gestion de la red. Los dispositivos de una VLAN pueden ser configurados y administrados de forma separada.

Los dispositivos CRS (tienen capacidad de capa 3) se pueden utilizar como enrutador y conmutador al mismo tiempo, útil para redes que se centran en el rendimiento de la red interna.

VLAN - Laboratorio de pruebas

Ambos routers estan en blanco - System - Reset Configuration - No Default Configuration - Reset Configuration.

Tenemos un router 1 (R1) donde se crean las VLAN, vlan10 con vlan-id=10 y vlan20 con vlan-id=20 en la interfaz Ether3, cada una con su direccionamineto IP y un DHCP Server. Esas VLAN se envían Tagged (Trunk en Cisco) a través de Ether3 y se reciben Tagged en el router 2 (R2) en el puerto Ether1. Luego se entregan como Untagged (Access Port) en los puertos Ether3 y Ether4.

Configuración vía comandos del Router 1.

Nota: La dirección IP del dns-server correspnde al servidor DNS de mi red interna. Puede utilizar DNS públicos si no tiene un servidor DNS local, por ejemplo, 1.1.1.1 o los del propio router Mikrotik, por defecto 192.168.88.1.

/interface
add interface=ether2 name=vlan10 vlan-id=10
add interface=ether2 name=vlan20 vlan-id=20
/ip pool
add name=dhcp_pool0 ranges=10.10.10.200-10.10.10.254
add name=dhcp_pool1 ranges=172.24.1.200-172.24.1.254
/ip dhcp-server
add address-pool=dhcp_pool0 disable=no interface=vlan10 name=dhcp1
add address-pool=dhcp_pool1 disable=no interface=vlan20 name=dhcp2
/ip address
add address=10.10.10.1/24 interface=vlan10 network=10.10.10.0
add address=172.24.1.1/24 interface=vlan20 network=172.24.1.0
/ip dhcp-server network
add address=10.10.10.0/24 dns-server=192.168.88.200 gateway=10.10.10.1
add address=172.24.1.0/24 dns-server=192.168.88.200 gateway=172.24.1.1

En el Router R2 se crean las VLAN en el puerto Ether1 que es donde recibimos las VLAN con el nombre y vlan-id correspondiente, vlan10 vlan-id=10 y vlan20 vlan-id=20. Teniendo en cuenta que para que las VLAN se comuniquen entre dispositivos el id debe ser el mismo. Tambien hay que crear un bridge por cada VLAN Bridge_VLAN10 y Bridge_VLAN20. En la pestaña Bridge - Bridge - Ports, agregar dos interfaces: la propia VLAN y el puerto físico donde quiero entregarla como acceso (Access Port). En el caso de la VLAN vlan10 los puertos son: la propia VLAN vlan10 y el puerto Ether3. En la VLAN vlan20 los puertos son: la propia VLAN vlan20 y el puerto Ether4. Evidentemente, si quiero entregar la misma VLAN en más puertos este último paso se repite para todos los puertos involucrados.

Configuracion vía comandos Router 2 (R2)

/interface vlan
add interface=ether1 name=vlan10 vlan-id=10
add interface=ether1 name=vlan20 vlan-id=20
/interface bridge
add name=Bridge_VLAN10
add name=Bridge_VLAN20
/interface Bridge port
add bridge=Bridge_VLAN10 interface=vlan10
add bridge=Bridge_VLAN10 interface=ether3
add bridge=Bridge_VLAN20 interface=vlan20
add bridge=Bridge_VLAN20 interface=ether4

IP Route R1

[admin@R1] /ip route> print
Flags: X - disabled, A - active, D - dynamic, 
C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, 
B - blackhole, U - unreachable, P - prohibit 
 #      DST-ADDRESS        PREF-SRC        GATEWAY         DISTANCE
 0 ADS  0.0.0.0/0                          192.168.88.1           1
 2 ADC  10.10.10.0/24      10.10.10.1      vlan10                 0
 3 ADC  172.24.1.0/24      172.24.1.1      vlan20                 0
 4 ADC  192.168.88.0/24    192.168.88.12   ether1                 0
 

Conecto un PC a Ether3 del router R2 y recibe una IP del DHCP-Server configurado en R1

[admin@R1] /ip dhcp-server lease print
Flags: X - disabled, R - radius, D - dynamic, B - blocked 
 #   ADDRESS              MAC-ADDRESS       H SE.. R STATUS  LAST-SEEN            
 0 D 10.10.10.251         E4:B9:7A:6B:96:CD s dh..   bound   4m6s  
 

(Opcional) -¿Cómo Permitir tráfico de VLANs?

/ip firewall filter
add chain=forward src-address=10.10.10.0/24 dst-address=172.24.1.0/24 \
connection-state=new,established action=accept comment="Permitir VLAN10 \
a VLAN20"
/ip firewall filter
add chain=forward src-address=172.24.1.0/24 dst-address=10.10.10.0/24 \
connection-state=new,established action=accept comment="Permitir VLAN20 \
a VLAN10"

Ubicación de las reglas:

Antes de cualquier regla que bloquee tráfico (ej. action=drop).
Usa el menú Drag & Drop en Winbox para ordenarlas.

Explicacion:

Las opciones connection-state=new,established permiten:
new: Conexiones iniciadas desde el origen.
established: Respuestas al tráfico iniciado.

Permitir acceso administrativo sólo desde la red 10.10.10.1/24

add chain=input src-address=10.10.10.1/24 protocol=tcp dst-port=22,8291,8728,8729 \
action=accept comment="Acceso administrativo (Winbox/SSH/API)"

Reglas de cortafuegos R1

admin@R1VLAN] > /ip firewall filter print
Flags: X - disabled, I - invalid, D - dynamic 
 0    ;;; Permitir conexiones establecidas
      chain=input action=accept connection-state=established,related log=no log-prefix="" 

 1    ;;; Permitir ICMP
      chain=input action=accept protocol=icmp log=no log-prefix="" 

 2    ;;; Permitir conexiones establecidas
      chain=forward action=accept connection-state=established,related log=no log-prefix="" 

 3    ;;; Bloquear conexiones inva/ip lidas
      chain=forward action=drop connection-state=invalid log=no log-prefix="" 

 4    ;;; Permitir trafico forward in wlan1 y out vlan10
      chain=forward action=accept in-interface=wlan1 out-interface=vlan10 log=no log-prefix="" 

 5    ;;; Permitir forward in vlan10 y out wlan1
      chain=forward action=accept in-interface=vlan10 out-interface=wlan1 log=no log-prefix="" 

 6    ;;; Permitir trafico forward in wlan1 y out vlan20
      chain=forward action=accept in-interface=wlan1 out-interface=vlan20 log=no log-prefix="" 

 7    ;;; Perimtir trafico forward in vlan20 out wlan1
      chain=forward action=accept in-interface=vlan20 out-interface=wlan1 log=no log-prefix="" 

 8    ;;; Bloquear trafico no permitido
      chain=forward action=drop log=no log-prefix="" 
FreeBSD es genial!.

jueves, 12 de junio de 2025

Firewall Mikrotik Protege LAN y Permite Acceso a Internet

Configuración de firewall para MikroTik (RouterOS)

Protege la red LAN (10.10.10.0/24) y permite acceso a Internet. Las reglas incluyen protección anti-spoofing, bloqueo de tráfico no autorizado, y permiten tráfico legítimo.

El router Mikrotik esta conectado al puerto ehter1 (WAN_ether1) y uno de los puertos ethernet del router ISP usando DHCP Client

Configuración básica de interfaces

/interface bridge
add name=LAN_bridge
/interface bridge port
add bridge=LAN_bridge interface=ether2
add bridge=LAN_bridge interface=ether3
add bridge=LAN_bridge interface=ether4
add bridge=LAN_bridge interface=ether5
add bridge=LAN_bridge interface=wlan1
add bridge=LAN_bridge interface=wlan2
/ip address
add address=10.10.10.1/24 interface=LAN_bridge

DHCP Client en WAN (WAN_ether1)

/ip dhcp-client
add interface=WAN_ether1

NAT para acceso a Internet

/ip firewall nat
add chain=srcnat out-interface=WAN_ether1 action=masquerade

POLÍTICAS POR DEFECTO (FILTER)

/ip firewall filter

CONEXIONES ESTABLECIDAS

add chain=input action=accept connection-state=established,related \
comment="Permitir conexiones Establecidas/Realacionadas (Input)"
add chain=forward action=accept connection-state=established,related \
comment="Permitir conexiones Establecidas/Relacionadas (Forward)"
add chain=output action=accept connection-state=established,related \
comment="Permitir conexiones Establecidas/Relacionadas (Output)"

ANTI-SPOOFING Y SEGURIDAD BÁSICA Bloqueo de IPs falsas en WAN

add chain=input action=drop in-interface=WAN_ether1 src-address=10.10.10.0/24 \
comment="Bloquear LAN IP Spoofing (Input)"
add chain=forward action=drop in-interface=WAN_ether1 src-address=10.10.10.0/24 \
comment="Bloquear LAN IP Spoofing (Forward)"

Protección contra escaneos y ataques comunes

add chain=input action=drop in-interface=WAN_ether1 protocol=tcp psd=21,3s,3,1 \
comment="Bloquear TCP SYN Scans"
add chain=input action=drop in-interface=WAN_ether1 protocol=udp

REGLAS INPUT (TRÁFICO AL ROUTER) Permitir administración solo desde LAN

add chain=input action=accept in-interface=LAN_bridge protocol=tcp dst-port=22,8291,443 \
comment="Acceso Administracion (LAN)"

Permitir ICMP (ping)

add chain=input action=accept protocol=icmp comment="Allow ICMP"

Permitir DHCP desde ISP

add chain=input action=accept in-interface=WAN_ether1 protocol=udp src-port=67-68 dst-port=67-68 \
comment="DHCP Cliente"

Bloquear todo lo demás en WAN

add chain=input action=drop in-interface=WAN_ether1 \
comment="Bloquear Todo WAN Input"

REGLAS FORWARD (TRÁFICO A TRAVÉS DEL ROUTER)

Permitir LAN -> Internet

add chain=forward action=accept in-interface=LAN_bridge out-interface=WAN_ether1 \
connection-state=new comment="LAN a Internet"

Bloquear Internet -> LAN (excepto respuestas)

add chain=forward action=drop in-interface=WAN_ether1 out-interface=LAN_bridge \
connection-state=new comment="Bloquear Internet a LAN"

Permitir tráfico entre interfaces LAN (opcional)

add chain=forward action=accept in-interface=LAN_bridge out-interface=LAN_bridge \
comment="Inter-LAN Tráfico"

REGLAS OUTPUT (TRÁFICO DESDE EL ROUTER)

add chain=output action=accept comment="Permitir Router Output" disabled=no

REGLAS ADICIONALES DE SEGURIDAD Bloqueo de redes reservadas/rfc1918 desde WAN

add chain=input action=drop in-interface=WAN_ether1 src-address-list=private_ranges \
comment="Bloquear IPs Privada (Input)"
add chain=forward action=drop in-interface=WAN_ether1 src-address-list=private_ranges \
comment="Bloquear IPs Privada (Forward)"

Lista de redes reservadas

/ip firewall address-list
add address=172.16.0.0/12 list=private_ranges
add address=10.0.0.0/8 list=private_ranges
add address=192.168.0.0/16 list=private_ranges
add address=169.254.0.0/16 list=private_ranges

LOGGING (OPCIONAL)

add chain=input action=log log-prefix="[BLOQUEO DE CORTAFUEGOS] " \
comment="Log Bloqueado Input"
add chain=forward action=log log-prefix="[BLOQUEO DE CORTAFUEGOS] " 
comment="Log Bloqueado Forward"

Configurar servicios:

/ip service
set ssh address=10.10.10.0/24,192.168.88.0/24
set winbox address=10.10.10.0/24,192.168.88.0/24
set ftp disable=yes
set telnet disable=yes
set api disable=yes
set api-ssl disable=yes
set www disable=yes
set www-ssl disable=yes

Protección bridge:

/interfaces bridge settings
set use-ip-firewall=yes

Protección extra:

/ip firewall filter
add chain=forward protocol=tcp tcp-flags=syn,!ack action=drop comment="Bloquear SYN-flood"
add chain=forward protocol=udp limit=10/1m action=drop comment="Limite UDP floods"

Explicación:

1. Conexiones Establecidas: - Acepta tráfico de respuestas en todas las cadenas (input, forward, output).

2. Protección Anti-Spoofing: - Bloquea tráfico WAN con IPs de la LAN (10.10.10.0/24). - Bloquea redes reservadas (RFC 1918) desde WAN.

3. Reglas INPUT: - Solo permite administración (SSH, Winbox, WebFig) desde la LAN. - Permite ICMP (ping) y DHCP del ISP. - Bloquea todo el tráfico entrante no autorizado en WAN.

4. Reglas FORWARD: - Permite nuevas conexiones desde LAN hacia Internet. - Bloquea nuevas conexiones desde Internet hacia LAN. - Permite comunicación entre dispositivos LAN (opcional).

5. Reglas OUTPUT: - Permite todo el tráfico generado por el router (se puede ajustar si es necesario).

6. Protección Adicional: - Bloqueo de escaneos TCP/UDP desde Internet. - Logging de tráfico bloqueado para diagnóstico.

Notas: - Políticas por Defecto: - Input: drop (implícito por reglas). - Forward: drop (regla final bloquea tráfico no autorizado). - Output: accept.

- NAT: La regla masquerade en srcnat permite a la LAN acceder a Internet usando la IP WAN (asignada por DHCP).

- Personalización: - Para permitir acceso desde Internet (ej: servidor web), agregar reglas `forward` específicas. - Ajustar puertos de administración en reglas `input` según necesidades.

Esta configuración equilibra seguridad y funcionalidad, protegiendo la LAN de amenazas externas mientras permite acceso a Internet.

FreeBSD es genial!.