Skip to main content

209.2 Configuração do Servidor NFS


Introdução


O NFS é um software que foi desenvolvido pela Sun Microsystem com o propósito de compartilhar diretórios na rede local por servidores Linux/Unix. Possui a arquitetura sendo cliente/servidor, tendo pacotes separados para cada um (como de costume); um conjunto de pacotes para o Servidor e outro para o Cliente.


Vamos a uma rápida introdução dos pacotes:

PacotesDistroDescrição
nfs-commonDebian likeUtilitário para o Cliente NFS.
nfs-kernel-serverDebian likePacote para o Servidor NFS.
nfs-utilsRedHat likeUtilitário para o Cliente NFS e Servidor NFS.

Para os testes instale o pacote destinado ao Servidor (ou ambos cliente e servidor, não faz mal).


Com o NFS instalado, podemos gerenciar o serviço:

# Serviço do NFS server:
$ systemctl status nfs-server.service
● nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; vendor preset: enabled)
Active: active (exited) since Wed 2023-04-12 23:55:39 UTC; 1min 36s ago
Main PID: 1937 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 460)
Memory: 0B
CGroup: /system.slice/nfs-server.service

Apr 12 23:55:38 ubuntu2004.localdomain systemd[1]: Starting NFS server and services...
Apr 12 23:55:39 ubuntu2004.localdomain systemd[1]: Finished NFS server and services.

