NFS - Sistema de Ficheros en Red

ArticleCategory:

System Administration

AuthorImage:

TranslationInfo:

original in fr Frédéric Raynal
fr to en Philippe Trbich
en to es Roberto Hernando

AboutTheAuthor:

Frédéric Raynal está preparando una tesis en informática sobre el tatuaje en el INRIA. Está leyendo una buena novela policíaca en la que aparece Th.Roosevelt a principios de siglo cuando era precepto de policía. La atmósfera es muy lúgubre. Trata de la investigación que lleva a cabo un grupo de personas para encontrar a un asesino en serie que ataca a niños. Este grupo se ayuda de las nuevas tecnologías (psicología, huellas dactilares, etc...) para solucionar el caso. Esta novela de Caleb Carr, L'ange des ténèbres, pinta un asombroso retrato del comienzo del último siglo.

Abstract:

Un Sistema de Ficheros en Red (NFS-Net File System)permite manejar ficheros de distintos ordenadores dentro de una red como si estuvieran en el disco duro local. Es decir, no se necesita saber dónde están localizados físicamente los ficheros para poder acceder a ellos.

ArticleIllustration:

ArticleBody:

Introducción

NFS permite compartir datos entre varios ordenadores de una forma sencilla. Por ejemplo, un usuario validado en una red no necesitará hacer login a un ordenador específico: vía NFS, accederá a su directorio personal (que llamaremos exportado) en la máquina en la que esté trabajando.

Pero NFS no es un protocolo demasiado eficiente y es muy lento para conexiones mediante módem. Está diseñado para redes locales, siendo muy flexible. Ofrece muchas posibilidades tanto a usuarios como a administradores.

Deberá administrar este servicio con precaución. Permitir a cualquiera escribir en su red puede que realmente no sea una buena decisión ;-) Algunas acciones básicas pueden reducir los riesgos.

Este artículo comienza con una cortísima introducción a los sistemas de ficheros. Después veremos el protocolo NFS. Luego se irá a la parte menos teórica instalando un servidor y un cliente NFS. También echaremos un vistazo a las mínimas medidas de seguridad que deberá tomar. Después, con un ejemplo, ilustraremos como combinar NFS, NIS y autofs.

Presentación general y no exhaustiva de los sistemas de ficheros

Antes de hablar de NFS, deberá entender el concepto sistema de ficheros. Un sistema de ficheros es la forma de almacenar datos en un medio, la manera en que se organizan y manejan. Hay muchos sistemas de ficheros, algunos más utilizados que otros (New Technology FileSystem (NTFS), High Performance FileSystem (HPFS),DOS, FAT 12/16/32, VFAT, Macintosh Hierarchical Filesystem (HFS), ISO 9660(para CD-ROM), extended file systems (Ext, Ext2, Ext3), y muchos otros).

Por ejemplo, podemos considerar que cada medio físico para datos (como un disco duro) es un conjunto de pequeñas unidades que contienen la información: estamos hablando de los bloques. Cada sistema de ficheros maneja estos bloques de forma distinta. Por ejemplo en la figura 1 , se quiere insertar un fichero que consta de dos bloques. En la ilustración superior, el fichero se ha puesto después del último bloque ocupado, dejando espacios vacíos al principio. En la parte inferior de la figura (un sistema de ficheros diferente), se ha puesto en el primer lugar libre. Tal decisión influye en cuánto se va fragmentando el disco. Algunos sistemas de ficheros impiden automáticamente la fragmentación, mientras que otros necesitan ser defragmentados manualmente.


Fig. 1 : Dos formas distintas de colocar bloques.

El sistema de ficheros más común en Linux se llama ext2fs (extended 2 file system). Cada fichero está representado por un ínodo1. Los directorios contienen la lista de ficheros y el acceso al dispositivo se hace mediante operaciones como lectura/escritura en ficheros específicos.

La tarea de un servidor NFS es dar a sus clientes los ínodos a los que quiere acceder. ¡Sin embargo, un cliente no podría trabajar demasiado bien con únicamente el ínodo del fichero! Un servidor NFS provee una capa de red adicional permitiendo a máquinas remotas manejar los ínodos.

El protocolo NFS

Lo que comúnmente se llama NFS está formado por 4 protocolos distintos. Cada uno depende de las Remote Procedure Calls(RPC) y de portmap (también llamado rpc.portmap). Un portmapper convierte números de programa RPC en números de puerto. Cuando un servidor RPC se inicia, dice a portmap qué puerto usará y el número de programa RPC manejado. Cuando un cliente quiere enviar una petición RPC a un número de programa dado, primero contacta con el servidor portmap para tomar el número de puerto dando acceso al programa deseado. Después, dirige los paquetes RPC al puerto correspondiente.

