Come configurare smartphone e PC. Portale informativo
  • casa
  • Windows Phone
  • Cos'è l'NFS? File system di rete. Protocollo di accesso al file system di rete

Cos'è l'NFS? File system di rete. Protocollo di accesso al file system di rete

NFS ti consente di condividere directory su una macchina Unix. L'insicurezza di NFS, e in particolare di NIS, è associata a RPC: in termini di numero di vari exploit, RPC sembra essere il leader non ufficiale (ad eccezione di Sendmail). Poiché questi protocolli sono destinati a reti interne, dovranno essere protetti dai “loro” utenti. Anche se prima di usarli devi decidere se sono realmente necessari.

Su una rete domestica possono essere molto utili, ma su una rete aziendale, per motivi di sicurezza, è meglio trovare un'alternativa più sicura.

File system NFS.

Il Network File System (NFS) è stato sviluppato da Sun come mezzo per accedere ai file situati su altre macchine Unix all'interno di una rete locale. NFS non è stato progettato pensando affatto alla sicurezza, il che ha portato a molte vulnerabilità nel corso degli anni.

NFS può essere eseguito su TCP o UDP e utilizza un sistema RPC, il che significa che devono essere in esecuzione le seguenti applicazioni comunemente vulnerabili: portmapper, nfs, nlockmgr (lockd), rquotad, statd e mountd.

Non è necessario eseguire NFS: è necessario trovare una soluzione alternativa. Se NFS è ancora necessario, qui parleremo di come ridurre al minimo il rischio di utilizzarlo.

/etc/export

Il primo passo è selezionare le macchine che esporteranno i propri file system. Quindi puoi determinare quali macchine sono autorizzate a connettersi ai server NFS (o server, se presente) sulla rete. Non è necessario utilizzare NFS su macchine direttamente (direttamente) connesse a Internet. Dopo aver selezionato le macchine, è necessario selezionare le directory su queste macchine che verranno esportate.

Le directory di esportazione sono definite nel file /etc/exports. Il formato di ciascuna voce è semplice: nome della directory, elenco degli utenti autorizzati ad accedere e modalità di accesso. Per esempio:

