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 em cima do UDP, porque ele tinha o melhor desempenho nas Redes e nos Servidores daquela época (estamos falando do NFS versão 2), o NFS por esse motivo (trabalhar com UDP) fazia remontagem da sequência dos pacotes e verificação de erros (já que o UDP não faz), mas ainda fica de fora algo muito importante, controle de congestionamento, ele é essencial para o bom desempenho de redes IP de grande porte (nem UDP nem NFS fazem isso). Na versão 3 do NFS, podemos escolher entre TCP ou UDP, e na versão 4 do NFS, temos somente o uso do TCP.


O NFS versão 4 requer TCP como protocolo padrão de transporte e se comunica na porta 2049. Já as versões anteriores podem ter sua porta modificada, assim como o protocolo de transporte.


Por padrão, o NFS sempre vai preferir o TCP, mas para versão 2 e 3, onde temos o uso do rpcbind (antigo portmap), a comunicação com o rpcbind e com o mountd é feita infelizmente usando UDP (mas é modificável).


Rpcbind escuta na porta 111 e mountd fica escutando numa porta aleatória por padrão, mas você pode mudar ela.



RPCBIND


Antigamente era chamado de portmap, ainda hoje é possível ver logs e registros usando esse nome, como no Wireshark (ainda usa o nome portmap). Escuta requisições na porta 111 (tcp/udp), sua função é informar ao cliente NFS a porta que o daemon do NFS/mountd está usando, dessa forma, o cliente sabe em qual porta se conectar.


Seu arquivo de configuração fica em /etc/default/rpcbind, mas pode ser usado um outro arquivo, localizado em /etc/rppcbind.conf (normalmente esse segundo arquivo não existe, tendo somente o primeiro arquivo).



Mountd


No Linux o daemon do mountd chama-se nfs-mountd.service, mountd não possui um arquivo de configuração, ele usa opções passadas como argumento ao script, essas opções podem ser colocadas num arquivo, assim sempre teremos as mesmas opções sendo fornecidas ao mountd. Ao reiniciar o daemon do nfsd, as configurações do mountd também são recarregadas, isso ocorre porque o daemon do nfsd está configurado para ter esse comportamento (reiniciar o serviço do mountd junto ao nfsd), por isso, muitas vezes só precisamos reiniciar o nfsd (mountd acabará sendo reiniciado também).


Seu script fica em /usr/sbin/rpc.mountd. Como mountd roda em portas aleatórias, isso cria uma dificuldade para gerenciar todas as portas no firewall, por isso vamos ver como alterar/fixar sempre a mesma porta.


Acesse o arquivo /etc/default/nfs-kernel-server, nesse arquivo vai ter uma variável usada pelo daemon do mountd, chamada RPCMOUNTDOPTS, para fixar uma porta use a opção --port <porta>.



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.


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