Los 4 servicios que permiten funcionar a NFS son:
Protocolo
Descripción
Demonio
nfs Este protocolo es el básico y permite crear, buscar, leer o escribir ficheros. Este protocolo también maneja autentificación y estadísticas de ficheros.
nfsd
mountd Éste se encarga de montar sistemas exportados para acceder a ellos con nfs. El servidor recibe peticiones como mount y umount debiendo mantener información sobre los sistemas de ficheros exportados.
mountd
nsm
(Network Status Monitor) 
Se usa para monitorizar los nodos de la red y así conocer el estado de una máquina (cliente o servidor). Informa, por ejemplo, de un rearranque.
statd
nlm
(Network Lock Manager) 
Para impedir modificaciones de los datos por varios clientes al mismo tiempo, este protocolo maneja un sistema de bloqueo. Así, con la ayuda del protocolo Nsm es posible conocer cuándo se está reiniciando un cliente. Nsm libera todos los bloqueos del cliente antes de devolverlos.
lockd

El demonio knfsd, disponible con las últimas versiones del núcleo, soporta directamente los protocolos nfs y nlm. Por otro lado, mountd y nsm no están todavía soportados. Cuando el servidor NFS está instalado y arrancado, podemos verificar que todo esté funcionando con el comando:
 

>> ps auxwww | egrep "nfs|mount|lock|stat"
root      1370  0.0  0.2  1176  580 ?        S    22:28   0:00 rpc.mountd --no-nfs-version 3
root      1379  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1380  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1381  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1382  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1383  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1384  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1385  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1386  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [nfsd]
root      1399  0.0  0.0     0    0 pts/0    SW   22:28   0:00 [lockd]
root      1409  0.0  0.2  1156  560 ?        S    22:28   0:00 rpc.statd
root      1652  0.0  0.1  1228  484 pts/3    S    22:49   0:00 egrep nfs|mount|lock|stat
Por el momento, están disponibles dos versiones de NFS (versiones 2 y 3, que para distinguirlas denotaremos NFSv2 y NFSv3, respectivamente). Los servidores NFS de Linux sólo soportan la versión 2 (de aquí la opción en la línea mountd del ejemplo anterior).

NFS trata con una estructura de datos llamada file handle. Es una serie de bits bastante esotérica que permite identificar de forma única cada objeto del sistema de ficheros (como un fichero, pero no tan sólo ficheros). Contiene por ejemplo el ínodo del fichero y también una entrada representando el dispositivo donde se localizan. Por tanto, podemos ver NFS como un sistema de ficheros dentro de otro sistema de ficheros.

Instalación

El servidor

La primera cosa a hacer, como ya hemos visto, es iniciar portmap ya que este protocolo es necesario para NFS .
root >>/usr/sbin/rpcinfo -p
rpcinfo: can't contact portmapper: RPC: Remote system error - Connection refused
root >>/sbin/portmap
root >>/usr/sbin/rpcinfo -p
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
El comando rpcinfo muestra los servicios RPCs en la máquina especificada como argumento (opción -p). Notamos que portmap todavía no está funcionando: lo iniciamos (la mayoría de las distribuciones Linux proveen scripts para automatizar esto en el arranque) y comprobamos que funciona. Otra razón común para que rpcinfo responda negativamente es que el portmapper no permita la respuesta a causa de la restricción de seguridad en los ficheros /etc/hosts.{allow, deny}. En este caso, añada una entrada "portmap: hosts" en el fichero hosts.allow.

Antes de que NFS se inicie por sí mismo, debe ser configurado. Existe un único fichero de configuración que se llama /etc/exports. Cada línea muestra la ruta exportada seguido de una lista de clientes a los que se permite el acceso. Se pueden añadir opciones al final de cada nombre de cliente. La página de manual exports (man exports) explica la sintaxis para los nombres de cliente y las opciones.

Se aceptan como nombres de cliente:

No vamos a detallar aquí todas las opciones de montaje disponibles, pero algunas de las más importantes son: Ahora tenemos que iniciar los demonios rpc.mountd y rpc.nfs para tener funcionando el servidor NFS. Comprobamos nuevamente que todo está funcionando con el comando rpcinfo. Incluso podemos inicializar el servidor para los protocolos nsm y nlm (rpc.statd y rpc.lockd, respectivamente). No hay ninguna premisa para arrancar un servidor NFS... pero es altamente recomendable que se reinicie por sí mismo, en caso de que la máquina falle, etc...

Cuando modificamos el fichero de configuración /etc/exports, debemos avisar a los demonios implicados que se deben hacer los cambios. El comando exportfs transmite esta información a nuestros servidores. La opción -r sincroniza el fichero /etc/mtab2 con el fichero /etc/exports file. La opción -v muestra juntos todos los sistemas de ficheros exportados junto con sus opciones.