L'accesso completo (lettura/scrittura) alla directory /home/utente è consentito alla macchina con indirizzo IP 10.0.0.6. La cosa migliore è non dare pieno accesso, ma limitarlo all'accesso di sola lettura (ro). Oltre a ciò, puoi anche specificare le seguenti opzioni:

  • Sicuro- la richiesta di montaggio deve provenire da una porta privilegiata (numerata fino a 1024). Ciò significa che il comando mount è stato immesso da un utente con privilegi root.
  • Root_zucca- una richiesta dell'utente root verrà considerata come una richiesta di un utente anonimo. Ciò consente di causare il minor danno al sistema. Questa opzione deve essere abilitata.
  • Tutto_zucca- tutte le richieste (non solo dall'utente root) verranno considerate come provenienti da un utente anonimo. Utile per le directory esportate pubblicamente.

Se un cracker con accesso root ottiene l'accesso a una macchina a cui è stato concesso l'accesso rw alla directory specificata in /etc/exports, otterrà il pieno controllo del file system, quindi non potrà esportare la directory root (/), e system- directory importanti, ad esempio /usr, /bin, /sbin, /lib, /opt e /etc. Le directory home degli utenti sono adatte per l'esportazione.

Sul lato client, il montaggio di un file system condiviso deve essere effettuato specificando l'opzione -o nosuid:

# mount -t nfs -o nosuid 10.0.0.3:/home/utente/files /mnt/home/frank

Ciò impedirà a un cracker che ha accesso al server NFS di ottenere l'accesso root ai client.

Limitazione dell'accesso.

Indipendentemente dal servizio, IPTables deve essere utilizzato per limitare l'accesso alla macchina. Nel caso di un server NFS ciò è particolarmente importante. Quando si utilizza IPTables, è necessario ricordare che il demone NFS utilizza la porta 2049/TCP/UDP.

Alcuni servizi RPC, come portmapper e NFS, utilizzano porte persistenti (rispettivamente 113 e 2049/tcp/udp), ma altri servizi RPC hanno porte non persistenti, il che rende difficile filtrare i pacchetti utilizzando IPTables. L'unica cosa nota è che gli RPC utilizzano le porte nell'intervallo 32768-65535.

Se stai usando il kernel 2.4.13 o successivo, usa l'opzione -p<порт>è possibile specificare la porta esatta per ciascun servizio RPC.

Diamo un'occhiata alla funzione start() da /etc/rc.d/init.d/nfslock, che viene utilizzata per avviare nsflock:

inizio()(

#. Avvia i demoni.

se ["$USERLAND_LOCKD"]; Poi

echo -n $"Avvio del blocco NFS: "

demone rpc.lockd

echo -n $"Avvio di NFS statd: "

demone rpc.statd

echo [ $RETVAL -eq 0 ] && touch /var/touch/lock/subsys/nfslock

restituire $RETVAL)

Per forzare il demone statd a utilizzare una porta specifica, puoi utilizzare l'opzione -p, ad esempio daemon rpc.statd -p 32800 (o qualsiasi altra, a seconda di quale preferisci). Allo stesso modo, devi impostare la porta per mountd, nfsd, rquotad: vengono tutti avviati dallo script /etc/rc.d/init.d/nfs:

inizio()(

#Avvia demoni.

action -n $"Avvio dei servizi NFS: " /usr/sbin/exportfs -r

if t _x /usr/sbin/rpc.quotad ] ; then echo -n $"Quote NFS iniziali: " daemon rpc.rquotad echo

fi echo -n $"Avvio di NFS mountd: "

demone rpc.mountd 3RPCMUNTDOPTS

echo -n $"Avvio del demone NFS: " demone rpc.nfsd $RPCNFSDOPTS echo touch /var/lock/subsys/nfs

La tecnologia per cambiare la porta per lockd (nlockmgr) è diversa da quella sopra (non è necessario provare a cambiare il file /etc/rc.d/init.d/nfslock - non funzionerà nulla).

Lockd è implementato come modulo del kernel o compilato staticamente nel kernel. Per modificare il numero di porta, è necessario aprire il file /etc/modules e trovare le opzioni passate al modulo:

opzioni bloccate nlm_udpport=33000 nlm_tcpport=33000

Ora che i servizi RPC utilizzano porte statiche conosciute, è necessario utilizzare IPTables. Il seguente insieme di regole presuppone che NFS sia l'unico server in esecuzione sulla macchina e che solo le macchine elencate nel file /usr/local/etc/nfsexports.hosts possano accedervi:

IPX = "/usr/sbin/iptables"

# Cancella tutte le catene

$IPT: colore

$IPT -t nat --flush $IPT -t mangle --flush $IPT -X

# Consenti traffico di loopback $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT

# Regole predefinite $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP

$IPT -A INPUT -m stato -stato STABILITO,RELATO -j ACCETTA $IPT -A OUTPUT -m stato -stato NUOVO,STABILITO,RELATO -j ACCETTA

# Consenti l'accesso a ciascun computer

# specificato in /usr/local/etc/nfsexports.hosts

per l'host in "cat /usr/local/etc/nfsexports.hosts"; do $IPT -I INPUT -s $host -p tcp -dport 111 -j ACCEPT

$IPT -I INPUT -s $host -p udp -dport 111 -j ACCETTA

$IPT -I INPUT -s $host -p udp -dport 2049 -j ACCETTA

$IPT -I INPUT -s $host -p tcp --dport 32800 -j ACCETTA

$IPT -I INPUT -s $host -p tcp --dport 32900 -j ACCETTA

$IPT -I INPUT -s $host -p tcp -dport 33000 -j ACCETTA

$IPT -I INPUT -s $host -p tcp --dport 33100 -j ACCETTA

Naturalmente, questo è solo uno scheletro; dovranno essere aggiunte molte altre regole: almeno consentire SSH e impostare alcuni parametri del kernel usando /proc.

Tunneling NFS su SSH.

L'abbreviazione NFS a volte sta per “No File Security”: queste tre parole parlano da sole. Pertanto, è molto importante proteggere il traffico NFS. Questo è facile da fare usando ssh.

Il primo passo è modificare il file /etc/exports sul server NFS in modo che i file system vengano esportati nel nodo locale:

Quindi è necessario utilizzare SSH per inoltrare le porte NFS e mountd. NFS utilizza la porta 2049/udp e mountd, come detto, utilizza il numero di porta 33000:

#ssh [e-mail protetta]-L 200: localhost:2049 -f sonno 120m

#ssh [e-mail protetta]-L 200: localhost:33000 -f sonno 120m

Questi due comandi forniscono all'utente una shell interattiva, ma poiché non è necessaria, SSH esegue il comando sleep 120: torniamo alla riga di comando, ma il port forwarding richiederà altre 2 ore.

Il montaggio di un file system dal lato client sembra molto insolito:

mount -t nfs -o nosuid port=200 mountport=210 nfsserver.test.net:/home/utente /mnt/another

Se i trucchi del tunneling ssh sono troppo complicati, puoi utilizzare il progetto SHFS (Shell Filesystem) ( http://shfs.sourceforge.net/ ), che consente di automatizzare l'intera procedura.

Dopo l'installazione, è necessario accedere a SHFS utilizzando il comando mount -t shfs o il nuovo comando shfsmount. La sintassi di questo comando è simile al precedente:

shfsmount [e-mail protetta]:/home/utente/mnt/utente

CFS e TCFS

Il file system crittografico utilizza la crittografia e la decrittografia trasparenti del traffico NFS utilizzando l'algoritmo DES. Inoltre, supporta la gestione automatica delle chiavi, che rende il processo il più trasparente possibile per l'utente.

Sebbene CFS sia stato sviluppato per SunOS e BSD, è piuttosto interessante perché sembra essere il primo tentativo di codificare in modo trasparente i file condivisi. TCFS (Transparent Cryptographic File System) fornisce un modo ancora più trasparente per crittografare il traffico NFS.

Oltre alla codifica dei dati, questo file system supporta il controllo dell'integrità dei dati.

Per la distribuzione dei file all'interno di una rete locale si possono distinguere le seguenti tecnologie (vengono considerati i sistemi basati su Linux):

  • Network File System (NFS) - protocollo di accesso alla rete per file system;
  • I file trasferiti tramite il protocollo Shell (FISH) è un protocollo di rete che utilizza o RSH trasferire file tra computer;
  • Secure SHell FileSystem (SSHFS) - un client di file system per il montaggio di dispositivi disco su sistemi remoti, utilizzato per interagire con il sistema remoto SFTP;
  • Samba è un pacchetto software che consente di accedere a unità di rete e stampanti su vari sistemi operativi tramite il protocollo SMB/CIFS;

In questa nota parleremo di NFS.

NFS (file system di rete) utile quando è necessario distribuire file/directory a chiunque sulla rete. Accedi alla trasparenza con NFS consente ai client di montare un file system remoto come directory locale e i file system possono essere di diversi tipi. Ciò significa che qualsiasi applicazione client in grado di funzionare con un file locale può funzionare altrettanto facilmente con un file connesso tramite NFS, senza alcuna modifica al programma stesso.

Ai benefici NFS possono essere attribuiti:

  • ridurre il carico sul processore;
  • visualizzare le risorse condivise come directory regolari nel sistema;
  • Attualmente disponibile NFS v4.1, che ha introdotto una nuova funzionalità pNFS permettendoti di parallelizzare l'implementazione della condivisione di file. Esiste anche un'estensione per NFS 2 e 3 - WebNFS, che consentono una più semplice integrazione nei browser Web e la capacità di lavorare attraverso un firewall.

    Schema di lavoro NFS protocollo.

    Installazione e configurazione del server NFS sotto Linux

    Controlliamo se il sistema supporta NFS

    Cat /proc/filesystems | grep nfs

    Sotto ArcoLinux server e client sono nello stesso pacchetto

    Yaourt -S nfs-utils

    Per installare il server ( nfs-kernel-server) e cliente ( nfs-comune) Sotto Ubuntu pacchetti necessari

    Sudo apt-get install nfs-kernel-server nfs-common portmap

    Più avanti in questa nota, per il server verrà utilizzato l'IP 192.168.1.100 . Affinché al server venga assegnato sempre lo stesso IP, è necessario specificare nel server DHCP (solitamente un router) la distribuzione di un determinato IP a uno specifico indirizzo MAC. Oppure aumenta il tuo server DNS locale. Ad esempio o.

    L'indirizzo MAC può essere trovato utilizzando ifconfig (campo etere V ArcoLinux).

    NFSv4 presuppone che esista una directory root, all'interno della quale si trovano già i file per la distribuzione. Per esempio, /srv/nfs- radice, /srv/nfs/audio- directory per la distribuzione della musica. Se non segui questa nuova guida nella versione 4 , potresti ricevere un errore durante la connessione da parte del client:

    Mount.nfs: accesso negato dal server durante il montaggio di 192.168.1.100:/home/proft/torrents

    Se desideri comunque utilizzare l'approccio sul server senza una directory root per NFS, quindi durante il montaggio da parte del client, è necessario specificare esplicitamente la versione 3

    # per il comando di montaggio mount -o "vers=3" 192.168.1.100:/home/proft/torrents /home/proft/nfs/torrents # per fstab 192.168.1.100:/home/proft/torrents /home/proft/nfs /torrent nfs soft,nfsvers=3 0 0

    userò NFSv4 con la directory root in /srv/nfs/ e montare le sottodirectory utilizzando mount --bind .

    Supponiamo di volere

    • directory di distribuzione ~/torrent Con rw accesso per tutti all'interno della rete locale;
    • directory di distribuzione ~/foto Con ro accesso per host con IP 192.168.1.101 ;

    Per prima cosa creiamo una directory root e le sottodirectory necessarie.

    Sudo mkdir -p /srv/nfs/(torrent,foto)

    Monta le directory esistenti torrent, foto V /srv/nfs.

    # sudo vim /etc/fstab /home/proft/torrents /srv/nfs/torrents none bind 0 0 /home/proft/photos /srv/nfs/photos none bind 0 0

    Modifichiamo /etc/export, che descrive tutte le directory condivise

    # sudo vim /etc/exports # formato file: directory consentiti-hosts(opzioni) /srv/nfs/torrents 192.168.1.1/24(rw,async) /srv/nfs/photos 192.168.1.101(ro,async)

    Tieni presente che non c'è spazio in mezzo host consentiti E (opzioni). La presenza di uno spazio introduce una diversa interpretazione delle regole.

    Opzioni disponibili:

    • ro (rw) - consente l'accesso in sola lettura (lettura/scrittura);
    • subtree_check (no_subtree_check) - in alcuni casi è necessario esportare non l'intera sezione, ma solo una parte di essa. In questo caso, il server NFS deve eseguire controlli aggiuntivi sulle richieste dei client per garantire che stiano tentando di accedere solo ai file situati nelle sottodirectory appropriate. Questo controllo sottoalbero ( controlli del sottoalbero) rallenta in qualche modo l'interazione con i client, ma se lo abbandoni potrebbero sorgere problemi con la sicurezza del sistema. È possibile annullare il controllo di un sottoalbero utilizzando l'opzione no_subtree_check. Opzione sottoalbero_controllo, che include tale controllo, viene assunto per impostazione predefinita. Il controllo della sottostruttura può essere omesso se la directory esportata è la stessa di una partizione del disco;
    • sync (asincrono): specifica che il server deve rispondere alle richieste solo dopo che le modifiche apportate da tali richieste sono state scritte su disco. Opzione asincrono dice al server di non attendere che le informazioni vengano scritte sul disco, il che migliora le prestazioni, ma riduce l'affidabilità, perché in caso di interruzione della connessione o guasto delle apparecchiature, potrebbe verificarsi la perdita dei dati;
    • noaccess - nega l'accesso alla directory specificata. Può essere utile se in precedenza hai impostato l'accesso per tutti gli utenti della rete a una determinata directory e ora desideri limitare l'accesso alla sottodirectory solo ad alcuni utenti;
    • no_root_squash – utente predefinito radice sulla macchina client non avrà gli stessi diritti sulla directory sul server. Questa opzione rimuove questa limitazione;
    • nohide- NFS non mostra automaticamente le risorse non locali (ad esempio, montate utilizzando mount --bind), questa opzione abilita la visualizzazione di tali risorse;
    • insicuro - utilizzo di porte non privilegiate (> 1024);

    Avvio del server NFS

    # sotto archlinux sudo systemctl start rpc-idmapd.service rpc-mountd.service # sotto ubuntu sudo /etc/init.d/nfs-kernel-server start

    In futuro, quando si modificherà il file di configurazione, basterà rileggerlo con il comando:

    Sudo exportfs -rav

    Comando rpcinfo -p | grep nfs ti consente di verificare se il server è stato avviato correttamente.

    Cliente Linux

    Installazione

    # sotto archlinux yaourt -S nfs-utils # sotto ubuntu sudo apt-get install portmap nfs-common

    Creiamo directory per montare le risorse di rete torrent E fotografie

    Mkdir -p ~/nfs/(torrenti,foto)

    Per il montaggio manuale lo faremo

    Sudo mount -t nfs -o rw,soft 192.168.1.100:/srv/nfs/torrents /home/proft/nfs/torrents sudo mount -t nfs -o rw,soft 192.168.1.100:/srv/nfs/photos /home /proft/nfs/foto

    Opzione morbido specifica di annullare silenziosamente i tentativi di connessione alla condivisione dopo un certo periodo di tempo (il tempo è specificato dall'opzione ritrasf). Maggiori dettagli in uomo nfs.

    Questo metodo non è molto conveniente, poiché ogni volta dopo il riavvio dovrai eseguire questi comandi. Rendiamo automatica l'installazione.

    Per montarlo automaticamente, modifica il file /etc/fstab

    # sudo vim /etc/fstab 192.168.1.100:/srv/nfs/torrents /home/proft/net/torrents nfs rw,soft 0 0 192.168.1.100:/srv/nfs/photos /home/proft/net/photos nfs ro,morbido 0 0

    Ma questo metodo ha anche i suoi svantaggi, ad esempio se il server non è disponibile, il caricamento del client potrebbe bloccarsi a causa dei tentativi di connessione al server NFS. Per risolvere questo problema, vedere di seguito AutoFS.

    AutoFS: connessione automatica delle risorse di rete

    È possibile montare una risorsa remota utilizzando AutoFS al primo accesso e smontato automaticamente quando non c'è attività.

    AutoFS utilizza i modelli che si trovano in /etc/autofs. Viene chiamato il modello principale auto.master, può puntare a uno o più altri modelli per tipi di media specifici.

    Installazione

    # sotto archlinux yaourt -S autofs # sotto ubuntu sudo apt-get install autofs

    Esistono diversi modi per specificare i metodi di montaggio automatico. Io uso questo: in /home/proft/nfs Viene creata automaticamente una directory con il nome del server NFS, nella quale vengono create automaticamente le directory accessibili sul server.

    # sudo vim /etc/autofs/auto.master /home/proft/nfs /etc/autofs/auto.nfs --timeout=60

    Parametro aggiuntivo tempo scaduto imposta il numero di secondi dopo i quali il dispositivo verrà smontato. Parametro fantasma specifica che le risorse configurate verranno sempre visualizzate e non solo quando saranno disponibili (questa opzione è abilitata di default in AutoFS5)

    Descriveremo in /etc/autofs/auto.nfs Server NFS e directory principale.

    # sudo vim /etc/autofs/auto.nfs nfsserver 192.168.1.100:/srv/nfs

    Ora alla prima chiamata /home/proft/nfs/torrents La risorsa NFS verrà montata automaticamente.

    Riavviamo il servizio autofs:

    # sotto archlinux sudo systemctl restart autofs # sotto ubuntu sudo /etc/init.d/autofs restart

    È inoltre possibile specificare il tempo di attesa affinché una risorsa NFS diventi disponibile. Per fare ciò è necessario modificare i valori MONTAGGIO_ATTESA.

    # sotto archlinux # sudo vim /etc/conf.d/autofs MOUNT_WAIT=5 # sotto ubuntu sudo /etc/default/autofs MOUNT_WAIT=5

    Forzare l'uso di NFS v3

    In alcuni casi NFSv4 potrebbe funzionare lentamente. Per risolvere questo problema, puoi forzarlo a utilizzare la terza versione.

    Tutti sanno che sui sistemi UNIX un file system è logicamente una raccolta di file system fisici collegati ad un singolo punto. Uno dei principali vantaggi di tale organizzazione, a mio avviso, è la capacità di modificare dinamicamente la struttura di un file system esistente. Inoltre, grazie agli sforzi degli sviluppatori, oggi abbiamo l'opportunità di connettere file system di quasi tutti i tipi e in qualsiasi modo conveniente. Con "metodo" voglio innanzitutto sottolineare la capacità del kernel del sistema operativo di funzionare con i file system tramite connessioni di rete.

    Molti protocolli di rete ci offrono la possibilità di lavorare con file remoti, siano essi FTP, SMB, Telnet o SSH. Grazie alla capacità del kernel di non dipendere in definitiva dal tipo di file system connesso, abbiamo la possibilità di connettere qualsiasi cosa e come vogliamo utilizzando il programma di montaggio.

    Oggi vorrei parlare di NFS - Network File System. Questa tecnologia consente di connettere singoli punti del file system su un computer remoto al file system del computer locale. Il protocollo NFS stesso consente di eseguire operazioni sui file in modo abbastanza rapido, sicuro e affidabile. Cos'altro ci serve? :-)

    Cosa è necessario affinché funzioni

    Per non dilungarci a lungo sul tema delle versioni NFS e del loro supporto nei vari kernel, supponiamo immediatamente che la versione del vostro kernel non sia inferiore alla 2.2.18. Nella documentazione ufficiale, gli sviluppatori promettono il pieno supporto per la funzionalità NFS versione 3 in questo kernel e nelle versioni successive.

    Installazione

    Per eseguire il server NFS nel mio Ubuntu 7.10 - Gutsy Gibbon, dovevo installare i pacchetti nfs-common e nfs-kernel-server. Se hai bisogno solo di un client NFS, non è necessario installare nfs-kernel-server.

    Ottimizzazione del server

    Dopo che tutti i pacchetti sono stati installati con successo, è necessario verificare se il demone NFS è in esecuzione:

    /etc/init.d/nfs-kernel-server stato

    Se il demone non è in esecuzione, è necessario avviarlo con il comando

    /etc/init.d/nfs-kernel-server avviare

    Dopo che tutto è iniziato correttamente, puoi iniziare ad esportare il file system. Il processo in sé è molto semplice e richiede un tempo minimo.

    Il file di configurazione del server NFS principale si trova in /etc/exports e ha il seguente formato:

    Directory macchina1(opzione11,opzione12) macchina2(opzione21,opzione22)

    directory— percorso assoluto della directory del server FS a cui è necessario fornire l'accesso

    macchinaX— Nome DNS o indirizzo IP del computer client da cui è consentito l'accesso

    opzioneXX— Parametri di esportazione FS, i più comunemente utilizzati:

    • ro- L'accesso ai file è di sola lettura
    • rw— è fornito l'accesso in lettura/scrittura
    • no_root_zucca— per impostazione predefinita, se ti connetti a una risorsa NFS come root, il server, per motivi di sicurezza, accederà ai file come utente nessuno. Tuttavia, se abiliti questa opzione, si accederà ai file sul lato server come root. Fai attenzione con questa opzione.
    • no_subtree_check— per impostazione predefinita, se non esporti l'intera partizione sul server, ma solo una parte del file system, il demone controllerà se il file richiesto si trova fisicamente sulla stessa partizione oppure no. Se stai esportando l'intera partizione o se il punto di montaggio del file system esportato non influisce sui file di altri volumi fisici, puoi abilitare questa opzione. Questo ti darà un aumento della velocità del server.
    • sincronizzare— abilita questa opzione se esiste la possibilità di un'improvvisa perdita di connessione o di un'interruzione dell'alimentazione del server. Se questa opzione non è abilitata, il rischio di perdita di dati è molto elevato se il server NFS si arresta improvvisamente.

    Quindi, diciamo che dobbiamo dare accesso al computer asep-desktop alla directory /var/backups del computer asep-laptop. È necessario l'accesso alla directory per copiare i file di backup da asep-desktop. Il mio file è risultato così:

    /var/backups asep-desktop(rw,no_subtree_check,sync)

    Dopo aver aggiunto la riga a /etc/exports, è necessario riavviare il server NFS affinché le modifiche abbiano effetto.

    /etc/init.d/nfs-kernel-server riavviare

    È tutto. Puoi iniziare a connettere il FS esportato sul computer client.

    Configurazione del cliente

    Sul lato client, il file system remoto viene montato allo stesso modo di tutti gli altri: con il comando mount. Inoltre, nessuno ti proibisce di usare /etc/fstab se hai bisogno di connettere automaticamente l'FS all'avvio del sistema operativo. Quindi, l'opzione di montaggio sarà simile a questa:

    Montare -t nfs ashep-laptop:/var/backups/ /mnt/ashep-laptop/backups/

    Se tutto è andato bene e devi connetterti automaticamente all'FS remoto all'avvio, aggiungi semplicemente la riga a /etc/fstab:

    Ashep-laptop:/var/backups /mnt/ashep-laptop/backups nfs auto 0 0

    Cos'altro

    Abbiamo quindi una panoramica pratica e ridotta delle capacità di NFS. Naturalmente questa è solo una piccola parte di ciò che NFS può fare. Questo è sufficiente per l'uso a casa o in un piccolo ufficio. Se questo non ti basta ti consiglio di leggere prima

    Allora, qual è il prossimo? Come guardare film e ascoltare file musicali che sono stati scaricati? È davvero necessario masterizzarli su dischi e quindi trasferirli su un computer dotato di GUI? Oppure dovrò copiarli tramite SFTP lento? NO! NFS viene in soccorso! No, questa non è una serie di giochi di corse, ma un Network File System.
    Network File System (NFS) è un file system di rete che consente agli utenti di accedere a file e directory situati su computer remoti come se tali file e directory fossero locali. Il vantaggio principale di un tale sistema è che le singole workstation possono utilizzare meno spazio su disco, poiché i dati condivisi vengono archiviati su una macchina separata e sono disponibili per altre macchine sulla rete. NFS è un'applicazione client-server. Cioè, un client NFS deve essere installato sul sistema dell'utente e un server NFS deve essere installato sui computer che forniscono lo spazio su disco.

    Installazione e configurazione di un server NFS (192.168.1.2)

    1. Installa. Dopo esserti connesso tramite SSH al computer server o semplicemente nella sua console, inserisci:

    Sudo apt-get install nfs-kernel-server nfs-common portmap

    Questo installerà il server NFS e il pacchetto portmap richiesto.

    2. Configurazione. Per configurare l'elenco delle directory che vogliamo aprire e l'elenco di chi vogliamo aprirle, modificheremo il file /etc/export :

    Sudo nano /etc/exports /data 192.168.1.1/24(rw,no_root_squash,async)

    Nell'esempio sopra, abbiamo aperto una directory sul server /dati e le sue sottodirectory per l'uso condiviso da tutti i computer con IP: 192.168.1.1 - 192.168.1.255 con diritti di lettura e scrittura.

    Un altro esempio:

    /home/serg/ 192.168.1.34(ro,asincrono)

    Questo esempio rende la directory home dell'utente serg disponibile in modalità di sola lettura su un computer con IP 192.168.1.34. Tutti gli altri computer della rete non avranno accesso a questa directory.

    Opzioni disponibili:

    • ro - diritti di sola lettura. Non è necessario specificarlo, poiché è installato di default;
    • rw: fornisce ai client il permesso di scrittura;
    • no_root_squash - per impostazione predefinita, l'utente root sul computer client non avrà accesso alle directory aperte sul server. Con questa opzione rimuoviamo questa limitazione. Per motivi di sicurezza è meglio non farlo;
    • noaccess - nega l'accesso alla directory specificata. Può essere utile se in precedenza hai impostato l'accesso per tutti gli utenti della rete a una determinata directory e ora desideri limitare l'accesso alla sottodirectory solo ad alcuni utenti.

    Ora devi riavviare nfs-kernel-server:

    Sudo /etc/init.d/nfs-kernel-server riavviare

    Se dopo questo vuoi cambiare qualcosa nel file /etc/export , quindi affinché le modifiche abbiano effetto, è sufficiente eseguire il comando seguente:

    Sudo exportfs -a

    Tutto. Il server NFS è installato e configurato. Puoi passare al client NFS.

    Installazione e configurazione del client NFS

    1. Installazione. Eseguiamo quanto segue nel terminale del computer, che si collegherà:

    Sudo apt-get install portmap nfs-common

    2. Configurazione. Innanzitutto, creiamo una directory in cui verrà montata la cartella remota:

    Cd ~ dati mkdir

    Puoi montare in due modi: manualmente ogni volta o scrivendo le opzioni di montaggio in un file /etc/fstab.

    Metodo 1: montaggio manuale
    Crea un file di testo sul desktop o in qualche altra cartella:

    Nano ~/Desktop/nfs-server-connect

    In esso scriviamo:

    #! /bin/bash sudo mount -t nfs -o ro,soft,intr 192.168.1.2:/data ~/data

    Rendiamolo eseguibile:

    Chmod +x ~/Desktop\nfs-server-connect

    Ora, quando devo connettermi al server, eseguo questo script nel terminale in modo da poter inserire la password per sudo.

    Metodo 2: aggiungere a /etc/fstab
    Apri /etc/fstab:

    Sudo nano /etc/fstab

    E aggiungi una riga alla fine del file:

    192.168.1.2:/dati ~/dati nfs rw,hard,intr 0 0

    Attenzione! Invece di 192.168.1.2:/data, inserisci l'IP o il nome del server e il percorso della directory condivisa. Le opzioni di montaggio possono essere modificate.

    Opzione difficile lega strettamente la directory del client al server e, se il server si interrompe, anche il computer potrebbe bloccarsi. Opzione morbido, come suggerisce il nome, non è così categorico.

    Dopo aver salvato il file, puoi montare la cartella remota.

    Capitolo 29 NFS: File system di rete

    introduzione

    In questo capitolo esamineremo Network File System (NFS), una popolare applicazione che fornisce alle applicazioni client un accesso trasparente ai file. La pietra angolare di NFS è Sun RPC: Remote Procedure Call, di cui parleremo per primo.

    Il programma client non richiede strumenti speciali per sfruttare NFS. Il kernel rileva che il file si trova su un server NFS e genera automaticamente una chiamata RPC per accedere al file.

    Non esamineremo in dettaglio come viene implementato l'accesso ai file, ma esamineremo come vengono utilizzati i protocolli Internet, in particolare UDP.

    Chiamata di procedura remota Sun

    Nella maggior parte dei casi, i problemi di programmazione di rete vengono risolti scrivendo programmi applicativi che richiamano funzioni fornite dal sistema per eseguire specifiche operazioni di rete. Ad esempio, una funzione esegue un'apertura TCP attiva, un'altra un'apertura TCP passiva, una terza invia dati tramite una connessione TCP, una quarta imposta opzioni specifiche del protocollo (abilita il timer "resta in vita" TCP) e così via. Nella sezione Interfacce di programmazione dell'applicazione del Capitolo 1, abbiamo menzionato che esistono due insiemi popolari di funzioni di programmazione di rete (interfacce di programmazione dell'applicazione, API): socket e TLI. L'API utilizzata dal client e l'API utilizzata dal server possono differire, così come i sistemi operativi eseguiti dal client e dal server. Sono i protocolli di comunicazione e applicazione che determinano se un particolare client può comunicare con il server. Un client Unix scritto in C utilizzando socket come interfaccia di programmazione e TCP come protocollo di comunicazione può comunicare con un server mainframe scritto in COBOL utilizzando API e TCP diversi se entrambi gli host sono connessi alla rete ed entrambi hanno un'implementazione TCP /IP.

    In genere, il client invia comandi al server e il server invia risposte al client. Tutte le applicazioni che abbiamo esaminato - Ping, Traceroute, demoni di routing, client e server DNS, TFTP, BOOTP, SNMP, Telnet, FTP, SMTP - sono tutte costruite in questo modo.

    RPC, chiamata di procedura remota, implementa un approccio diverso alla programmazione di rete. Il programma client chiama semplicemente le funzioni nel programma server. Quindi questo viene deciso dal punto di vista del programmatore, ma in realtà avviene la seguente sequenza di azioni.

    1. Quando un client chiama una procedura remota, viene chiamata una funzione sull'host locale generata dal pacchetto RPC. Questa funzione è chiamata stub del client. lo stub del client impacchetta gli argomenti della procedura in un messaggio di rete e invia il messaggio al server.
    2. lo stub del server sull'host del server riceve il messaggio di rete. Gli argomenti vengono recuperati dal messaggio di rete e viene effettuata una chiamata alla procedura server scritta dal programmatore dell'applicazione.
    3. La funzione server restituisce il controllo allo stub del server, che a sua volta prende i valori ricevuti, li impacchetta in un messaggio di rete e invia il messaggio allo stub del client.
    4. lo stub client restituisce i valori da un messaggio di rete all'applicazione client.

    La programmazione di rete utilizzando stub e routine RPC di libreria utilizza API (socket o TLI), ma le applicazioni utente (il programma client e le procedure server chiamate dal client) non accedono mai all'API. L'applicazione client deve solo chiamare la procedura server, mentre tutti i dettagli di implementazione sono nascosti dal pacchetto RPC, dallo stub del client e dallo stub del server.

    I pacchetti RPC presentano i seguenti vantaggi.

    • La programmazione diventa più semplice perché non devi risolvere problemi di programmazione di rete (e se lo fai, è davvero poco). I programmatori di applicazioni scrivono semplicemente il programma client e le procedure server che il client chiama.
    • Se viene utilizzato un protocollo inaffidabile come UDP, tutti i dettagli, ovvero timeout e ritrasmissioni, vengono gestiti dal pacchetto RPC. Ciò a sua volta semplifica l'applicazione utente.
    • La libreria RPC gestisce la conversione necessaria degli argomenti e dei valori restituiti. Ad esempio, se gli argomenti sono costituiti da numeri interi e a virgola mobile, il pacchetto RPC gestirà eventuali differenze tra la rappresentazione di numeri interi e a virgola mobile sul client e sul server. Ciò semplifica l'implementazione di client e server per operare in ambienti eterogenei.

    La programmazione RPC è trattata in dettaglio nel Capitolo 18. I due pacchetti RPC più popolari sono Sun RPC e il pacchetto RPC nell'ambiente di calcolo distribuito (DCE) della Open Software Foundation (OSF). Vedremo come viene chiamata la procedura, come appare il messaggio di ritorno e come questo è correlato al pacchetto Sun RPC, poiché è questo pacchetto ad essere utilizzato in Sun RPC Versione 2, descritto in RFC 1057 [Sun Microsystems 1988a].

    Esistono due tipi di Sun RPC. Una versione viene creata utilizzando l'API socket e funziona con TCP e UDP. L'altro si chiama TI-RPC (indipendente dal trasporto), costruito utilizzando l'API TLI e funziona con qualsiasi livello di trasporto fornito dal kernel. Dal nostro punto di vista non c'è differenza tra loro, poiché in questo capitolo considereremo solo TCP e UDP.

    La Figura 29.1 mostra il formato di un messaggio di chiamata di procedura RPC che utilizza UDP.

    Figura 29.1 Messaggi di chiamata di procedura RPC in formato datagramma UDP.

    Le intestazioni IP e UDP standard sono mostrate in precedenza (Figura 3.1 e Figura 11.2). Tutto ciò che segue l'intestazione UDP è determinato dal pacchetto RPC.

    L'identificatore della transazione (XID - ID transazione) viene impostato dal client e restituito dal server. Quando il client riceve una risposta, confronta l'XID restituito dal server con l'XID della richiesta inviata. Se non corrispondono, il client scarta il messaggio e attende l'arrivo del successivo. Ogni volta che il client emette una nuova RPC, modifica l'XID. Se il client ritrasmette la RPC (se non è stata ricevuta alcuna risposta), tuttavia, l'XID non cambia.

    La variabile di chiamata è 0 per una chiamata e 1 per una risposta. La versione RPC corrente è 2. Le tre variabili successive, numero di programma, numero di versione e numero di procedura, identificano la procedura specifica da richiamare sul server.

    Le credenziali identificano il client. In alcuni esempi questo campo viene lasciato vuoto, mentre in altri viene visualizzato l'identificatore digitale dell'utente e l'identificativo del gruppo di appartenenza. Il server può esaminare le credenziali e decidere se elaborare la richiesta o meno. Verifier viene utilizzato per Secure RPC, che utilizza la crittografia DES. Anche se i campi di autorità e di convalida sono campi a lunghezza variabile, la loro lunghezza viene passata come parte del campo.

    Poi ci sono i parametri della procedura. Il loro formato dipende da come l'applicazione definisce la procedura remota. Come fa il ricevitore (stub del server) a conoscere la dimensione dei parametri? Poiché viene utilizzato UDP, la dimensione dei parametri può essere calcolata come la dimensione del datagramma UDP meno la lunghezza di tutti i campi fino al campo di controllo. Quando si utilizza TCP invece di UDP, non esiste il concetto di lunghezza fissa, poiché TCP è un flusso di byte senza delimitatori di record. In tal caso, tra l'intestazione TCP e l'XID viene visualizzato un campo di lunghezza 4 byte, dal quale il destinatario apprende la lunghezza della chiamata RPC in byte. Ciò consente di inviare il messaggio di chiamata RPC su più segmenti TCP, se necessario. (DNS utilizza una tecnica simile; Esercizio 4 nel Capitolo 14.)

    La Figura 29.2 mostra il formato della risposta RPC. Viene inviato dallo stub del server allo stub del client quando termina la procedura remota.

    Figura 29.2 Formato del messaggio di risposta della procedura RPC come datagramma UDP.

    La chiamata XID viene semplicemente copiata nella risposta XID. Il campo risposta contiene 1, questo campo distingue tra una sfida e una risposta. Il campo stato contiene un valore nullo se il messaggio di chiamata è stato accettato. (Il messaggio può essere scartato se il numero di versione RPC non è 2 o se il server non riesce ad autenticare il client.) Il campo verificatore viene utilizzato nel caso di RPC sicuro per indicare il server.

    Il campo dello stato di accettazione contiene un valore zero se tutto va bene. Un valore diverso da zero potrebbe indicare, ad esempio, un numero di versione errato o un numero di procedura errato. Se viene utilizzato TCP invece di UDP, allora, come nel caso del messaggio di verifica RPC, viene inviato un campo di 4 byte tra l'intestazione TCP e l'XID.

    XDR: Rappresentazione dei dati esterni

    La rappresentazione dei dati esterni (XDR) è uno standard utilizzato per codificare i valori nei messaggi di chiamata e risposta RPC: campi di intestazione RPC (XID, numero di programma, stato di ricezione, ecc.), parametri di procedura e risultati della procedura. Un modo standard di codificare i dati consente a un client di chiamare una procedura su un sistema con un'architettura diversa. XDR è definito nella RFC 1014 [Sun Microsystems 1987].

    XDR definisce un certo numero di tipi di dati e il modo esatto in cui vengono trasportati in un messaggio RPC (ordine dei bit, ordine dei byte e così via). Il mittente deve costruire il messaggio RPC in formato XDR, quindi il destinatario converte il formato XDR nella rappresentazione originale. (Nel formato accettato per il suo sistema.) Vediamo, ad esempio, nelle Figure 29.1 e 29.2, che tutti i valori interi che abbiamo mostrato (XID, chiamata, numero di programma e così via) sono interi a 4 byte . In effetti, tutti i numeri interi in XDR occupano 4 byte. XDR supporta altri tipi di dati, inclusi numeri interi senza segno, booleani, a virgola mobile, array a lunghezza fissa, array a lunghezza variabile e strutture.

    Conformità del porto

    I programmi server RPC che contengono procedure remote utilizzano porte assegnate dinamicamente anziché porte preconosciute. Ciò richiede una qualche forma di "registrazione" per sapere sempre quale porta assegnata dinamicamente viene utilizzata da quale programma RPC. In Sun RPC questo logger è chiamato port mapper. (Un port mapper è un server che converte i numeri di programma RPC in numeri di porta del protocollo DARPA. Questo server deve essere in esecuzione per poter effettuare una chiamata RPC.)

    Il termine "porta" nel nome deriva dai numeri di porta TCP e UDP, caratteristiche della famiglia di protocolli Internet. Poiché TI-RPC viene eseguito su qualsiasi livello di trasporto, non solo su TCP e UDP, il mappatore delle porte dei nomi sui sistemi che utilizzano TI-RPC (SVR4 e Solaris 2.2, ad esempio) è stato convertito in rpcbind. Tuttavia, continueremo a utilizzare il mappatore di porte più familiare.

    In effetti, il risolutore di porte stesso deve avere una porta conosciuta: porta UDP 111 e porta TCP 111. Il risolutore di porte è semplicemente un programma server RPC. Ha un numero di programma (100000), un numero di versione (2), una porta TCP 111 e una porta UDP 111. I server si registrano a vicenda con il risolutore di porte utilizzando chiamate RPC e i client richiedono il risolutore di porte utilizzando chiamate RPC. Il risolutore di porte fornisce quattro procedure server:

    1. PMAPPROC_SET. Chiamato dal server RPC all'avvio per registrare il numero di programma, il numero di versione e il protocollo con il risolutore di porte.
    2. PMAPPROC_UNSET. Chiamato dal server per rimuovere una trasformazione registrata in precedenza.
    3. PMAPPROC_GETPORT. Chiamato dal client RPC all'avvio per ottenere il numero di porta per il numero di programma, il numero di versione e il protocollo specificati.
    4. PMAPPROC_DUMP. Restituisce tutti gli elementi (numero di programma, numero di versione, protocollo e numero di porta) al database del risolutore di porte.

    All'avvio del programma server RPC e successivamente quando viene chiamato dal programma client RPC, si verificano i seguenti passaggi.

    1. Il convertitore di porta dovrebbe avviarsi per primo, solitamente all'avvio del sistema. Ciò crea un endpoint TCP e apre passivamente la porta TCP 111. Crea inoltre un endpoint UDP che attende l'arrivo di un datagramma UDP sulla porta UDP 111.
    2. All'avvio, il programma del server RPC crea un endpoint TCP e un endpoint UDP per ciascuna versione supportata del programma. (Un programma RPC può supportare più versioni. Il client specifica la versione richiesta quando chiama la procedura del server.) A ciascun endpoint viene assegnato un numero di porta assegnato dinamicamente. (Non fa differenza se i numeri di porta TCP e UDP sono uguali o diversi.) Il server registra ogni programma, versione, protocollo e numero di porta effettuando una chiamata remota alla procedura di risoluzione delle porte PMAPPROC_SET.
    3. All'avvio, il programma client RPC chiama la procedura del risolutore di porte PMAPPROC_GETPORT per ottenere il numero di porta assegnato dinamicamente per il programma, la versione e il protocollo specificati.
    4. Il client invia un messaggio di sfida RPC al numero di porta ottenuto nel passaggio 3. Se viene utilizzato UDP, il client invia semplicemente un datagramma UDP contenente il messaggio di sfida RPC (Figura 29.1) al numero di porta UDP del server. In risposta, il server invia un datagramma UDP contenente un messaggio di risposta RPC (Figura 29.2). Se viene utilizzato TCP, il client esegue un'apertura attiva al numero di porta TCP del server e quindi invia un messaggio di verifica RPC sulla connessione. Il server risponde con un messaggio di risposta RPC sulla connessione.

    Il programma rpcinfo(8) stampa tutte le impostazioni correnti del port mapper. (Qui è dove viene chiamata la routine del port mapper PMAPPROC_DUMP.) L'output tipico è mostrato di seguito:

    Sole% /usr/etc/rpcinfo -p
    programma rispetto al port proto
    100005 1 demone di montaggio NFS montato tcp 702
    100005 1udp 699 montatod
    100005 2 tcp 702 montatod
    100005 2udp 699 montatod

    100003 2 udp 2049 nfs NFS stesso

    100021 1 tcp 709 nlockmgr Gestore blocchi NFS
    100021 1 udp 1036 nlockmgr
    100021 2 tcp 721 nlockmgr
    100021 2 udp 1039 nlockmgr
    100021 3 tcp 713 nlockmgr
    100021 3 udp 1037 nlockmgr

    Vediamo che alcuni programmi supportano più versioni e ciascuna combinazione di numero di programma, numero di versione e protocollo ha il proprio layout del numero di porta, servito da un risolutore di porte.

    È possibile accedere a entrambe le versioni del demone di montaggio tramite lo stesso numero di porta TCP (702) e lo stesso numero di porta UDP (699), tuttavia ciascuna versione del gestore dei blocchi ha il proprio numero di porta.

    Protocollo NFS

    NFS offre ai client un accesso trasparente ai file e al file system del server. Questo è diverso dall'FTP (Capitolo 27), che fornisce il trasferimento di file. Utilizzando FTP, viene eseguita una copia completa del file. NFS accede solo a quelle parti di un file a cui ha avuto accesso un processo e il vantaggio principale di NFS è che rende questo accesso trasparente. Ciò significa che qualsiasi applicazione client in grado di funzionare con un file locale può funzionare altrettanto facilmente con un file NFS, senza alcuna modifica al programma stesso.

    NFS è un'applicazione client-server creata utilizzando Sun RPC. I client NFS accedono ai file su un server NFS inviando richieste RPC al server. Ciò può essere implementato utilizzando normali processi utente, ovvero il client NFS può essere un processo utente che effettua chiamate RPC specifiche al server, che può anche essere un processo utente. Tuttavia, NFS viene solitamente implementato in modo diverso per due motivi. Innanzitutto, l'accesso ai file NFS deve essere trasparente per il client. Pertanto, le chiamate client NFS vengono effettuate dal sistema operativo client per conto del processo utente del client. In secondo luogo, i server NFS vengono implementati all'interno del sistema operativo per migliorare l'efficienza del server. Se il server NFS fosse un processo utente, ogni richiesta del client e risposta del server (compresi i dati da leggere o scrivere) dovrebbe passare attraverso un separatore tra il kernel e il processo utente, il che generalmente è piuttosto costoso.

    In questa sezione esamineremo la versione 2 di NFS come documentato nella RFC 1094 [Sun Microsystems 1988b]. La migliore descrizione di Sun RPC, XDR e NFS è fornita in [X/Open 1991]. I dettagli sull'uso e sull'amministrazione di NFS sono forniti in [Stern 1991]. Le specifiche della versione 3 del protocollo NFS sono state implementate nel 1993, di cui parleremo in una sezione di questo capitolo.

    La Figura 29.3 mostra le tipiche impostazioni del client NFS e del server NFS. In questa figura, è necessario prestare attenzione a quanto segue.

    1. Al client non interessa se accede a un file locale o a un file NFS. Il kernel lo rileva quando il file è aperto. Dopo che il file è stato aperto, il kernel passa tutti gli accessi ai file locali alla casella denominata "accesso ai file locali" e tutti i collegamenti ai file NFS vengono passati alla casella "client NFS".
    2. Il client NFS invia richieste RPC al server NFS tramite il modulo TCP/IP. NFS utilizza in genere UDP, tuttavia le implementazioni più recenti potrebbero utilizzare TCP.
    3. Il server NFS riceve le richieste dal client come datagrammi UDP sulla porta 2049. Sebbene NFS possa funzionare con un risolutore di porte, che consente al server di utilizzare porte assegnate dinamicamente, la porta UDP 2049 è codificata in NFS nella maggior parte delle implementazioni.

    Figura 29.3 Impostazioni tipiche del client NFS e del server NFS.

  • Quando il server NFS riceve una richiesta da un client, questa viene passata a una routine di accesso ai file locali, che fornisce l'accesso al disco locale sul server.
  • Il server potrebbe impiegare del tempo per elaborare le richieste del client. Anche l'accesso al file system locale può richiedere del tempo. Durante questo periodo, il server non vuole bloccare le richieste di altri client che necessitano anch'essi di essere serviti. Per far fronte a questa situazione, la maggior parte dei server NFS vengono avviati più volte, il che significa che all'interno del kernel sono presenti più server NFS. I metodi di soluzione specifici dipendono dal sistema operativo. La maggior parte dei kernel Unix non "vivono" su più server NFS, ma avviano invece più processi utente (solitamente chiamati nfsd) che effettuano una singola chiamata di sistema e rimangono all'interno del kernel come processo del kernel.
  • Allo stesso modo, un client NFS impiega tempo per elaborare una richiesta da un processo utente sull'host del client. L'RPC viene inviato al server host, dopodiché è prevista una risposta. Per garantire che i processi utente sull'host client possano sfruttare NFS in qualsiasi momento, sono presenti diversi client NFS in esecuzione all'interno del kernel client. L'implementazione specifica dipende anche dal sistema operativo. I sistemi Unix tipicamente utilizzano una tecnica che ricorda un server NFS: un processo utente chiamato biod effettua una singola chiamata di sistema e rimane all'interno del kernel come processo del kernel.
  • La maggior parte degli host Unix può funzionare come client NFS e server NFS o entrambi contemporaneamente. La maggior parte delle implementazioni PC (MS-DOS) hanno solo implementazioni client NFS. La maggior parte dei mainframe IBM fornisce solo funzionalità server NFS.

    NFS in realtà è molto più che un semplice protocollo NFS. La Figura 29.4 mostra i vari programmi RPC utilizzati con NFS.

    Applicazione

    Numero del programma

    Numero della versione

    Numero di procedure

    convertitore di porta
    NFS
    montare il programma
    gestore del blocco
    monitor di stato

    Figura 29.4 Vari programmi RPC utilizzati in NFS.

    Le versioni che abbiamo mostrato in questa figura come unità si trovano su sistemi come SunOS 4.1.3. Le nuove implementazioni forniscono versioni più recenti di alcuni programmi. Solaris 2.2, ad esempio, supporta anche le versioni 3 e 4 del risolutore di porte e la versione 2 del demone di montaggio. SVR4 supporta anche la versione 3 del convertitore di porte.

    Il demone di montaggio viene richiamato sull'host NFS del client prima che il client possa accedere al file system del server. Descriviamo questo processo di seguito.

    Il gestore dei blocchi e il monitor dello stato consentono al client di bloccare alcuni file che si trovano sul server NFS. Questi due programmi sono indipendenti dal protocollo NFS poiché il blocco richiede l'autenticazione del client sia per l'host del client che per il server e NFS stesso è "neutro". (Parleremo dell'indifferenza di NFS in maggior dettaglio più avanti.) I capitoli 9, 10 e 11 [X/Open 1991] documentano le procedure utilizzate dal gestore dei blocchi e dal monitor dello stato per il blocco in NFS.

    Descrittori di file

    Uno dei fondamenti di NFS è implementato dai descrittori di file. Per accedere a un file o una directory sul server degli oggetti, viene utilizzato opaque. Il termine opaco significa che il server crea un handle di file, lo restituisce al client, che il client utilizza quindi quando accede al file. Il client non guarda mai il contenuto del descrittore di file: il suo contenuto interessa solo il server.

    Il client NFS riceve un handle di file ogni volta che apre un file che risiede effettivamente sul server NFS. Quando un client NFS legge o scrive su questo file (per conto di un processo utente), un handle per il file viene passato al server. Ciò indica che è stato effettuato l'accesso al file.

    In genere il processo utente non funziona con i descrittori di file. I descrittori di file vengono scambiati tra il client NFS e il server NFS. Nella versione 2 di NFS, il descrittore di file è di 32 byte e nella versione 3 è cresciuto fino a 64 byte.

    I server Unix in genere memorizzano le seguenti informazioni nel descrittore di file: identificatore del file system (numeri di dispositivo principale e secondario del file system), numero di inode (i-node) (un numero univoco all'interno del file system), numero di generazione di inode (un numero che cambia ogni volta che l'inode viene riutilizzato per un altro file).

    Protocollo di montaggio

    Il client utilizza il protocollo di montaggio NFS per montare il file system del server prima di accedere ai file NFS. Questo di solito accade durante il caricamento del client. Di conseguenza, il client riceve un handle di file nel file system del server.

    La Figura 29.5 descrive la sequenza di azioni di un client Unix durante l'esecuzione del comando mount(8).

    Figura 29.5 Protocollo di montaggio utilizzato dal comando Unix mount.

    In questo caso vengono eseguiti i seguenti passaggi.

    1. All'avvio del server, viene avviato il convertitore di porta.
    2. Dopo il risolutore di porte, sul server viene avviato il demone di montaggio (mountd). Crea un endpoint TCP e un endpoint UDP e assegna a ciascuno un numero di porta assegnato dinamicamente. Quindi registra questi numeri con il port mapper.
    3. Il client esegue il comando mount, che emette una chiamata RPC al risolutore di porte del server per ottenere un numero di porta dal demone di montaggio sul server. Sia TCP che UDP possono essere utilizzati per la comunicazione tra il client e il risolutore di porte, ma solitamente viene utilizzato UDP.
    4. Il risolutore di porte riporta il numero di porta.
    5. Il comando mount invia una chiamata RPC al demone mount per montare il file system del server. Anche in questo caso è possibile utilizzare TCP o UDP, ma solitamente viene utilizzato UDP. Il server ora può convalidare un client in base al suo indirizzo IP e al numero di porta per vedere se il client può montare il file system specificato.
    6. Il demone di montaggio risponde con un handle di file al file system specificato.
    7. Il comando mount del client emette la chiamata di sistema mount per associare l'handle di file ottenuto nel passo 5 con il punto di montaggio locale sull'host del client. L'handle del file è memorizzato nel codice client NFS e da ora in poi qualsiasi accesso da parte dei processi utente ai file sul file system del server utilizzerà l'handle del file come punto di partenza.

    Questa implementazione lascia l'intero processo di montaggio, ad eccezione della chiamata di sistema di montaggio sul client, ai processi utente piuttosto che al kernel. I tre programmi che abbiamo mostrato - il comando mount, il risolutore di porte e il demone mount - sono processi utente.

    In questo esempio, sull'host sun (client NFS), il comando è stato eseguito

    sole # mount -t nfs bsdi:/usr /nfs/bsdi/usr

    Questo comando monta la directory /usr sull'host bsdi (server NFS) come file system locale /nfs/bsdi/usr. La Figura 29.6 mostra il risultato.

    Figura 29.6 Montaggio della directory bsdi:/usr come /nfs/bsdi/usr sull'host sun.

    Successivamente, quando si accede al file /nfs/bsdi/usr/rstevens/hello.c sul client sun, si accede al file /usr/rstevens/hello.c sul server bsdi.

    Procedure NFS

    Il server NFS prevede 15 procedure, che ora descriveremo. (I numeri utilizzati in questa descrizione non sono gli stessi numeri delle procedure NFS, poiché li abbiamo raggruppati per funzionalità.) Sebbene NFS sia stato progettato per funzionare su più sistemi operativi, non solo sui sistemi Unix, alcune procedure si basano specificamente sul funzionamento Unix , che, a sua volta, potrebbe non essere supportato da altri sistemi operativi (ad esempio, collegamenti fisici, collegamenti simbolici, utilizzo di gruppo, diritti di accesso all'esecuzione e così via). Il Capitolo 4 contiene ulteriori informazioni sulle caratteristiche dei file system, alcuni dei quali vengono utilizzati da NFS.

    1. GETATTR. Restituisce gli attributi del file: tipo di file (file normale, directory, ecc.), diritti di accesso, dimensione del file, proprietario del file, ora dell'ultimo accesso e così via.
    2. SETATTR. Imposta gli attributi del file. È possibile impostare solo un insieme specifico di attributi: diritti di accesso, proprietario, proprietà del gruppo, dimensione, ora dell'ultimo accesso e ora dell'ultima modifica.
    3. STATISTICHE. Restituisce lo stato del file system: quantità di spazio libero, dimensione ottimale per il trasferimento e così via. Utilizzato, ad esempio, dal comando Unix df.
    4. CERCARE. "Valuta" il file. Questa procedura viene richiamata dal client ogni volta che un processo utente apre un file che si trova sul server NFS. Viene restituito un handle di file, insieme agli attributi del file.
    5. LEGGERE. Legge da un file. Il client specifica un handle di file, un offset di byte iniziale e il numero massimo di byte da leggere (fino a 8192).
    6. SCRIVERE. Scrive su un file. Il client specifica l'handle del file, l'offset iniziale in byte, il numero di byte da scrivere e i dati da scrivere.

      Le scritture NFS devono essere sincrone (con un'attesa). Il server non può rispondere correttamente finché i dati non sono stati scritti correttamente (e qualsiasi altra informazione sul file che deve essere aggiornata) sul disco.

    7. CREARE. Crea un file.
    8. RIMUOVERE. Elimina un file.
    9. RINOMINARE. Rinomina il file.
    10. COLLEGAMENTO. Crea un collegamento reale al file. Un collegamento fisico è un concetto Unix che specifica che un dato file su disco può avere un numero qualsiasi di punti di ingresso (nomi chiamati anche collegamenti reali) che puntano a quel file.
    11. SYMLINK. Crea un collegamento simbolico a un file. Un collegamento simbolico è un file che contiene il nome di un altro file. La maggior parte delle operazioni eseguite su un collegamento simbolico (ad esempio l'apertura) vengono effettivamente eseguite sul file a cui punta il collegamento simbolico.
    12. LEGGILINK. La lettura di un collegamento simbolico restituisce il nome del file a cui punta il collegamento simbolico.
    13. MKDIR. Crea una directory.
    14. RMDIR. Elimina una directory.
    15. READDIR. Legge la directory. Utilizzato, ad esempio, dal comando Unix ls.

    Infatti, i nomi delle procedure mostrati iniziano con il prefisso NFSPROC_, che abbiamo omesso.

    UDP o TCP?

    NFS è stato originariamente scritto per utilizzare UDP e tutti i fornitori forniscono questa funzionalità. Tuttavia, anche le implementazioni più recenti supportano TCP. Il supporto TCP viene utilizzato per operare su reti globali, che stanno diventando sempre più veloci. Pertanto, l'uso di NFS non è più limitato alle reti locali.

    I confini tra le reti locali e globali si stanno sfumando e tutto ciò sta accadendo molto rapidamente. I tempi di ritorno variano in un intervallo molto ampio e il traboccamento si verifica sempre più frequentemente. Queste caratteristiche delle reti globali portano al fatto che utilizzano sempre più gli algoritmi che abbiamo considerato per TCP: avvio lento ed evitamento della congestione. Poiché UDP non fornisce nulla di simile a questi algoritmi, essi o altri simili devono essere integrati nel client e nel server NFS, altrimenti deve essere utilizzato TCP.

    NFS su TCP

    L'implementazione NFS di Berkeley Net/2 supporta sia UDP che TCP. [Macklem 1991] descrive questa implementazione. Diamo un'occhiata a come differisce l'utilizzo di NFS quando si esegue su TCP.

    1. All'avvio del server, avvia il server NFS, che si apre attivamente sulla porta TCP 2049, in attesa che arrivi una richiesta di connessione dal client. Questo di solito viene fatto in aggiunta al normale NFS UDP, che ascolta i datagrammi in entrata sulla porta UDP 2049.
    2. Quando un client monta il file system di un server utilizzando TCP, esegue un'apertura attiva sulla porta TCP 2049 sul server. Ciò stabilisce una connessione TCP tra il client e il server per questo file system. Se lo stesso client monta un altro file system sullo stesso server, viene creata un'altra connessione TCP.
    3. Sia il client che il server impostano l'opzione TCP "resta vivo" alle loro estremità della connessione (Capitolo 23). Ciò consente di determinare il momento del fallimento o del riavvio dell'uno o dell'altro partecipante allo scambio.
    4. Tutte le applicazioni sul client che utilizzano il file system del server condividono la stessa connessione TCP a quel file system. Ad esempio, se ci fosse la Figura 29.6, ci sarebbe un'altra directory su bsdi, chiamata smith, sotto la directory /usr, le chiamate ai file in /nfs/bsdi/usr/rstevens e /nfs/bsdi/usr/smith sarebbero condivise la stessa cosa, la stessa connessione TCP.
    5. Se il client determina che il server si è bloccato o si è riavviato (dopo aver ricevuto un errore TCP "connessione scaduta" o "connessione chiusa dall'host"), tenta di riconnettersi al server. Il client esegue un'altra apertura attiva per ristabilire la connessione TCP per questo file system. Qualsiasi richiesta da parte di un client che è scaduta su una connessione precedente viene riemessa su una nuova connessione.
    6. Se un client fallisce, lo stesso accadrà alle applicazioni che erano in esecuzione prima del fallimento. Quando il client si riavvia, potrebbe rimontare il file system del server utilizzando TCP, utilizzando una diversa connessione TCP al server. La connessione precedente tra client e server per questo file system è in uno stato semiaperto (il server pensa che sia ancora aperto), tuttavia, poiché il server ha impostato l'opzione "resta in vita", questa connessione semiaperta sarà chiuso quando il server TCP invia la sonda successiva." resta vivo."

    Nel corso del tempo, altri fornitori prevedono di supportare NFS su TCP.

    Esempi di NFS

    Usiamo tcpdump per vedere quali routine NFS vengono invocate dal client per le normali operazioni sui file. Quando tcpdump determina che un datagramma UDP contiene una chiamata RPC (la chiamata è 0 nella Figura 29.1) con la porta di destinazione 2049, decodifica il datagramma come una richiesta NFS. Allo stesso modo, se un datagramma UDP contiene una risposta RPC (la risposta è 1 nella Figura 29.2) con una porta di origine 2049, decodifica il datagramma come una risposta NFS.

    Esempio semplice: leggere un file

    Nel primo esempio, copieremo un file situato sul server NFS sul terminale utilizzando il comando cat(1):

    Sole% cat /nfs/bsdi/usr/rstevens/ciao.c copiare un file sul terminale
    principale()
    {
    printf("ciao mondo\n");
    }

    Il file system /nfs/bsdi/usr sull'host sun (client NFS) è in realtà il file system /usr sull'host bsdi (server NFS), come mostrato nella Figura 29.6. Il kernel sun lo rileva quando cat apre un file e utilizza NFS per accedere al file. La Figura 29.7 mostra l'output del comando tcpdump.

    1 0.0 sun.7aa6 > bsdi.nfs: 104 getattr
    2 0.003587 (0.0036) bsdi.nfs > sun.7aa6: risposta ok 96

    3 0.005390 (0.0018) sun.7aa7 > bsdi.nfs: 116 ricerca "rstevens"
    4 0.009570 (0.0042) bsdi.nfs > sun.7aa7: risposta ok 128

    5 0.011413 (0.0018) sun.7aa8 > bsdi.nfs: 116 ricerca "ciao.c"
    6 0.015512 (0.0041) bsdi.nfs > sun.7aa8: risposta ok 128

    7 0.018843 (0.0033) sun.7aa9 > bsdi.nfs: 104 getattr
    8 0.022377 (0.0035) bsdi.nfs > sun.7aa9: risposta ok 96

    9 0,027621 (0,0052) sun.7aaa > bsdi.nfs: 116 leggi 1024 byte @ 0
    10 0.032170 (0.0045) bsdi.nfs > sun.7aaa: risposta ok 140

    Figura 29.7 Operazione NFS durante la lettura di un file.

    Il comando tcpdump decodifica la richiesta o risposta NFS e stampa anche il campo XID per il client invece del numero di porta. Il campo XID nelle righe 1 e 2 è 0x7aa6.

    Il nome file /nfs/bsdi/usr/rstevens/hello.c viene elaborato dalla funzione open nel kernel client un elemento nome alla volta. Quando la funzione open raggiunge /nfs/bsdi/usr, determina che si tratta di un punto di montaggio del file system NFS.

    Nella riga 1, il client chiama GETATTR per ottenere gli attributi della directory del server montata dal client (/usr). Questa richiesta RPC contiene 104 byte di dati, oltre alle intestazioni IP e UDP. La risposta sulla riga 2 restituisce OK e contiene 96 byte di dati, oltre alle intestazioni IP e UDP. Possiamo vedere in questa figura che il messaggio NFS minimo contiene circa 100 byte di dati.

    Alla riga 3, il client chiama LOOKUP sul file rstevens e riceve una risposta OK alla riga 4. LOOKUP specifica il nome del file rstevens e un handle per il file che è stato memorizzato dal kernel quando è stato montato il file system remoto. La risposta contiene un nuovo handle di file che verrà utilizzato nel passaggio successivo.

    Alla riga 5, il client CERCA il file hello.c utilizzando l'handle di file della riga 4. Riceve un handle di file diverso alla riga 6. Questo nuovo handle di file è esattamente quello che il client usa alle righe 7 e 9 per accedere al file / nfs /bsdi/usr/rstevens/ciao.c. Vediamo che il client esegue una RICERCA su ciascun componente del nome nel percorso del file da aprire.

    Alla riga 7, il client esegue nuovamente GETATTR, seguito da READ alla riga 9. Il client richiede 1024 byte a partire dall'offset 0, ma riceve meno di 1024 byte di dati. (Dopo aver sottratto le dimensioni dei campi RPC e degli altri valori restituiti dalla procedura READ, alla riga 10 vengono restituiti 38 byte di dati. Questa è esattamente la dimensione del file hello.c.)

    In questo esempio, il processo utente non sa nulla di queste richieste e risposte NFS, che vengono eseguite dal kernel. L'applicazione chiama semplicemente la funzione core open, che provoca lo scambio di 3 richieste e 3 risposte (righe 1-6), quindi chiama la funzione core read, che chiama 2 richieste e 2 risposte (righe 7-10). Per l'applicazione client, il file situato sul server NFS è trasparente.

    Esempio semplice: creazione di una directory

    Come altro esempio, cambiamo la directory di lavoro in una directory che si trova sul server NFS, quindi creiamo una nuova directory:

    Sole% cd /nfs/bsdi/usr/rstevens cambiare la directory di lavoro
    sole% mkdir Mail creare una directory

    La Figura 29.8 mostra l'output del comando tcpdump.

    1 0.0 sun.7ad2 > bsdi.nfs: 104 getattr
    2 0.004912 (0.0049) bsdi.nfs > sun.7ad2: risposta ok 96

    3 0.007266 (0.0024) sun.7ad3 > bsdi.nfs: 104 getattr
    4 0.010846 (0.0036) bsdi.nfs > sun.7ad3: risposta ok 96

    5 35.769875 (35.7590) sun.7ad4 > bsdi.nfs: 104 getattr
    6 35.773432 (0.0036) bsdi.nfs > sun.7ad4: risposta ok 96

    7 35.775236 (0.0018) sun.7ad5 > bsdi.nfs: 112 ricerca "Posta"
    8 35.780914 (0.0057) bsdi.nfs > sun.7ad5: risposta ok 28

    9 35.782339 (0.0014) sun.7ad6 > bsdi.nfs: 144 mkdir "Posta"
    10 35.992354 (0.2100) bsdi.nfs > sun.7ad6: risposta ok 128

    Figura 29.8 Operazione NFS quando si cambia la directory (cd) nella directory NFS e quindi si crea la directory (mkdir).

    Quando si cambia directory, il client chiama GETATTR due volte (righe 1-4). Quando creiamo una nuova directory, il client chiama GETATTR (righe 5 e 6), quindi LOOKUP (righe 7 e 8 per verificare che la directory non esista), quindi MKDIR per creare la directory (righe 9 e 10). La risposta OK alla riga 8 non significa che la directory esiste. Significa semplicemente che la procedura ha restituito un valore. tcpdump non interpreta il valore restituito dalle procedure NFS. Il comando stampa semplicemente OK e il numero di byte di dati nella risposta.

    Indifferenza

    Una delle caratteristiche di NFS (i critici di NFS lo chiamano un difetto, non una caratteristica) è che il server NFS è indifferente. Al server non interessa quali client accedono a quali file. Si noti che l'elenco delle procedure NFS mostrato in precedenza non include una procedura di apertura o chiusura. La procedura LOOKUP è simile all'apertura, ma il server non sa mai se il client ha avuto accesso al file dopo che è stata effettuata la LOOKUP.

    Il motivo di questo "comportamento di fregatura" è quello di rendere più semplice il ripristino da un errore del server dopo l'arresto anomalo e il riavvio.

    Esempio: guasto del server

    Nell'esempio seguente, stiamo leggendo un file da un server NFS quando il server si blocca e si riavvia. Ciò mostrerà come "l'indifferenza" del server consente al client di "non sapere" che il server ha fallito. Per tutto il tempo in cui il server si blocca e si riavvia, il client non è a conoscenza del problema e l'applicazione client funziona come prima.

    Sul client sun, abbiamo eseguito cat con un file molto grande come argomento (/usr/share/lib/termcap sul server NFS svr4), abbiamo disconnesso il cavo Ethernet durante il trasferimento, spento e riavviato il server, quindi ricollegato il cavo . Il client è stato configurato per leggere 1024 byte per lettura NFS. La Figura 29.9 mostra l'output di tcpdump.

    Le righe 1-10 corrispondono al client che apre il file. Questa operazione è simile a quella mostrata nella Figura 29.7. Alla riga 11 vediamo la prima lettura (READ) dal file di 1024 byte di dati; la risposta è tornata alla riga 12. Ciò continua fino alla riga 129 (leggendo READ a 1024 byte e quindi rispondendo OK).

    Nelle righe 130 e 131 vediamo due richieste che scadono e vengono ripresentate nelle righe 132 e 133. Prima domanda: vediamo due richieste di lettura, una inizia all'offset 65536 e l'altra inizia all'offset 73728, perché? Il kernel client ha determinato che l'applicazione client stava leggendo in sequenza e ha tentato di ottenere blocchi di dati in anticipo. (La maggior parte dei kernel Unix esegue questa lettura anticipata.) Il kernel client esegue anche diversi demoni di input/output (I/O) di blocchi NFS (processi biod) che tentano di generare più richieste RPC per conto del client. Un demone legge 8192 byte, a partire da 65536 (in catene da 1024 byte), e gli altri leggono in avanti 8192 byte, a partire da 73728.

    Le ritrasmissioni del client vengono visualizzate sulle righe 130-168. Alla riga 169 vediamo che il server si è riavviato e ha inviato una richiesta ARP prima di rispondere alla richiesta NFS del client alla riga 168. La risposta alla riga 168 viene inviata alla riga 171. Le richieste READ del client continuano.

    1 0.0 sun.7ade > svr4.nfs: 104 getattr
    2 0.007653 (0.0077) svr4.nfs > sun.7ade: risposta ok 96

    3 0.009041 (0.0014) sun.7adf > svr4.nfs: 116 ricerca "condividi"
    4 0.017237 (0.0082) svr4.nfs > sun.7adf: risposta ok 128

    5 0.018518 (0.0013) sun.7ae0 > svr4.nfs: 112 ricerca "lib"
    6 0.026802 (0.0083) svr4.nfs > sun.7ae0: risposta ok 128

    7 0.028096 (0.0013) sun.7ae1 > svr4.nfs: 116 ricerca "termcap"
    8 0.036434 (0.0083) svr4.nfs > sun.7ae1: risposta ok 128

    9 0.038060 (0.0016) sun.7ae2 > svr4.nfs: 104 getattr
    10 0.045821 (0.0078) svr4.nfs > sun.7ae2: risposta ok 96

    11 0.050984 (0.0052) sun.7ae3 > svr4.nfs: 116 leggi 1024 byte @ 0
    12 0.084995 (0.0340) svr4.nfs > sun.7ae3: risposta ok 1124

    Lettura

    128 3.430313 (0.0013) sun.7b22 > svr4.nfs: 116 letti 1024 byte @ 64512
    129 3.441828 (0.0115) svr4.nfs > sun.7b22: risposta ok 1124

    130 4.125031 (0.6832) dom.7b23 >
    131 4.868593 (0.7436) dom.7b24 >

    132 4.993021 (0.1244) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536
    133 5.732217 (0.7392) sun.7b24 > svr4.nfs: 116 leggi 1024 byte @ 73728

    134 6.732084 (0.9999) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536
    135 7.472098 (0.7400) sun.7b24 > svr4.nfs: 116 leggi 1024 byte @ 73728

    136 21.101964 (2.7399) dom.7b23 >
    137 10.951960 (0.7400) dom.7b24 >

    138 17.171767 (6.2198) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536
    139 17.911762 (0.7400) sun.7b24 > svr4.nfs: 116 leggi 1024 byte @ 73728

    140 31.092136 (13.1804) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536
    141 31.831432 (0.7393) sun.7b24 > svr4.nfs: 116 letti 1024 byte @ 73728

    142 51.090854 (19.2594) sun.7b23 > svr4.nfs: 116 leggi 1024 byte @ 65536
    143 51.830939 (0.7401) sun.7b24 > svr4.nfs: 116 letti 1024 byte @ 73728

    144 71.090305 (19.2594) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536
    145 71.830155 (0.7398) sun.7b24 > svr4.nfs: 116 letti 1024 byte @ 73728

    Ritrasmissioni

    167 291.824285 (0.7400) sun.7b24 > svr4.nfs: 116 leggi 1024 byte @ 73728
    168 311.083676 (19.2594) sun.7b23 > svr4.nfs: 116 letti 1024 byte @ 65536

    Server riavviato

    169 311.149476 (0.0658) arp chi-ha il sole racconta svr4
    170 311.150004 (0.0005) risposta arp sole è alle 8:0:20:3:f6:42

    171 311.154852 (0.0048) svr4.nfs > sun.7b23: risposta ok 1124

    172 311.156671 (0.0018) sun.7b25 > svr4.nfs: 116 letti 1024 byte @ 66560
    173 311.168926 (0.0123) svr4.nfs > sun.7b25: risposta ok 1124
    lettura

    Figura 29.9 Client che legge un file quando il server NFS si blocca e si riavvia.

    L'applicazione client non saprà mai che il server si è bloccato e si è riavviato, tranne che c'è stata una pausa di 5 minuti tra le righe 129 e 171, quindi il crash del server è trasparente per il client.

    Per stimare la durata dei timeout di ritrasmissione in questo esempio, immagina che ci siano due demoni client, ciascuno con i propri timeout. Gli intervalli per il primo demone (lettura dall'offset 65536) sono approssimativamente i seguenti (arrotondati a due cifre decimali): 0,68; 0,87; 1,74; 3,48; 6,96; 13,92; 20,0; 20,0; 20.0 e così via. Gli intervalli per il secondo demone (lettura dall'offset 73728) sono esattamente gli stessi. Ciò significa che questi client NFS utilizzano timeout multipli di 0,875 secondi, con un limite superiore di 20 secondi. Dopo ogni timeout, l'intervallo di ritrasmissione raddoppia: 0,875; 1,75; 3,5; 7.0 e 14.0.

    Quanto tempo occorrerà al client per effettuare le ritrasmissioni? Il client ha due opzioni che possono influire su questo. Innanzitutto, se il filesystem del server è montato manualmente, il client ritrasmetterà per sempre, ma se il filesystem del server è montato tramite software, il client smetterà di provare dopo un numero fisso di ritrasmissioni. Inoltre, nel caso di un montaggio hardware, il client ha la possibilità di consentire all'utente di interrompere le ritrasmissioni non riuscite o di non interromperle. Se, durante il montaggio del file system del server, l'host del client indica che può essere interrotto e se non vogliamo attendere 5 minuti per il riavvio del server dopo un crash, possiamo inserire un simbolo di interruzione per terminare l'applicazione client.

    Diverse procedure identiche

    Le procedure RPC possono essere eseguite dal server più volte, ma restituiscono sempre lo stesso risultato. Ad esempio, la procedura di lettura NFS. Come abbiamo visto nella Figura 29.9, il client semplicemente riemette la chiamata READ finché riceve una risposta. Nel nostro esempio, il motivo della ritrasmissione era che il server era inattivo. Se il server non ha fallito e i messaggi contenenti risposte RPC sono andati persi (poiché UDP è un protocollo inaffidabile), il client semplicemente ritrasmette e il server esegue nuovamente la stessa lettura. La stessa parte dello stesso file viene letta nuovamente e inviata al client.

    Funziona perché ogni richiesta di lettura READ contiene un offset iniziale. Se la procedura NFS chiedesse al server di leggere i successivi N byte del file, non funzionerebbe. Se il server non fosse indifferente (questo è l'opposto di indifferente) e la risposta andasse persa e il client riemettesse READ per i successivi N byte, il risultato sarebbe diverso. Questo è il motivo per cui le procedure NFS READ e WRITE hanno un offset iniziale. È il client che mantiene lo stato (l'offset corrente per ciascun file), non il server.

    Sfortunatamente, non tutte le operazioni sul file system possono essere eseguite più volte. Ad esempio, immagina i seguenti passaggi: il client NFS emette una richiesta REMOVE per rimuovere un file; Il server NFS cancella il file e risponde OK; risposta del server persa; Il client NFS scade e ritrasmette la richiesta; Il server NFS non riesce a trovare il file e restituisce un errore; L'applicazione client riceve un errore che indica che il file non esiste. Questo errore viene restituito all'applicazione client e contiene informazioni errate: il file non esisteva ed è stato eliminato.

    Di seguito è riportato un elenco di procedure NFS che possono essere eseguite più volte: GETATTR, STATFS, LOOKUP, READ, WRITE, READLINK e READDIR. Procedure che non possono essere eseguite più volte: CREATE, REMOVE, RENAME, LINK, SYMLINK, MKDIR e RMDIR. SETATTR viene solitamente eseguito più volte, a meno che non sia stato utilizzato per troncare un file.

    Poiché è sempre probabile che si verifichino risposte orfane quando si utilizza UDP, i server NFS devono disporre di un modo per gestire le operazioni che non possono essere eseguite più volte. La maggior parte dei server dispone di una cache delle risposte recenti in cui memorizzano le ultime risposte ricevute per tali operazioni. Ogni volta che il server riceve una richiesta, prima esamina la cache e, se viene trovata una corrispondenza, restituisce la risposta precedente anziché richiamare nuovamente la procedura NFS. [Juszczak 1989] descrive i dettagli di questi tipi di cache.

    Questo approccio alle procedure server si applica a tutte le applicazioni basate su UDP, non solo a NFS. Il DNS, ad esempio, fornisce un servizio che può essere utilizzato più volte senza problemi. Il server DNS può interrogare il parser un numero qualsiasi di volte, il che non porterà a risultati negativi (forse, tranne che le risorse di rete saranno occupate).

    NFS versione 3

    Nel corso del 1994 furono rilasciate le specifiche per la versione 3 del protocollo NFS [Sun Microsystems 1993]. Si prevede che le implementazioni diventino disponibili nel corso del 1994.

    Ecco una rapida carrellata delle principali differenze tra le versioni 2 e 3. Le chiameremo V2 e V3.

    1. I descrittori di file nella V2 sono un array di dimensione fissa di 32 byte. Nella V3 è un array di dimensioni variabili con una dimensione massima di 64 byte. Un array di lunghezza variabile in XDR è definito da un contatore di 4 byte seguito da byte reali. Ciò riduce la dimensione del descrittore di file in implementazioni come Unix, dove sono richiesti solo circa 12 byte, ma consente alle implementazioni non Unix di scambiare informazioni aggiuntive.
    2. V2 limita il numero di byte per procedura RPC READ o WRITE a 8192 byte. Questa limitazione non si applica nella V3, il che a sua volta significa che utilizzando UDP il limite sarà solo la dimensione del datagramma IP (65535 byte). Ciò consente di utilizzare pacchetti di grandi dimensioni per la lettura e la scrittura su reti veloci.
    3. Le dimensioni dei file e gli offset dei byte iniziali per le procedure READ e WRITE sono stati espansi da 32 a 64 bit, consentendo di gestire file di dimensioni maggiori.
    4. Gli attributi del file vengono restituiti in ogni chiamata che può influire sugli attributi. Ciò riduce il numero di chiamate GETATTR richieste dal client.
    5. Le scritture (WRITE) possono essere asincrone, mentre nella V2 avrebbero dovuto essere sincrone. Ciò potrebbe migliorare le prestazioni della procedura WRITE.
    6. È stata rimossa una procedura (STATFS) e ne sono state aggiunte sette: ACCESS (controlla i permessi dei file), MKNOD (crea uno speciale file Unix), READDIRPLUS (restituisce i nomi dei file in una directory insieme ai loro attributi), FSINFO (restituisce informazioni statistiche su il file system), FSSTAT (restituisce informazioni sul file system dinamico), PATHCONF (restituisce informazioni sul file POSIX.1) e COMMIT (esegue il commit delle scritture asincrone effettuate in precedenza sull'archiviazione persistente).

    Brevi conclusioni

    RPC è un modo per creare un'applicazione client-server in modo tale che il client chiami semplicemente le procedure sul server. Tutti i dettagli della rete sono nascosti negli stub del client e del server, generati per le applicazioni dal pacchetto RPC e nelle routine della libreria RPC. Abbiamo mostrato il formato dei messaggi di chiamata e risposta RPC e menzionato che XDR viene utilizzato per codificare i valori, consentendo ai client e ai server RPC di funzionare su architetture di macchine diverse.

    Una delle applicazioni RPC più utilizzate è Sun NFS, un protocollo di accesso ai file eterogeneo ampiamente utilizzato su host praticamente di tutte le dimensioni. Abbiamo esaminato NFS e il modo in cui utilizza UDP o TCP. Il protocollo NFS versione 2 definisce 15 procedure.

    L'accesso del client a un server NFS inizia con un protocollo di montaggio, dopo il quale viene restituito al client un handle di file. Il client può quindi accedere ai file sul file system del server utilizzando questo handle di file. I nomi dei file vengono cercati sul server un elemento nome alla volta, restituendo un nuovo handle di file per ciascun elemento. Il risultato finale è un handle del file a cui è stato effettuato l'accesso e che viene utilizzato per letture e scritture sequenziali.

    NFS cerca di rendere tutte le sue procedure indipendenti dal numero di esecuzioni in modo che il client possa semplicemente riemettere la richiesta se la risposta viene persa. Abbiamo visto esempi di ciò in cui un client stava leggendo un file mentre il server si bloccava e si riavviava.

    Esercizi

    Nella Figura 29.7 abbiamo visto che tcpdump interpreta i pacchetti come richieste e risposte NFS e stampa l'XID. tcpdump può eseguire questa operazione per eventuali richieste o risposte RPC?
  • Perché pensi che il programma server RPC sui sistemi Unix utilizzi porte assegnate dinamicamente anziché porte pre-conosciute?
  • Il client RPC ha richiamato due procedure server. Il completamento della prima procedura ha richiesto 5 secondi e il secondo - 1 secondo. Il client ha un timeout di 4 secondi. Disegna un diagramma temporale di ciò che viene scambiato tra client e server. (Immaginiamo che non venga impiegato tempo per passare un messaggio dal client al server e viceversa.)
  • Nell'esempio della Figura 29.9, cosa accadrebbe se la scheda Ethernet del server NFS fosse rimossa mentre il server NFS era spento?
  • Quando il server si è riavviato nella Figura 29.9, ha elaborato la richiesta a partire dall'offset 65536 (righe 168 e 171), quindi ha elaborato la richiesta successiva a partire dall'offset 66560 (righe 172 e 173). Cosa succede alla query che inizia con l'offset 73728 (riga 167)?
  • Quando abbiamo descritto le procedure indipendenti dal numero di esecuzioni NFS, abbiamo mostrato un esempio di una risposta REMOVE andata persa nella rete. Cosa succede in questo caso se viene utilizzato TCP anziché UDP?
  • Se il server NFS utilizza una porta assegnata dinamicamente invece della porta 2049, cosa succede al client NFS quando il server si arresta in modo anomalo e si riavvia?
  • Ci sono pochissimi numeri di porta riservati (Capitolo 1, sezione “Numeri di porta”), con un massimo di 1023 per host. Se un server NFS richiede che i suoi client abbiano porte riservate (cosa che di solito fanno) e un client NFS che utilizza TCP monta N file system su N server diversi, il client deve avere numeri di porta riservati diversi per ciascuna connessione?
  • I migliori articoli sull'argomento