Páginas

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

https://gnulinuxcodigo.blogspot.com/2025/12/unbound-dns-local-en-freebsd-143.html


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 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

Configuración de servicios (/etc/rc.conf)


NFS y RPC

nfs_server_enable="YES"
nfsv4_server_enable="YES"
nfsuserd_enable="YES"
mountd_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.

statd_enable="YES"   # Para bloqueo de archivos (opcional pero recomendado)
lockd_enable="YES    # Para bloqueo de archivos 
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"

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!.

viernes, 12 de diciembre de 2025

Unbound DNS Local en FreeBSD 14.3

Configurar Unbound FreeBSD 14.3

Servidor tormenta y cliente solaris /etc/hosts

...
192.168.88.160		tormenta.local.com  tormenta
192.168.88.51		solaris.local.com  solaris
...

Archivo de configuracion /usr/local/etc/unbound/unbound.conf

server:
# Interfaces y puertos
interface: 127.0.0.1       # usar unbound para la resolucion DNS
interface: 192.168.88.160
port: 53
do-ip4: yes
do-ip6: no
do-udp: yes
do-tcp: yes

# Seguridad y acceso
access-control: 127.0.0.0/8 allow
access-control: 192.168.88.0/24 allow
access-control: 0.0.0.0/0 refuse

# Cache y rendimiento
cache-min-ttl: 3600
cache-max-ttl: 86400
prefetch: yes
prefetch-key: yes

# Privacidad
hide-identity: yes
hide-version: yes
identity: "DNS Server"
version: " "

# Validación DNSSEC - verificar autenticidad de las respuestas
auto-trust-anchor-file: "/usr/local/etc/unbound/root.key"
val-clean-additional: yes

# Archivos de zona local
include: /usr/local/etc/unbound/local-zone.conf

# Control remoto 
include: /usr/local/etc/unbound/remote-control.conf

# Redirección de consultas
forward-zone:
name: "."
forward-addr: 9.9.9.9 # Quad9 DNS
forward-addr: 8.8.8.8 # Google DNS
carlos@tormenta:~ % cat /usr/local/etc/unbound/local-zone.conf 
# Zona local local.com
local-zone: "local.com." static
local-data: "tormenta.local.com. IN A 192.168.88.160"
local-data: "solaris.local.com. IN A 192.168.88.51"
local-data: "ns.local.com. IN A 192.168.88.160"
local-data: "local.com. IN NS ns.local.com."
carlos@tormenta:~ % cat /usr/local/etc/unbound/remote-control.conf 
# Habilitar interfaz de control
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8953
control-use-cert: no
sysrc unbound_enable="YES"
service unbound start
Archivo /etc/resolv.conf (tormenta)
cat /etc/resolv.conf
# Generated by resolvconf
nameserver 127.0.0.1      # 
nameserver 192.168.88.160
domain local.com
search local.com

Archivo /etc/resolv.conf (solaris)

nameserver 192.168.88.160
domain local.com
search local.com

Consultas DNS desde el cliente (solaris.local.com)

dig @tormenta.local.com freebsd.org

; <<>> DiG 9.20.16 <<>> @tormenta.local.com freebsd.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56301
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;freebsd.org.			IN	A

;; ANSWER SECTION:
freebsd.org.		3600	IN	A	96.47.72.84

;; Query time: 58 msec
;; SERVER: 192.168.88.160#53(tormenta.local.com) (UDP)
;; WHEN: Wed Dec 10 14:12:38 CET 2025
;; MSG SIZE  rcvd: 56

Desde el servidor

dig freebsd.org @127.0.0.1
carlos@tormenta:~ % dig freebsd.org @127.0.0.1

; <<>> DiG 9.20.16 <<>> freebsd.org @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38422
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;freebsd.org.			IN	A

;; ANSWER SECTION:
freebsd.org.		3426	IN	A	96.47.72.84

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Fri Dec 12 16:01:03 CET 2025
;; MSG SIZE  rcvd: 56
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!.

martes, 23 de septiembre de 2025