Después de ponerse en marcha el servidor NFS, los siguientes ficheros contienen información importante:

Cuando un cliente quiere acceder a un sistema de ficheros, empieza haciendo una petición mountd. Entonces se busca en etab si la petición está disponible. Se comprueba el núcleo para saber si el cliente tiene permitida la petición (comprobando hosts.{allow, deny}, reglas de cortafuegos, ...). El núcleo utiliza exportfs para la comprobación, permitiendo actualizar el fichero /var/lib/nfs/etab. Si, en este fichero, el sistema exportado tiene permitido ser exportado al grupo al que pertenece el cliente, entonces mountd informa al núcleo que actualice xtab con este nuevo host.

El cliente

No hay que hacer nada ... normalmente. El acceso al sistema de ficheros exportado por NFS está controlado directamente por el núcleo. Éste tiene que haber sido compilado para soportar NFS. El fichero /proc/filesystems contiene una lista con todos los sistemas de ficheros soportados directamente por el núcleo. Entonces, lo único que tiene que hacer es decir al núcleo que quiere acceder a un sistema exportado por NFS.

El comando mount permite acceder a diferentes sistemas de ficheros. Informa al núcleo que está disponible un nuevo sistema de ficheros indicando su tipo, su dispositivo y su punto de montaje. Se puede usar la opción -t  para indicar el tipo del sistema de ficheros a usar. Para NFS, escribimos: -t nfs.

mount tiene sus propias opciones para NFS. Por ejemplo, se pueden utilizar las opciones rsize y wsize para cambiar el tamaño de los bloques para lectura o escritura. Puede combinar opciones específicas de NFS con opciones más generales como intr, noexec o nosuid. La página de manual mount muestra todas esas opciones.

Supongamos que la máquina charly tiene un servidor NFS y exporta su directorio /usr/local. Cuando quiera acceder desde la máquina jill, tendrá que montar el directorio exportado de charly a jill:

root@jill >> mount -t nfs -o nosuid,hard,intr charly:/usr/local /usr/local
El comando indica que estamos montando un sistema de ficheros NFS (-t nfs), con las opciones nosuid, hard e intr. Los dos últimos argumentos son los más interesantes. El primero de ellos especifica el dispositivo a montar. Para NFS la sintaxis es distinta de la línea mount habitual, donde se especifica dispositivo y directorio. Aquí especificamos servidor:directorio_exportado en vez de dispositivo. El último argumento indica la localización del sistema de ficheros en la parte cliente. Hemos compartido exactamante el /usr/local de charly con jill y así podemos evitar el tener que instalar programas en /usr/local más de una vez. Para hacer esta configuración permanente, podemos especificarlo en el fichero /etc/fstab de jill. fstab contiene todos los dispositivos que serán montados en el arranque. La sintaxis para /etc/fstab es:
 
#    device           mount point   file system   options     dump  fsckorder
charly:/usr/local    /usr/local       nfs       nosuid,hard,intr    0      0

Sin embargo, deberá tener cuidado con una entrada permanente. Sólo podrá usarlo cuando el servidor (charly) esté siempre encendido, o cuando encienda charly antes que jill.

Precauciones

Uno de los mayores problemas con NFS viene del hecho de que exista por defecto una relación de confianza entre un cliente y un servidor NFS. En el caso de que la cuenta root del servidor esté comprometida, la del cliente también lo estará. El NFS-COMO describe un conjunto de medidas esenciales que debe tomarse para conseguir cierta seguridad..

Un cliente no debe confiar ciegamente en un servidor, por ello debemos especificar opciones restrictivas cuando usamos el comando mount. Ya hemos mencionado la primera de ellas: nosuid. Cancela el efecto de los bits SUID y GID. Con esto alguien que esté como root en el servidor primero debe hacer login en el cliente como un usuario normal y después hacerse root. Otra opción, más restrictiva, es noexec. Prohíbe ejecutar programas en sistema de ficheros exportado. Esta opción únicamente se utiliza en sistemas que sólo contengan datos.

En el lado del servidor NFS, podemos especificar que no confíe en la cuenta root del cliente. Tenemos que especificarlo en /etc/exports con la opción root_squash. Entonces si un usuario con UID 0 (root) en el cliente accediese al sistema de ficheros exportado por el servidor, tomaría el UID nobody para consultar ficheros. Esta opción está activada por defecto bajo Linux pero se puede desactivar con la opción no_root_squash. Se puede especificar qué opciones deben aplicarse en un conjunto de UIDs. Recuerde también que las opciones anonuid y anongid permiten cambiar los UID/GID de nobody por los de otro usuario diferente.

Algunas opciones son más generales y se efectúan por el portmapper. Por ejemplo, prohibimos el acceso a todas las máquinas con la siguiente línea en el fichero /etc/hosts.deny:
 

