En este diseño se confunden dos permisos distintos: quién puede usar un directorio y qué direcciones pueden conectarse siquiera. Escribir una lista de cuentas junto a una lista de orígenes parece un emparejamiento, pero Samba evalúa las dos listas como predicados independientes. Se admite a cualquiera que satisfaga ambas, lo que es una regla más amplia de lo que la mayoría de los administradores pretende. La solución es o bien otro diseño del recurso o bien una capa de política que pueda expresar el par.

El mito: dos listas hacen una regla

La referencia de smb.conf define valid users y hosts allow como dos parámetros no relacionados, y es al poner ambos en un mismo recurso donde empieza la confusión. Pon valid users = mira, tomas y hosts allow = 10.77.0.21, 10.77.0.22 y se admiten cuatro combinaciones: Mira desde cualquiera de las dos direcciones y Tomás desde cualquiera de las dos direcciones. Nada en la configuración ata el primer nombre a la primera dirección, y el orden en que aparecen los nombres no tiene ningún significado. Reordenarlos, añadir una segunda línea hosts allow o poner un nombre por línea no cambia nada. El resultado es el producto de dos listas, no una correspondencia entre ellas.

Lo que la mayoría quiere en realidad es más estrecho: Mira solo desde una dirección y Tomás solo desde otra. Una sola definición de recurso no tiene sintaxis para esa vinculación, y ningún orden ingenioso la crea. Esa es una forma de política que Samba no expresa dentro de un solo recurso, y ahí sobrevive el mito.

Qué evalúa Samba y en qué orden

Las etapas siguen un orden fijo, y equivocar el orden produce el diagnóstico equivocado. Un cliente abre una conexión; se ejecuta una comprobación global de host si hay una configurada; la configuración de la sesión autentica la cuenta; después el cliente se conecta a un recurso, donde se aplican su propia lista de hosts, valid users y el ajuste de solo lectura; y solo cuando se abre un archivo deciden los permisos del sistema de archivos de la identidad autenticada. Cada etapa puede rechazar la petición por sí sola, y pasar una no dice nada de la siguiente. La consecuencia importante es que la cuenta ya se conoce cuando se evalúa la lista de hosts del recurso, y la lista de hosts sigue sin tener forma de nombrar esa cuenta.

Por eso un recurso no puede atar un usuario a una dirección: hosts allow y valid users son predicados separados que se aplican en la misma etapa de conexión del árbol, y cada uno responde a su propia pregunta. El predicado de host nunca toma el nombre de la cuenta como entrada, así que no puede escribirse por usuario. Solo un segundo recurso o una capa de política fuera de Samba pueden expresar el par.

Los valores globales importan por cómo se heredan. Un recurso que omite hosts allow hereda el valor global, y un recurso que establece el suyo usa ese valor en lugar del global, no además de él. Así, una lista global amplia amplía los recursos que nunca definen el parámetro y no hace nada a un recurso que define el suyo. Ejecuta testparm -s y lee los valores por recurso que imprime, porque esa salida es la política efectiva y el archivo del disco no lo es.

Restringir un recurso tampoco hace nada por el resto del servidor. Los demás recursos, las colas de impresión y la conexión IPC mantienen sus propias reglas, así que un diseño que se apoya en la lista de direcciones de un solo recurso protege un camino y no el host.

Dos nombres de recurso sobre un directorio

Cuando el mismo directorio tiene que ser accesible por dos personas desde dos direcciones, expónlo dos veces con nombres distintos. Cada bloque lleva una cuenta y un origen, lo que convierte el par en algo que la configuración puede imponer. El coste es que cada persona usa un nombre de recurso distinto para llegar a los mismos archivos, y eso tiene que ser un cambio deliberado en el lado del cliente.

[shared-mira]
    path = /srv/shared
    guest ok = no
    read only = yes
    valid users = mira
    hosts allow = 10.77.0.21
    hosts deny = ALL

[shared-tomas]
    path = /srv/shared
    guest ok = no
    read only = yes
    valid users = tomas
    hosts allow = 10.77.0.22
    hosts deny = ALL

Una puerta de recurso no es un permiso del sistema de archivos. Ambas identidades siguen necesitando acceso al directorio a través de la ACL subyacente, y el ajuste de solo lectura es una segunda capa y no la única. Concede acceso de escritura solo si el flujo de trabajo lo exige, y después comprueba que los archivos creados por una identidad siguen siendo utilizables por la otra.

Ambos bloques apuntan a una sola ruta, así que un cambio en el directorio afecta a los dos recursos. Normalmente ese es el objetivo, pero también significa que un error de permisos es visible para los dos usuarios a la vez.

Qué puede demostrar la dirección de origen

La dirección que ve Samba es la dirección que llegó al servidor, no la que el cliente cree tener. Una puerta de enlace VPN que traduce cada cliente a una sola dirección de origen elimina la distinción: todos los clientes llegan como el mismo host y la lista de orígenes ya no puede distinguirlos. Una asignación estable por cliente y una puerta de enlace que preserve el origen son requisitos previos para usar direcciones como política. Sin ambas, la restricción mide la puerta de enlace y no al usuario.

Aun así, una dirección no es un dispositivo. Dos portátiles detrás de una dirección de túnel, una concesión reasignada y una estación de trabajo compartida desmienten la suposición de que un origen identifica a una persona. Trata la restricción como ámbito de red y mantén las cuentas SMB autenticadas como la capa de identidad, con una credencial de dispositivo como un certificado si necesitas autorización de dispositivo.

Eso explica también por qué el diseño cierra recursos y no el servidor. Un par rechazado aún puede abrir una sesión, llegar a otro recurso o listar el servidor, lo que es un resultado distinto de un fallo de autenticación al conectar. Si el requisito es el rechazo antes de la autenticación, los parámetros de recurso de Samba son la herramienta equivocada.

Demuéstralo con pares cruzados

Valida la configuración y después prueba las cuatro combinaciones con conexiones nuevas en lugar de una sesión reutilizada. El par previsto debería llegar al directorio, y ambos pares cruzados deberían fallar. Una sesión en caché de una prueba anterior responderá encantada por la combinación equivocada y hará que una regla rota parezca correcta.

testparm -s
smbclient //fileserver/shared-mira -U mira -c 'ls'
smbclient //fileserver/shared-tomas -U tomas -c 'ls'
smbstatus --shares

Una comprobación de sintaxis solo demuestra que el archivo se analiza. Las credenciales, las ACL y la decisión de host se ejercen con una conexión real, así que ejecuta el comando del cliente desde la dirección que quieres probar y observa qué etapa lo rechaza. Si un par cruzado tiene éxito, la lista efectiva de hosts es más amplia de lo que sugiere el bloque, y testparm -s es lo primero que hay que leer. Si un par cruzado falla por el motivo equivocado, la cuenta o la ACL son los sospechosos.

Monitorizar sesiones con smbstatus y matarlas es una acción de respuesta posterior al inicio del acceso, no un control de admisión. Bloquear toda una dirección observada también puede desconectar a usuarios no relacionados detrás del mismo NAT, y por eso la decisión pertenece a la definición del recurso y la monitorización al proceso de respuesta. Mantén las dos cosas separadas y el diseño seguirá siendo honesto sobre lo que impone.

Artículos relacionados