Supervisar Disco con smartmontools en FreeBSD 14.2

Configurar smartmontools en FreeBSD 14.2 para supervisar el estado de discos SSD y/o nvme y enviar correos mediante DMA usando los servidores de Gmail


Instalar smartmontools

 pkg install smartmontools

Habilitar el servicio smartd para que inicie al arrancar el sistema

 sysrc smartd_enable="YES"

Iniciar servicio

 service smartd start

Identificar el disco SSD

Primero listar los discos disponibles

 smartctl --scan

/dev/da0 -d sat # /dev/da0 [SAT], ATA device
/dev/nvme0 -d nvme # /dev/nvme0, NVMe device

Configurar smartd para monitorear el SSD

Editar el archivo de configuración

 cp /usr/local/etc/smartd.conf.sample /usr/local/etc/smartd.conf

Agregar esta línea para monitorear el SSD y enviar alertas por correo electrónico

 /dev/da0 -d sat -H -l error -l selftest -f -m tucorreo@protonmail.com
Explicación
 -H Comprueba el estado general SMART
 -l error Revisa el log de errores
 -l selftest Revisa el log de autopruebas
 -f Revisa fallos futuros
 -m Dirección de correo para notificaciones

Comprobar que el disco habla con el disco /dev/da0

# smartctl -d sat -a /dev/da0
smartctl 7.5 2025-04-30 r5714 [FreeBSD 14.3-RELEASE-p2 amd64] (local build)
Copyright (C) 2002-25, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Toshiba 2.5" HDD MQ04UBD...
Device Model:     TOSHIBA MQ04UBD200
Serial Number:    Y0JKT0QOT
LU WWN Device Id: 0 000000 000000000
Firmware Version: JT001U
User Capacity:    2,000,398,934,016 bytes [2.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Rotation Rate:    5400 rpm
Form Factor:      2.5 inches
Zoned Device:     Device managed zones
Device is:        In smartctl database 7.5/5706
ATA Version is:   ACS-3 T13/2161-D revision 5
SATA Version is:  SATA 3.3, 3.0 Gb/s (current: 3.0 Gb/s)
Local Time is:    Tue Sep 23 15:03:29 2025 CEST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
...

Configurar DMA para enviar correos por Gmail


https://gnulinuxcodigo.blogspot.com/2024/12/freebsd-dma-dragonfly-mail-agent.html

FreeBSD 14.2 usa DMA como agente de correo por defecto.

Probando el envío de correos

echo "Prueba de correo desde FreeBSD" | mail -s "Prueba" tucorreo@protonmail.com

o, otra forma para lograr el mismo resultado

 cat >> mensaje.txt<<EOF
Esto es una prueba de correo desde usando el agente DMA.
EOF

 mail -v -s prueba tucorreo@protonmail.com < mensaje.txt

Verificar el log de DMA

 tail -f /var/log/maillog
...
Sep 19 08:59:00 tormenta dma[dd67.2b6bad248050][86005]: trying remote delivery to smtp.gmail.com [74.125.133.109] pref 0
Sep 19 08:59:00 tormenta dma[dd67.2b6bad248050][86005]: using SMTP authentication for user tucorreo@gmail.com
Sep 19 08:59:01 tormenta dma[dd67.2b6bad248050][86005]:  delivery successful

Para que smartmontools vigile un disco NVMe

Averiguar el nodo del NVMe

 nvmecontrol devlist
 nvme0: CT500P2SSD8
    nvme0ns1 (476940MB)

 ls -l /dev/nvme*
crw-------  1 root wheel 0x33 Sep 20 15:41 /dev/nvme0
crw-------  1 root wheel 0x40 Sep 20 15:41 /dev/nvme0ns1

Comprobar que smartctl habla con el NVMe

 smartctl -d nvme /dev/nvme0ns1 -i

smartctl 7.5 2025-04-30 r5714 [FreeBSD 14.2-RELEASE-p1 amd64] (local build)
Copyright (C) 2002-25, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Number:                       CT500P2SSD8
Serial Number:                      2216E629B1D4
Firmware Version:                   P2CR048
PCI Vendor/Subsystem ID:            0xc0a9
IEEE OUI Identifier:                0x00a075
Total NVM Capacity:                 500,107,862,016 [500 GB]
Unallocated NVM Capacity:           0
Controller ID:                      1
NVMe Version:                       1.3
Number of Namespaces:               1
Namespace 1 Size/Capacity:          500,107,862,016 [500 GB]
Namespace 1 Formatted LBA Size:     512
Namespace 1 IEEE EUI-64:            00a075 61b0000125
Local Time is:                      Fri Sep 19 09:36:00 2025 CEST

Mostrará modelo, serial, versión NVMe, etc.

Crear una entrada específica para el NVMe en /usr/local/etc/smartd.conf

 /dev/nvme0ns1 -d nvme -H -l error -l selftest -f -m tucorreo@protonmail.com -M test

Explicación

 -d nvme - le dice a smartd que use el backend NVMe
 -H - atributo "Health"
 -l error - log de errores
 -l selftest - log de autopruebas 
 -f - predicción de fallos
 -m - destinatario
 -M test - envía un correo de bienvenida al arrancar smartd (útil para verificar).

Contenido del fichero /usr/local/etc/smartd.conf

 sed -e '/^[ ]*#/d' -e '/^$/d' /usr/local/etc/smartd.conf
 
/dev/da0 -d sat -H -l error -l selftest -f -m tucorreo@protonmail.com
/dev/nvme0ns1 -d nvme -H -l error -l selftest -f -m tucorreo@protonmail.com

service smartd restart

En /var/log/daemon.log se verá

 tail -f /var/log/daemon.log 
...
Sep 19 09:55:34 tormenta smartd[87644]: Device: /dev/nvme0, opened
Sep 19 09:55:34 tormenta smartd[87644]: Device: /dev/nvme0, CT500P3SSD8, S/N:2240E6733488, FW:P9CR30A
Sep 19 09:55:34 tormenta smartd[87644]: Device: /dev/nvme0, is SMART capable. Adding to "monitor" list.
Sep 19 09:55:34 tormenta smartd[87644]: Monitoring 1 ATA/SATA, 0 SCSI/SAS and 1 NVMe devices

Arrancar o reiniciar el demonio

 service smartd restart

En /var/log/daemon.log se verá la línea "Device:/dev/nvme0ns1,opened" y si se incluye -M test, un correo inmediato.

Crear el helper de notificación

En FreeBSD el paquete smartmontools no instala helper de notificación; hay que crearlo.

Crear el script que smartd invoca y asegurarse de que llame a /usr/bin/mail smartd siempre ejecuta el script con sh, por lo que la shell personal (csh) no afecta en absoluto.

cat > /usr/local/sbin/smartdnotify-mailout <<'EOF'
#!/bin/sh
# SMARTD_ADDRESS direccion destino
# SMARTD_SUBJECT asunto
# SMARTD_MESSAGE cuerpo del mensaje
exec /usr/bin/mail -s "$SMARTD_SUBJECT" "$SMARTD_ADDRESS" <<EOF_MAIL
$SMARTD_MESSAGE
EOF_MAIL
EOF

Contenido del archivo /usr/local/sbin/smartdnotify-mailout

#!/bin/sh
# SMARTD_ADDRESS direccion destino
# SMARTD_SUBJECT asunto
# SMARTD_MESSAGE cuerpo del mensaje
exec /usr/bin/mail -s "$SMARTD_SUBJECT" "$SMARTD_ADDRESS" <<EOF
$SMARTD_MESSAGE
EOF

Hay que darle permisos de ejecución

chmod 755 /usr/local/sbin/smartdnotify-mailout

Verificar que smartd lo va a usar

grep ^mailout /usr/local/etc/smartd.conf

Si tuviera una línea como

MAILER /usr/local/libexec/smartdnotify

comentarla o borrarla para que smartd use el helper estándar.

Simular las variables que smartd exporta (shell csh)

setenv SMARTD_ADDRESS "tucorreo@protonmail.com"
setenv SMARTD_SUBJECT "SMART alerta"
setenv SMARTD_MESSAGE "Problema en disco detectado"

En csh las variables anteriores sólo existen en esa shell; Cuando smartd arranca como servicio, no las ve.

La solución es asegurarse de que smartd exporte esas variables él mismo

Forzar un correo de prueba

service smartd restart

si smartd ya está corriendo

pkill -USR1 smartd

Verificar la entrega

tail -f /var/log/maillog
...
Sep 21 16:14:42 tormenta dma[8210.32674c848000][49835]: trying remote delivery to smtp.gmail.com [64.233.184.109] pref 0
Sep 21 16:14:43 tormenta dma[f8210.32674c848000][49835]: using SMTP authentication for user tucorreo@gmail.com
Sep 21 16:14:43 tormenta dma[f820e.57c02fa48000][49825]: <tucorreo@protonmail.com> delivery successful
Sep 21 16:14:44 tormenta dma[f8210.32674c848000][49835]: <tucorreo@protonmail.com> delivery successful

El mensaje "SMART daemon startup" llegará a la bandeja de entrada

Comprobaciones

smartd invoca realmente el helper?

Verlo en tiempo real

service smartd stop
smartd -d -c /usr/local/etc/smartd.conf

En otra terminal forzar el envío

pkill -USR1 smartd

En la primera terminal debe aparecer

Executing "/usr/local/sbin/smartdnotify-mailout"

Si no aparece el problema es parseo de smartd.conf (espacio, salto de línea, falta -M test, etc.)

Borrar las variables del shell (no hacen falta), csh

unsetenv SMARTD_SUBJECT SMARTD_MESSAGE SMARTD_ADDRESS

No se necesita setenv en ningún fichero. Reiniciar smartd con service smartd restart y el demonio exportará las variables antes de llamar al helper.

Ahora ya se puede quitar -M test de ambas líneas cuando ya no se desee recibir el correo de bienvenida cada vez que reinicie smartd

-M test sólo fuerza el envío de un aviso al arrancar el demonio. No afecta a las alertas reales; esas se mandan siempre cuando ocurran.

A partir de ahora no se recibirá el mail "SMART daemon startup". Sí recibirás cualquier alerta real cuando smartd la detecte.

Verificar el estado actual y forzar una alerta en cualquier momento sin reiniciar el servicio.

Lectura rápida en caliente (sin detener smartd)

 smartctl -d nvme -A /dev/nvme0ns1
 smartctl -d nvme -H /dev/nvme0ns1
 smartctl -d nvme -l /dev/nvme0
 smartctl -d sat -A /dev/da0
 smartctl -d sat -H  /dev/da0
 smartctl -d sat -l error /dev/da0

Forzar un evento para comprobar que las alertas siguen funcionando

 kill -USR1 $(pgrep smartd) # sh
 kill -USR1 `pgrep smartd` # csh

Ver que está vigilando smartd en este momento

 tail -f /var/log/daemon.log | grep smartd

Cada 30 minutos, que es el valor por defecto, vuelve a comprobar y registrará cualquier cambio.

Mensajes recibidos en mi correo (uno por cada disco)


Primer mensaje

This message was generated by the smartd daemon running on:

   host name:  tormenta
   DNS domain: [Empty]

The following warning/error was logged by the smartd daemon:

TEST EMAIL from smartd for device: /dev/da0 [SAT]

Device info:
TOSHIBA MQ04UBD200, S/N:Y0JKT0QOT, WWN:0-000000-000000000, FW:JT001U, 2.00 TB

For details see host's SYSLOG.

Segundo mensaje

This message was generated by the smartd daemon running on:

   host name:  tormenta
   DNS domain: [Empty]

The following warning/error was logged by the smartd daemon:

TEST EMAIL from smartd for device: /dev/nvme0ns1

Device info:
CT500P3SSD8, S/N:2240E6733488, FW:P9CR30A, NSID:1

For details see host's SYSLOG.
FreeBSD es genial!.