# Serviço do rpcbind:
$ systemctl status rpcbind.service
● rpcbind.service - RPC bind portmap service
Loaded: loaded (/lib/systemd/system/rpcbind.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2023-04-12 23:55:33 UTC; 2min 52s ago
TriggeredBy: ● rpcbind.socket
Docs: man:rpcbind(8)
Main PID: 1293 (rpcbind)
Tasks: 1 (limit: 460)
Memory: 684.0K
CGroup: /system.slice/rpcbind.service
└─1293 /sbin/rpcbind -f -w

Apr 12 23:55:33 ubuntu2004.localdomain systemd[1]: Starting RPC bind portmap service...
Apr 12 23:55:33 ubuntu2004.localdomain systemd[1]: Started RPC bind portmap service.


NFS sobre TCP e UDP


Inicialmente, o NFS foi desenvolvido para trabalhar sobre UDP, porque esse protocolo oferecia melhor desempenho nas redes e nos servidores da época, especialmente no contexto do NFS versão 2. Como o UDP é um protocolo sem conexão e não garante a entrega dos dados, o uso do NFS sobre UDP exigia que o conjunto NFS/RPC lidasse com situações como timeouts, retransmissões e possíveis requisições duplicadas.


Ainda assim, ficava de fora um ponto importante, que é o controle de congestionamento. Esse controle é essencial para o bom desempenho em redes IP maiores, e nem o UDP nem o NFS implementavam esse recurso por conta própria.


Com o NFS versão 3, passou a ser possível escolher entre TCP e UDP como protocolo de transporte. Já no NFS versão 4, o TCP passa a ser o protocolo padrão exigido para a comunicação.


O NFSv4 utiliza a porta 2049 para o serviço NFS. As versões anteriores também podem utilizar essa porta, mas permitem mais variação na configuração, tanto em relação ao transporte quanto ao uso de serviços auxiliares. Por isso, em ambientes com NFSv2 e NFSv3, é comum precisar observar não apenas o serviço NFS em si, mas também os componentes RPC envolvidos na montagem e no registro dos serviços.


Por padrão, o NFS tende a preferir TCP quando essa opção está disponível. No entanto, nas versões 2 e 3, em que há uso do rpcbind, antigo portmap, a comunicação com serviços como rpcbind e mountd pode ocorrer via UDP, embora isso possa ser ajustado conforme a configuração do sistema.


O rpcbind normalmente escuta na porta 111. Já o mountd, por padrão, costuma escutar em uma porta aleatória, mas essa porta pode ser fixada manualmente. Isso é especialmente importante em servidores protegidos por firewall, porque, sem uma porta definida, a liberação do tráfego NFS pode ficar mais difícil de controlar.



RPCBIND


O rpcbind é o sucessor do antigo portmap/portmapper. Por isso, ainda é comum encontrar referências ao nome portmap ou portmapper em logs, documentação, ferramentas de análise de tráfego e na saída de comandos como rpcinfo -p.


O serviço escuta na porta 111/tcp e 111/udp. Sua função é mapear programas RPC para os endereços e portas em que esses serviços estão escutando. Quando um serviço RPC é iniciado, ele registra suas informações no rpcbind, quando um cliente precisa acessar esse serviço, ele consulta o rpcbind para descobrir para qual porta deve enviar a requisição.


O rpcbind é especialmente importante para NFSv2 e NFSv3, pois serviços auxiliares como rpc.mountd, rpc.statd e lockd podem usar portas dinâmicas. O cliente pode consultar o rpcbind para descobrir em quais portas esses serviços estão usando.


Em NFSv4, o uso do rpcbind é menor, porque o NFSv4 não usa um protocolo separado de montagem do mountd da mesma forma que NFSv2/NFSv3. Em uma configuração NFSv4 pura, o cliente normalmente acessa diretamente o serviço NFS na porta 2049/tcp. Mesmo assim, muitas distribuições ainda instalam ou mantêm rpcbind por compatibilidade com NFSv3 e outros serviços baseados em RPC.


Para verificar os serviços RPC registrados e suas portas, use:

rpcinfo -p

Os arquivos de configuração do rpcbind dependem da distribuição. Podem aparecer, por exemplo:

/etc/rpcbind.conf
/etc/default/rpcbind
/etc/sysconfig/rpcbind

Em sistemas Debian/Ubuntu, é comum encontrar /etc/default/rpcbind. Em sistemas Red Hat-like, pode aparecer /etc/sysconfig/rpcbind. Já configurações relacionadas às portas auxiliares do NFS, como mountd, statd e lockd, podem ser feitas em arquivos específicos do NFS, como /etc/nfs.conf, dependendo da distribuição e da versão dos pacotes.



Mountd


O daemon responsável pelo protocolo de montagem do NFS é o rpc.mountd. Em sistemas com systemd, ele normalmente é gerenciado pela unit nfs-mountd.service, mas o nome do daemon/binário continua sendo rpc.mountd.


O rpc.mountd implementa o lado servidor do protocolo NFS MOUNT, usado principalmente por NFSv2 e NFSv3. Quando um cliente NFSv3 tenta montar um export, o rpc.mountd verifica se o caminho solicitado e o endereço do cliente estão permitidos pelas regras de exportação. Se o acesso for permitido, ele retorna ao cliente um file handle para o diretório exportado.


O executável do daemon normalmente fica em:

/usr/sbin/rpc.mountd

O rpc.mountd pode receber opções pela linha de comando. Em versões atuais do nfs-utils, muitas dessas opções também podem ser configuradas em /etc/nfs.conf, especialmente na seção [mountd]. Em sistemas Debian/Ubuntu, também é comum encontrar configurações em /etc/default/nfs-kernel-server, nesse arquivo, a variável RPCMOUNTDOPTS pode ser usada para passar opções ao rpc.mountd, como:

RPCMOUNTDOPTS="--port 32767"

Fixar a porta do mountd é útil quando existe um firewall entre clientes e servidor NFS, principalmente em ambientes com NFSv3. Sem uma porta fixa, o rpc.mountd pode usar uma porta definida em /etc/services ou escolher uma porta efêmera, dependendo da distribuição e da configuração. Isso dificulta a criação de regras de firewall previsíveis.



NFSD


No Linux o nfsd não tem arquivo de configuração, assim como mountd, usa opções passadas como argumentos de linha de comando, inclusive, utilizam o mesmo arquivo /etc/default/nfs-kernel-server.


Por padrão o nfsd recebe um argumento numérico 8, isso especifica quantos threads de servidor bifurcar. Selecionar o número apropriado de threads nfsd é muito importante, se o número for muito baixo ou muito alto, o desempenho do NFS pode ser prejudicado.


O número ideal das threads vai depender do S.O. que vamos usar bem como do hardware. Se você notar que o comando ps geralmente mostra o nfsd no estado D (ininterrupto hibernação) e que alguma CPU ociosa está disponível, considere aumentar o número de threads. Se você encontrar a média de carga (conforme relatado pelo tempo de atividade) aumentando à medida que adiciona mais threads, você passou do limite, então deve diminuir a quantidade de threads.


Execute o nfsstat regularmente para verificar os problemas de desempenho que podem estar associados ao número de threads do nfsd. No FreeBSD, as opções --minthreads e --maxthreads permitem especificar o número de threads, usando um limite mínimo e máximo.


A variável usada pelo nfsd é chamada RPCNFSDARGS, no arquivo onde configuramos esses parâmetros (para deixar permanente) ela tem o nome de RPCNFSDCOUNT, tudo o que estiver nessa variável será importada para a variável RPCNFSDARGS. Seu script fica em /usr/sbin/rpc.nfsd e seu daemon chama-se nfs-kernel-server e tem um alias chamado nfs-server (para facilitar as coisas 🙂).


Em ambientes RedHat o arquivo nfs-kernel-server fica em /etc/sysconfig/nfs.



Compartilhamento e Montagem


A montagem de diretório é feita no arquivo /etc/exports, e nele é possível determinar qual versão vamos usar no NFS dependendo da forma como vamos configurar:

# Edite o arquivo abaixo:
$ sudo vim /etc/exports

## Essa configuração exporta o diretório '/dados' para todas as máquinas em todas as redes que esse servidor tem acesso, usando as opções padrões.
/dados *(rw,sync,no_subtree_check)

## Essa configuração exporta o diretório '/dados1' para todas as máquinas na rede informada.
/dados1 192.168.1.0/24(rw,sync,no_subtree_check)

## Essa configuração exporta o diretório '/dados2' para duas redes.
/dados2 192.168.1.0/24(rw,sync,no_subtree_check) 192.168.2.0/24(rw,sync,no_subtree_check)

# Agora vamos exportar todos esses compartilhamentos:
$ sudo exportfs -a

Dica

Para mais detalhes nas opções de montagem leia aqui.


Ainda é possível montar um diretório temporariamente usando o comando exportfs:

exportfs 192.168.1.220:/etc -o ro,sync,no_subtree_check

Agora vamos ver como montar esse diretório no servidor cliente:

$ sudo mount -t nfs 192.168.1.155:/dados /mnt

# Verifique se montou:
$ df -Th /mnt/
Filesystem Type Size Used Avail Use% Mounted on
192.168.1.155:/dados nfs4 124G 3.5G 114G 3% /mnt


Configurações e Segurança


O NFSv4 (versão 4 do Network File System) utiliza um conceito chamado de "pseudo file system", que é uma camada de abstração entre o sistema de arquivos do servidor e o cliente que está montando esse sistema de arquivos remoto.


Explicação extra - Não cai na LPIC-2

A partir desse ponto estou detalhando um pouco sobre o NFSv4, caso queira entender, mas a explicação acima já cobre os requisitos da LPIC-2.


O pseudo filesystem é uma representação virtual do sistema de arquivos remoto que permite que o cliente acesse e manipule os arquivos e diretórios remotos de maneira transparente, como se eles estivessem em um sistema de arquivos local.


O NFSv4 usa o pseudo filesystem para criar uma visão unificada do sistema de arquivos remoto para o cliente, independentemente do sistema de arquivos do servidor, o que significa que o cliente não precisa conhecer ou entender o sistema de arquivos subjacente para acessar os arquivos remotamente.


Além disso, o pseudo filesystem permite que o NFSv4 ofereça recursos avançados, como gerenciamento de atributos de arquivos e diretórios, controle de acesso a arquivos e integridade de dados, que não seriam possíveis sem essa camada de abstração.


Um jeito de entender esse pseudo filesystem é o seguinte, faça qualquer export no lado do servidor, não importa o que.

# No lado do servidor:
/home/vagrant *(rw,sync,no_subtree_check)

# Agora no cliente, vamos montar a "raiz do servidor":
$ sudo mount -t nfs 192.168.1.155:/ /mnt

# Verifique se montou:
$ df -Th /mnt/
Filesystem Type Size Used Avail Use% Mounted on
192.168.1.155:/ nfs4 124G 3.5G 114G 3% /mnt

# Agora com a raiz montada, podemos ver tudo que tem no servidor, correto? (não)
$ ls -lh /mnt
total 4.0K
drwxr-xr-x. 3 root root 4.0K Feb 16 02:28 home

Perceba que só montou o que tinha exportado no servidor, porque ele montou o pseudo filesystem e não o filesystem real. Essa é uma técnica usada agora na versão 4, caso queira montar tudo que o servidor está compartilhando, pode montar somente a raiz, ao invés de montar diretório por diretório.


Ainda podemos usar o parâmetro fsid=0 para definir qual diretório será a raiz do pseudo filesystem:

# No lado do servidor:
/home/vagrant *(rw,sync,no_subtree_check,fsid=0)

# Re-exporte tudo:
$ sudo exportfs -r

# Agora monte a raiz no lado do cliente:
$ sudo mount -t nfs 192.168.1.155:/ /mnt

# Verifique se montou:
$ df -Th /mnt/
Filesystem Type Size Used Avail Use% Mounted on
192.168.1.155:/ nfs4 124G 3.5G 114G 3% /mnt

# Agora veja o que tem na raiz:
$ ls -lh /mnt
total 0

Nesse caso não vai exibir nada porque estamos dentro da home do usuário vagrant, porque alteramos o local da raiz, ao invés de começar em /, permitindo que conseguíssemos ver o caminho completo como /home/vagrant, agora começa dentro de /home/vagrant/, não permitindo ver o caminho completo mais.



Versão padrão do NFS


Atualmente, a versão padrão do NFS é a 4.2. Portanto, quando os clientes NFS tentam montar um sistema de arquivos, eles tentam usar o protocolo NFSv4.2. Caso o servidor não suporte o NFSv4.2, o cliente volta para o protocolo NFSv4.1. Se esse protocolo também não for suportado, o cliente tenta usar o NFSv4.0 e, se ainda não for possível, o cliente retorna para o NFSv3.



Sobre a Configuração do Servidor para NFSv3


Na versão atual do NFS no Debian, a configuração --no-nfs-version não funciona corretamente, pois essa opção simplesmente não é lida se incluída no parâmetro RPCMOUNTDOPTS, o que pode ser considerado um bug. No entanto, é possível realizar a configuração incluindo a opção no parâmetro RPCNFSDCOUNT, no mesmo arquivo de configuração, como mostrado abaixo:

RPCNFSDCOUNT="8 --no-nfs-version 4"

É importante lembrar que, do lado do cliente, também é possível definir a versão do NFS que deseja utilizar, utilizando a opção nfsvers=3 ou vers=3 no comando mount ou no arquivo /etc/fstab.


Caso o servidor seja baseado em CentOS ou Red Hat, é possível encontrar o arquivo /etc/nfs.conf, onde é possível habilitar ou desabilitar as versões do NFS que deseja utilizar.



Sobre Configurações de Segurança


É importante observar que as configurações de bloqueio via TCP Wrapper funcionam apenas para conexões que utilizam a versão 3 do NFS. Com as mudanças implementadas na versão 4 do NFS, é recomendado que o controle de acesso seja realizado por meio de firewall ou pelas opções de autenticação disponíveis. Você pode encontrar mais informações sobre isso neste link.



Desativando a versão 4


No lado do servidor, vamos desativar o uso da versão 4, lembrando que é uma prática nao recomendada.


# Edite o arquivo abaixo:
$ sudo vim /etc/default/nfs-kernel-server

## Na opção abaixo:
RPCNFSDCOUNT=8

## Adicione '--no-nfs-version 4' como abaixo:
RPCNFSDCOUNT="8 --no-nfs-version 4"


# Agora reinicie o serviço do NFS:
$ sudo systemctl restart nfs-server