Capítulo 11
El Sistema Ficheros en Red (NFS)
NFS, acrónimo de Network File System, que nosotros llamaremos Sistema de Ficheros en Red, es probablemente el servicio más complejo de los que se ofrecen usando RPC. Permite acceder a los ficheros remotos exactamente igual que si fueran locales. Esto se hace programando parte de la funcionalidad a nivel del núcleo (en el lado del cliente) y la otra parte como un demonio servidor. El acceso a los ficheros es totalmente transparente al cliente, funcionando con muchas arquitecturas de servidores.
NFS ofrece numerosas ventajas:
o Los datos accedidos por todo tipo de usuarios pueden mantenerse en un nodo central, con clientes que montan los directorios en el momento de arrancar. Por ejemplo, puede mantener todas las cuentas de usuario en una máquina, y hacer que las demás monten dichas cuentas en su directorio /home por NFS. Si además se instala NIS, los usuarios podrían entrar y trabajar de forma transparente en cualquiera de las máquinas.
o Los datos que consumen grandes cantidades de espacio de disco pueden mantenerse en un nodo. Por ejemplo, mantener una sola copia de LATEX en lugar de copiarlo en cada nodo.
o Los datos de administración pueden también mantenerse en un solo nodo. Ya no será necesario usar rcp para instalar el mismo fichero en 20 máquinas distintas.
El NFS de Linux es, principalmente, obra de Rick Sladkey,1, pues escribió el código que corresponde al núcleo y buena parte del código del servidor NFS. Este último es una modificación del servidor unfsd que corre en espacio de usuario, escrito originalmente por Mark Shand, y el servidor hnfs (Harris NFS) escrito por Donald Becker.
_____________________________________________
1 Puede contactar con Rick en la dirección jrs@world.std.com
Veamos ahora un poco como funciona NFS: un cliente puede solicitar montar un directorio desde un servidor remoto, de forma similar a como montaría un directorio local. Sin embargo, la sintaxis no es exactamente igual. Por ejemplo, para montar el directorio /home del nodo vlager en el directorio /users de vale, el administrador escribiría el siguiente comando en vale:2
# mount -t nfs vlager:/home /users
mount intentará conectar con el demonio remoto mountd mediante RPC. El servidor comprobará si la máquina vale tiene permiso para montar el directorio pedido, y si es así retornará un descriptor de fichero. Este descriptor se utilizará en todas las peticiones que sobre ficheros de /users se realicen posteriormente.
Cuando alguien accede a un fichero remoto, el núcleo manda una llamada RPC al programa nfsd (demonio de NFS) del nodo remoto. Esta llamada incluye el descriptor de fichero, el nombre del fichero a acceder y los identificadores de usuario y de grupo del demandante. Estos identificadores se usan para chequear permisos de acceso en la máquina remota, con lo que los usuarios de ambas máquinas deberían ser los mismos.
En varias implementaciones de UNIX, las funcionalidades de cliente y servidor NFS se realizan como demonios de nivel de núcleo que se arrancan desde el espacio de usuario al arrancar la máquina. Se trata del programa nfsd en el servidor y del programa biod (Block I/O Daemon, o demonio de E/S3 por bloques) en el cliente. Para aumentar el rendimiento, biod realiza E/S asíncrona, y a veces corren concurrentemente varios servidores de NFS.
La implementación de NFS en Linux es algo diferente: el código de cliente está integrado en la capa de sistema de ficheros virtual (VFS) y no requiere control adicional mediante el programa biod. Por otro lado, el código de servidor corre totalmente en el espacio de usuario, por lo que ejecutar varias copias del nfsd resulta imposible debido a los problemas de sincronización que originaría.
El mayor problema con el código NFS de Linux es que el núcleo 1.0 no puede manejar bloques de memoria de mas de 4Kb, por lo que el código de red no puede manejar datagramas de un tamaño mayor que 3500 octetos una vez eliminadas las cabeceras. Esto significa que las transferencias con servidores NFS que utilicen datagramas grandes por defecto (por ejemplo, los 8Kb de SunOS) necesitan ser reducidos artificialmente. Esto produce perdidas de rendimiento en ciertas circunstancias.4 Esta limitación desapareció en los núcleos posteriores al 1.1, reescribiéndose el código del cliente para aprovechar la nueva situación.
_____________________________________________
2 Observar que puede omitirse la opción -t nfs, ya que el programa mount
sabe por la aparición de los dos puntos (:) que se trata de un sistema
NFS.
3 N. del T.: E/S es Entrada/Salida
4 Como me explicó Alan Cox: La especificación de NFS requiere
que el servidor guarde cada escritura en disco antes de retornar un reconocimiento
al cliente (ACK). Como los núcleos de BSD solo manejan
11.1 Preparación de NFS
11.2 Montaje de un volumen NFS
11.3 Demonios de NFS
11.4 El fichero exports
11.5 El sistema de automontado en Linux
Antes de usar NFS, sea en cliente o servidor, debe asegurarse de que el núcleo tiene el soporte incluido. Los núcleos modernos informan de ello a través del sistema /proc, con un comando como el siguiente:
$ cat /proc/filesystems
minix
ext2
msdos
nodev proc
nodev nfs
Si no aparece la palabra nfs, tendrá que recompilar el núcleo con el soporte NFS habilitado. Sobre como configurar el núcleo hablamos en la sección "Configuración del Núcleo" del capítulo 3.
Con versiones del núcleo anteriores a la 1.1, la forma de comprobarlo es intentar montar un sistema NFS de prueba, de la siguiente forma:
# mkdir /tmp/test
# mount localhost:/etc /tmp/test
Si el comando mount falla con el mensaje "fs type nfs no supported by kernel" (sistema tipo NFS no soportado por el núcleo), deberá recompilar el núcleo habilitando NFS. Otro tipo de errores no implican recompilar el núcleo, ya que se producen al no estar corriendo el programa nfsd.
11.2 Montaje de un volumen NFS
Los volúmenes NFS5 se montan como los sistemas de ficheros usuales. Se trata de llamar al comando mount con la sintaxis:
# mount -t nfs volumen_nfs directorio_local opciones
_____________________________________________
5 Hablamos de volúmenes, y no de sistemas de ficheros, porque no lo son realmente: pueden ser solo directorios de un sistema.
La parte volumen_nfs se especifica con la sintaxis "nodo_remoto :directorio_remoto".
Dado que esta notación es propia del NFS, la opción -t nfs resulta redundante.
Hay otras opciones que pueden incluirse en el programa mount, que van tras el modificador -o en la línea de comando o en el campo de opciones de la entrada correspondiente en el fichero /etc/fstab. En ambos casos, las distintas opciones deben separarse por comas.
Las opciones que se especifiquen en la línea de comandos tendrán preferencia sobre otras que se indiquen en /etc/fstab.
Una entrada de ejemplo del fichero /etc/fstab podría ser
# volumen directorio tipo opciones
news:/usr/spool/news /usr/spool/news nfs timeo=14,intr
Ahora el volumen anterior puede montarse con la orden
# mount news:/usr/spool/news
Ante la ausencia de una entrada en fstab, las llamadas al programa mount se hacen más incómodas. Por ejemplo, puede que tenga que teclear cosas como ésta, para especificar que se limite el tamaño del datagrama a 2 Kb:
# mount moonshot:/home /home -o rsize=2048,wsize=2048
La lista de todas las opciones válidas para mount se encuentra descrita en la página de ayuda nfs(5) que viene con la utilidad de montaje de Rick Sladkey, que forma parte del paquete util-linux de Rik Faith. Las opciones más interesantes son las siguientes:
rsize=n y wsize=n
Especifican el tamaño de datagrama utilizado por el cliente NFS en las peticiones de lectura y escritura, respectivamente. Por defecto, cada una de ellas vale 1024 octetos, dados los límites del tamaño de datagrama UDP ya comentados.
timeo=n
Esta opción establece el tiempo máximo de espera de respuesta a una petición del cliente NFS; en centésimas de segundo. Por defecto, este valor es de 0.7 segundos.
hard
Marca el montaje del volumen como físico. Es un valor por defecto.
soft
Hace que el montaje sea solo lógico (opuesto al anterior).
intr
Esta opción habilita la posibilidad de que una señal interrumpa una espera por NFS.
Es útil para poder abortarla cuando el servidor no responde.
Cuando el cliente realiza una petición al servidor NFS, esperará un tiempo máximo (el que se especifica en la opción timeout). Si no hay confirmación tras ese tiempo (tiempo que se denomina "de expiración" o timeout) tiene lugar otra espera, "de expiración secundaria" o minor timeout, en el que la operación se reintenta pero doblando el tiempo de expiración inicial. Tras 60 segundos, se retorna a la expiración principal o major timeout.
Por defecto, la expiración principal hará que el cliente envíe un mensaje a la consola y empiece de nuevo, con una expiración del doble de tiempo. Potencialmente, esto podría mantenerse eternamente. En este caso se habla de montaje físico o hard-mount. La otra variedad, el montaje lógico o soft-mount, genera un mensaje de error de E/S al proceso llamante cuando se produce la expiración principal. El error no se propaga al proceso hasta que hace una nueva llamada a write(2), por lo que esto, junto con la política de escritura desde la cache, hace que no se sepa realmente si una operación de escritura ha tenido éxito o no, a menos que el volumen esté montado de forma física.
En general, se recomienda el montaje físico salvo en caso de tratarse de información no crítica, como la de servidores de FTP o particiones de noticias. En entornos críticos (por ejemplo, estaciones de trabajo X con dependencia de servidores de aplicaciones X Window) no debe usarse el montaje lógico a riesgo de perder las conexiones si en un momento se satura o desactiva la red por algún motivo. Una solución alternativa a usar montajes físicos es aumentar el valor de la opción timeo, o bien usar montajes físicos pero permitiendo el envío de señales para interrumpir las esperas en caso de necesidad.
Normalmente, el demonio mountd llevará de alguna forma un registro de que directorios están montados desde que máquinas. El programa showmount, incluido en el paquete de aplicaciones NFS, permite consultar esta información. De todas formas, el mountd de Linux aun no lleva estos registros.
Si desea proporcionar un servicio NFS a otras máquinas, deberá ejecutar en el servidor los programas nfsd y mountd. Son programas basados en RPC, por lo que no son arrancados desde el inetd, sino lanzados como demonios en tiempo de arranque, y registrados en el mapeador de puertos de RPC. Por lo tanto, debe asegurarse que previamente ha sido lanzado el programa rpc.portmap. Normalmente, esto implica las siguientes líneas en los scripts de arranque rc:
if [ -x /usr/sbin/rpc.mountd ]; then
/usr/sbin/rpc.mountd; echo -n " mountd"
fi
if [ -x /usr/sbin/rpc.nfsd ]; then
/usr/sbin/rpc.nfsd; echo -n " nfsd"
fi
La información de propiedad de los ficheros que un servidor NFS proporciona a sus clientes viene dada en valores numéricos de identificador de usuario (uid) y de grupo (gid).
Por lo tanto, esto resultará útil si clientes y servidores tienen el mismo mapa de usuarios y grupos, lo que sucede cuando dicho mapa se obtiene en todos los nodos desde un servidor NIS central.
Sin embargo, hay veces que esto no sucede. En lugar de actualizar los uids y gids del cliente para ponerse de acuerdo con los del servidor, puede usarse el demonio ugidd para hacer este trabajo. Utilizando la opción map_daemon explicada después, se indicará a nfsd que establezca una correspondencia entre uid/gid del servidor y del cliente, con la ayuda, en el cliente, de ugidd.
ugidd es un servidor basado en RPC, y se inicia también en los scripts rc, con una línea:
if [ -x /usr/sbin/rpc.ugidd ]; then
/usr/sbin/rpc.ugidd; echo -n " ugidd"
fi
Mientras que las opciones anteriores se aplican a la configuración del cliente NFS, hay otras opciones que se aplican al servidor, que afectan a su relación con cada posible cliente. Estas opciones se incluyen en el fichero de sistemas exportados /etc/exports.
Por defecto, mountd no permitirá a nadie montar directorios de su máquina. Para permitir que algún nodo monte un directorio, éste debe estar exportado, es decir, especificado en el fichero de exportación. Un ejemplo de dicho fichero es el siguiente:
# Fichero de exportación para vlager (/etc/exports)
/home vale(rw) vstout(rw) vlight(rw)
/usr/X386 vale(ro) vstout(ro) vlight(ro)
/usr/TeX vale(ro) vstout(ro) vlight(ro)
/ vale(rw,no_root_squash)
/home/ftp (ro)
Cada línea define un directorio, y la lista de máquinas que pueden acceder a él por NFS. Un nombre de máquina puede especificarse con su nombre internet completo, aunque también se permite el uso de los comodines * y ?, que se interpretan como en el shell de Bourne. Por ejemplo, lab*.prueba.com encaja con cualquier nodo con nombre similar a laboratorio.prueba.com o lab12.prueba.com, etc. Cuando en una línea de /etc/exports no se indique el nombre del nodo, se asume que cualquier máquina podrá montar el directorio (así sucede en nuestro ejemplo con /home/ftp).
mountd usa la llamada gethostbyaddr(2) para comprobar si el cliente demandante tiene un nombre de los que aparecen en /etc/exports. Con DNS, la llamada retorna el nombre canónico con lo que debe evitar usar nombres de alias en el fichero de exportación6. Si no usa DNS, el nombre devuelto por la llamada anterior será el primer nombre que coincida con el IP del demandante, en el fichero /etc/hosts.
Tras el nombre del nodo autorizado, se puede encerrar entre paréntesis un conjunto de opciones separadas por comas. Dichas opciones son:
insecure Permitir acceso no autentificado desde ese nodo.
unix-rpc Requerir autentificación RPC del dominio Unix para este nodo. Se trata simplemente de que las peticiones se originen en un puerto reservado (es decir, inferior al 1024). Esta opción está activa por defecto.
secure-rpc Requerir autentificación RPC segura para este nodo. Aun no está implementado. Se sugiere ver la documentación de Sun al respecto (véase, "Secure RPC").
kerberos Requerir autentificación Kerberos. Tampoco se ha implementado aun. Se sugiere consultar la documentación del MIT.
root_squash Se trata de una opción de seguridad que deniega acceso a nivel de superusuario, traduciendo el identificador uid recibido (0) al del usuario nobody. Es decir, cualquier petición NFS del usuario root será tomada como si fuera del usuario nobody.
no_root_squash Evita la restricción anterior. Es una opción por defecto.
ro Monta la jerarquía de ficheros en modo de solo lectura. Es una opción por defecto.
rw Monta el directorio con permiso para leer y escribir en él.
_____________________________________________
6 Ver capítulo 6
link_relative Convierte enlaces simbólicos absolutos (que empiezan con una barra de directorio, "/") en enlaces relativos colocando los prefijos "../ " que sean necesarios para hacer que apunten a la raíz del servidor. Esta opción solo tiene sentido cuando se monta un sistema de ficheros completo y no solo un directorio. Así, si montamos dicho sistema bajo /mnt y existe en /mnt/sub un enlace fichero ! /tmp/fichero se convertirá a fichero ! ../tmp/fichero logrando así que el enlace sirva para algo. Es una opción activa por defecto.
link_absolute Deja los enlaces absolutos como estaban (es la opción habitual en servidores NFS de Sun).
map_identity La opción map_identity indica al servidor que asuma que el cliente utiliza el mismo mapa de uids y gids que el servidor. Es una opción por defecto.
map_daemon Esta opción indica al servidor NFS que no comparte el mapa de usuarios con el del cliente. Con ello, las comparaciones de uids y gids se harán mediante una lista de mapeado entre ambos que se construirá llamando al demonio ugidd del cliente.
Cualquier error analizando el fichero de exportaciones durante el arranque del servidor nfsd o mountd será enviado a nivel de notificación (notice) al registro del sistema (syslogd).
Obsérvese que los nombres de los nodos se obtienen a partir de las direcciones IP mediante resolución inversa, con lo que el sistema de resolución deberá tener una adecuada configuración en este punto. Si utiliza BIND y la seguridad le preocupa especialmente, deberá activar chequeo de nombres falsos (spoofing) en el fichero host.conf.
11.5 El sistema de automontado en Linux
A veces es ineficiente mantener montados todos los volúmenes NFS de uso potencial. Una alternativa es usar un demonio de automontado. Se trata de un demonio que automáticamente monta los volúmenes cuando se necesitan y los desmonta tras un tiempo de inactividad.
Además, sirve para poder montar los mismos ficheros de un lugar diferente. Por ejemplo, puede mantener varias copias de las utilidades de X Window y a la hora de ser necesitadas, intentar montar cada copia hasta conseguirlo.
El programa de automontado para Linux se llama amd. Ha sido escrito inicialmente por Jan-Simon Pendry para luego encargarse Rick Sladkey de portarlo a Linux. La versión actual es la 5.3.
Explicar el uso de amd excede los objetivos de este capítulo. El mejor manual se encuentra en las fuentes: un fichero texinfo con información muy detallada.