# hosts.deny : absolute prohibition for every one to
#              use the portmap
portmap: ALL

Después en el fichero /etc/hosts.allow esta estricta prohibición se puede contrarrestar permitiendo el acceso a las máquinas deseadas.

Unas buenas reglas de cortafuegos también contribuyen a una protección mejor. Observe los puertos usados por los diferentes servicios y los protocolos utilizados:
 

Servicio RPC Puerto Protocolos
portmap 111 upd / tcp
nfsd 2049 udp
mountd variable udp / tcp

Usando NIS, NFS y autofs

Fijémonos ahora en una red algo más complicada, como la que podrá encontrar e.g en una empresa. En una pequeña red en su casa probablemente pueda vivir sin NIS. El Servicio de Información en Red, NIS (Network Information Service) es una forma de distribuir ficheros de configuración (e.g en /etc) a otras máquinas.
El servidor principal en nuestra red se llamará "charly" y otras 3 máquinas de la red serán "sabrina", "jill" y "kelly". Configuramos charly como un servidor NIS para el dominio bosley. Las otras máquinas son tan sólo clientes NIS de charly (podríamos tener un servidor NIS secundario, pero hoy no es ése nuestro propósito).

Primero, veamos la configuración de nuestro servidor charly. Empezamos definiendo algunos mapas NIS que contienen toda la información necesaria.

El fichero /etc/netgroup contiene los grupos de máquinas con características comunes (una misma arquitectura, por ejemplo). Un mapa NIS es muy útil para NFS. Sólo tenemos que reunir todas las máquinas permitiéndoles acceder al mismo sistema de ficheros exportado. Entonces se usa este grupo en el fichero /etc/exports en lugar de especificar todos los clientes uno a uno:

# /etc/netgroup
charlysangels (sabrina,,) (jill,,) (kelly)
 Por lo que concierne a NFS, sabemos que la configuración es bastante restrictiva. El fichero /etc/exports de charly contiene:
# /etc/exports
/usr/local    @charlysangels(ro)
Decidimos utilizar automount para acceder al directorio exportado /usr/local. En vez de montar el sistema en el arranque, se hace automáticamente cuando un usuario accede a un fichero de este directorio.  Creamos el fichero /etc/auto.map para decidir qué será accesible por automount y NIS:
# /etc/auto.map
charly          charly:/usr/local
Como queremos integrar esta información (el nuevo auto.map y los ficheros netgroup) en la base de datos NIS, tenemos que modificar el Makefile antes de reconstruirlo. Debemos estar seguros de qué grupo accederá a la base. Por lo que respecta a auto.map, este fichero no está definido por defecto. Sólo tenemos que añadir una entrada en el Makefile, con la regla asociada (usando la existente como un modelo):
#To be added in the Yellow Pages Makefile
AUTO_MAP    = $(YPSRCDIR)/auto.map
# ...
#...
auto.map: $(AUTO_MAP) $(YPDIR)/Makefile
            @echo "Updating $@..."
            -@sed -e "/^#/d" -e s/#.*$$// $(AUTO_MAP) | $(DBLOAD) \
            -i $(AUTO_MAP) -o $(YPMAPDIR)/$@ - $@
            -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
Esta regla borra comentarios, añade una nueva entrada a la base de datos y después transmite la información a cada servidor

Sólo tenemos que ejecutar make desde el directorio /var/yp.

Ahora, tenemos tres clientes: sabrina, jill y kelly. Aquí, no hay que hacer nada :) Tenemos que decir a autofs que controle un nuevo mapa dado por YPs. En el fichero /etc/auto.master de cada cliente la siguiente línea informa de la presencia de una asignación auto.map obtenida vía los servicios de YP.

#/etc/auto.master
/usr/local    yp auto.map    --intr,nosuid,nodev
Después tenemos que reiniciar autofs para hacer este nuevo mapa efectivo.

Ahora tenemos un único directorio físico /usr/local en charly. Entonces, cuando se instale un programa específico en charly, todas las máquinas lo podrán usar.

Este ejemplo podría llevarse más lejos con la instalación de un único sistema /usr, /usr/doc u otros, pero la práctica muestra que no sería buena idea. Las instalaciones a menudo necesitan modificar ficheros en el directorio /etc o en otros. Tendríamos que actualizar todas las máquinas para actualizar ficheros no exportados, lo que sería tremendamente pesado.
 

Referencias

Sistemas de Ficheros

NFS


Notas

... ínodo1
Es un descriptor de fichero (una serie de bits) conteniendo, entre otros, permisos de acceso al fichero, propietario, direcciones de bloques físicos que contienen los datos, etc...
... /etc/mtab2
Este fichero contiene la lista de todos los sistemas de ficheros montados por el núcleo, tanto via mount, como los sistemas descritos en fstab, como via autofs/automount.