NFS: Unterschied zwischen den Versionen
K Dirkwagner verschob die Seite Entwuft:Dirkwagner:Linux:Network File System nach Entwurf:Linux:Network File System, ohne dabei eine Weiterleitung anzulegen |
|
(kein Unterschied)
|
Version vom 18. Oktober 2020, 08:53 Uhr
Einführung
Das Network File System – abgekürzt NFS (auch: Network File Service) – ist ein von Sun Microsystems entwickeltes Protokoll, das den Zugriff auf Dateien über ein Netzwerk ermöglicht. Dabei werden die Dateien nicht wie z. B. bei FTP übertragen, sondern die Benutzer können auf Dateien, die sich auf einem entfernten Rechner befinden, so zugreifen, als ob sie auf ihrer lokalen Festplatte abgespeichert wären.
Bei diesem UNIX-Netzwerkprotokoll handelt es sich um einen Internet-Standard (RFC 1094, RFC 1813, RFC 3530), der auch als verteiltes Dateisystem (engl. Distributed File System) bezeichnet wird.
Die Entsprechung zu NFS heißt unter Windows- und OS/2-Umgebungen Server Message Block (SMB). Während sich bei SMB der Benutzer authentifiziert, authentifiziert das populärere NFS V3 den Client-Rechner, erst NFS V4 ermöglicht Benutzerauthentifikation. NFS-Dienste sind auch auf Microsoft-Windows-Servern verfügbar, wodurch UNIX-Workstations Zugang zu deren Dateien erhalten können, allerdings wird in gemischten Umgebungen meist SMB mit Samba auf Unixseite verwendet.
NFS arbeitet auf dem Netzwerk-Transportprotokoll TCP/IP. NFS ist ursprünglich ein zustandsloses UDP-Protokoll. Mittlerweile gibt es aber auch NFS über TCP. Die aktuelle Version 4 ist nicht mehr zustandslos, was die Programmierung und die Netzwerksicherung extrem erleichtert. Sie wurde maßgeblich durch die IETF entwickelt, nachdem SUN die Entwicklung abgegeben hatte.
NFS im OSI-Schichtenmodell
Anwendung | NFS | |||
Darstellung | XDR | |||
Sitzung | (Sun-) RPC | |||
Transport | UDP | TCP | ||
Netzwerk | IP | |||
Netzzugang | Ethernet | TokenRing | FDDI | … |
Ablauf der Datenübertragung
Im Folgenden ist der prinzipielle Ablauf einer NFS-Kommunikation des zustandslosen NFS beschrieben. Szenario: Ein Nutzer des Client-Rechners möchte ein entferntes Verzeichnis ("/directory") öffnen und eine darin befindliche Datei ("test") anzeigen lassen.
Damit ein Datenaustausch zwischen NFS-Server und Client stattfinden kann, muss der NFS-Server gestartet und beim Portmapper registriert sein.*
- Portmapper gibt Portnummer für mountd heraus
- Client kontaktiert mountd und fragt nach einem Filehandle für "/directory"
- mountd gibt ein Filehandle 0 zurück
- Client kontaktiert Portmapper und fragt nach dem Port für NFS (nfsd)
- Portmapper gibt Portnummer für nfsd heraus
- Client führt LOOKUP-Prozedur aus mit den Parametern Filehandle 0 und dem Dateinamen ("test")
- nfsd gibt Filehandle 1 für Datei ("test") heraus
- Client führt READ-Prozedur aus mit dem Parameter Filehandle 1
- nfsd gibt Inhalt der Datei ("test") zurück (Daten)
Design der frühen Versionen des Systems
Ein Programm greift auf das Dateisystem über Systemaufrufe zu. Unter UNIX sind die wichtigsten Systemaufrufe:* open, close – Öffnen und Schließen einer Datei
- read, write – Lesen und Schreiben
- create, unlink – Erzeugen und Löschen
- mkdir, rmdir – Erzeugen und Löschen eines Verzeichnisses
- readdir – Lesen von Verzeichniseinträgen
Ein Netzwerkdateisystem muss diese Aufrufe in Netzwerkpakete verpacken und an einen Server senden. Dieser antwortet dann mit der entsprechenden Information oder einem Fehler.
Die Entwickler von Sun Microsystems entschieden sich zunächst für ein Remote Procedure Call-Modell. Das XDR setzt die Parameter in ein maschinenunabhängiges Format um, die Zugriffe werden dann über RPC wie ein normaler Unterprogrammaufruf behandelt.
Die Systemaufrufe werden aber nicht direkt in RPC-Aufrufe umgesetzt, da dann eine über open geöffnete Datei auch auf dem Server geöffnet werden müsste. Bei vielen Clients wären die Server dann schnell überlastet, da die Maschinen Mitte der 1980er Jahre noch relativ wenig Speicher hatten. Die Aufgaben des Servers wurden daher so einfach wie möglich gehalten, der Server merkt sich keine Dateiinformationen zwischen zwei RPC-Aufrufen. Er ist also zustandslos.
Statt open wird ein lookup-Aufruf implementiert. Dieser liefert ein Datei-"Handle", das die Inodenummer und die Gerätenummer des Massenspeichers auf dem Server enthält. Über dieses Handle kann eine Datei auf dem Server eindeutig identifiziert werden. Unter Unix steht über diese beiden Nummern die Dateiinformation effizient ohne Suche eindeutig zur Verfügung.
Die weiteren Aufrufe wie read oder write müssen stets ein Offset übergeben, so dass der Server auch hier ohne Kenntnis früherer Operation die gewünschte Information eindeutig liefern kann.
Weitere Eigenschaften des Protokolls sind* nur kurze Cachezeiten (wenige Sekunden) für Verzeichnisinformationen und Dateiattribute
- kein Datencache
- Verwendung des verbindungslosen User Datagram Protocols UDP
- Lock- und Mount-Operationen über zusätzliche Hilfsprotokolle
- Verwendung von Unix-Dateiattributen (zum Beispiel Benutzer-uid)
Wegen des einfachen Designs läuft NFS in normalen Umgebungen gut:* lokales Netzwerk mit kurzen Antwortzeiten
- Ausführen von Programmen über das lokale Netzwerk
- Normale Benutzeraktivitäten (Editieren, Programme übersetzen)
- Server mit relativ wenig Arbeitsspeicher
Weniger gut ist das Verhalten bei* gemeinsamer Nutzung von Dateien
- Verwendung über das Internet (lange Antwortzeiten, geringe Sicherheit)
- Verwendung von Firewalls (UDP, kein fester Port wegen Portmapper)
Das Protokoll wurde Ende der 1980er Jahre entwickelt. Auch teure Workstations hatten zu dieser Zeit nur wenige Megabytes Arbeitsspeicher, typisch etwa 4 bis 8 MB. Ein NFS-Server kann auf solchen Maschinen aufgrund des Designs trotzdem effizient betrieben werden.
Wegen des zustandslosen Servers kann dieser ohne Datenverlust heruntergefahren und neu gestartet werden. Programme stürzen nicht ab und Benutzer müssen dann einfach warten, bis der Server wieder verfügbar ist.
Plattenlose Workstations
Workstations können über NFS ganz ohne Plattenlaufwerk betrieben werden. Das Betriebssystem und die Betriebsparameter können über Protokolle wie BOOTP und TFTP geladen werden. Ein spezieller Kernel kann dann über NFS bereits auf das Wurzel-Laufwerk unter Unix zugreifen. Spezielle plattenlose Workstations (diskless workstations) wurden von der Firma Sun in den 1990er Jahren angeboten.
Vorteil ist ein verringerter Wartungsaufwand, gemeinsame Nutzung von Plattenplatz sowie einfachere und preiswerte Client-Workstations (Thin-Clients). Bei vielen Clients wird der Server jedoch stark belastet, außerdem sind die Zugriffszeiten über Netzwerk in den meisten Fällen langsamer.
PC-NFS
Sun und andere Firmen boten in den 1990er Jahren auch NFS-Clientsoftware für PCs unter Windows an, das PC-NFS. Der Server musste weiterhin eine Unix-Workstation sein. Bis Windows für Workgroups war der Netzwerkzugriff unter Windows nicht Teil des Betriebssystems. In Unix-Umgebungen wurde der Einsatz von PCs dadurch wesentlich erleichtert.
PC-NFS musste mit den unterschiedlichen Konzepten des DOS/Windows-Systems kämpfen. Die damaligen Windows-Versionen erlaubten nur Dateinamen mit bis zu acht Zeichen sowie eine drei Zeichen lange Erweiterung, die durch einen Punkt getrennt wurde (z. B. AUTOEXEC.BAT), während Unix 255 Zeichen lange Pfadnamen erlaubte. Die Dateinamen unterschieden im Gegensatz zu DOS zwischen Groß- und Kleinschreibung. PC-NFS musste also zwischen den Dateinamenkonzepten übersetzen.
Ein Unix-Dateiname file.txt erschien als FILE.TXT unter Windows/DOS, während ein Dateiname Dokumentation.txt etwa in DOKU~123.TXT umgesetzt wurde.
NFS Version 4
Die NFS Version 4 stellt eine Neuimplementierung dar, die neuere Erfordernisse berücksichtigt. Sie ist in RFC 3530 standardisiert.
Die Unix-Lastigkeit der frühen Versionen wird soweit wie möglich verringert. Die UNIX-Benutzer- und Gruppennummern werden durch Zeichenketten, etwa Benutzername@Rechnername, ersetzt. Da manche Dateisysteme keine effiziente Implementierung von eindeutigen Dateihandles ermöglichen, werden flüchtige Handles eingeführt, die nur eine bestimmte Zeit zur Verfügung stehen. Unter Unix kann man Handles sehr einfach aus der Geräte- und Inodenummer konstruieren. Auch Dateisysteme, die nicht zwischen Groß- und Kleinschreibung unterscheiden sowie benutzerdefinierte Dateiattribute werden jetzt unterstützt.
Das Mount- und Lockprotokoll sind jetzt Bestandteil des Protokolls selbst, Hilfsprotokolle werden nicht mehr benötigt. Das Protokoll selbst läuft auf dem festen TCP-Port 2049, UDP wird nicht mehr unterstützt. Zwar liefen auch schon frühere Versionen auf diesem Port, die Hilfsprotokolle wurden vom RPC-Portmapper aber dynamisch zugeteilt. Die Verwendung von Firewalls bei NFS-Verbindungen wird durch diese Maßnahmen stark vereinfacht.
Mehrere Anfragen können gebündelt werden (combined request), sie werden dann vom Server ausgeführt und nur eine Antwort muss zurückgesendet werden. Das Protokoll kann damit effizient auch im Wide-Area-Bereich (WAN) eingesetzt werden, zum Beispiel zwischen verschiedenen Standorten einer Organisation.
Verschlüsselung ist jetzt Teil der Spezifikation. Zwar war früher schon über Secure-RPC eine Verschlüsselung möglich. Dies wurde nur selten genutzt, unter anderem, weil Secure-RPC nicht grundsätzlich zur Verfügung stand.
Der lookup-Aufruf wird durch open ersetzt, die Speicherung von Dateiinformationen wird dadurch möglich. Beispielsweise könnte die Schreib-/Leseposition auf dem Server verwaltet werden. Auch die gemeinsame Nutzung von Dateien wird besser unterstützt. Falls viele Clients eine Datei nur lesen, kann diese an alle Clients verliehen (leases) werden. Wenn ein Client eine Datei schreiben möchte, kann diese exklusiv verliehen werden.
Konfiguration in Unix-Systemen
Die NFS-Freigaben werden unter Unix serverseitig meist in der Datei /etc/exports festgelegt. Der Client kann eine Freigabe manuell mounten oder ggf. mit einem Eintrag in der Datei fstab automatisieren.
Vielen aktuellen Linux-Distributionen liegen grafische Hilfswerkzeuge bei, um die Einbindung von NFS-Freigaben ins System zu vereinfachen.
Sicherheit
NFS wurde geschaffen um in Unix-System-Netzen Dateisysteme über Rechnergrenzen hinweg zugänglich zu machen. Zur Zeit der Entwicklung von NFS waren solche Netze fast ausschließlich zentral verwaltet und die Rechner wurden zentral administriert, entsprechend wurde das Sicherheitskonzept gestaltet.
Die Entwickler von NFS bei Sun Microsystems hatten ursprünglich vorgesehen, die Sicherheit als Aufgabe der RPC-Schicht zu implementieren. Hierzu wird RPC durch Secure-RPC ersetzt. Die NFS-Protokolle selbst bleiben davon unberührt. Leider hat Secure-RPC keine weite Verbreitung gefunden, die Verwendung von Secure-RPC ist auch nicht bei allen Implementierungen möglich.
Ein NFS-Server ohne Secure-RPC exportiert Dateisysteme an bestimmte andere Rechner (von root durch IP-Adressen festgelegt), d. h. der root eines Clientrechners kann auf alle Dateien zugreifen, die der Server an den Client exportiert, unabhängig von deren Zugriffsrechten. Die Zugriffsrechte (der Benutzer) werden von NFS an den Client mitübertragen und vom Betriebssystem des jeweiligen Rechners ausgewertet und gegenüber den Benutzern durchgesetzt. Die Konsistenz der Benutzerdatenbank auf den beteiligten Rechnern wird dabei z. B. durch NIS erreicht.
Heutzutage sind Rechnernetze oftmals offen und nur bedingt zentral administriert, d. h. ein Angreifer kann relativ einfach entweder einen Rechner, dem der NFS-Server vertraut, übernehmen, indem er ihn z. B. mit einem Live-System neu bootet oder einen zusätzlichen Laptop in das Netz hängen und die IP eines gerade nicht laufenden NFS-Clients annehmen. In beiden Fällen kann der Angreifer, da er auf seinem System Rootrechte hat, auf alle an den Client exportierte Dateien, unabhängig von den Zugriffsrechten der Dateien, zugreifen. Somit ist NFS v3 immer nur so sicher, wie das Netz und die beteiligten Rechner.
NFS v4 löst dieses Problem indem z. B. mittels Kerberos eine Benutzeridentifizierung erfolgen kann.
Spezifikationen
- RFC 1094 (NFS Version 2 Protocol Specification)
- RFC 1813 (NFS Version 3 Protocol Specification)
- RFC 3530 (NFS Version 4 Protocol Specification)
NFS Server
Übersicht
Dieser Abschnitt basiert auf Recherchen von Bernd Reimann. Herzlichen Dank an ihn für die Zusammenarbeit!
Bevor wir uns dem Schwerpunkt der Administration eines NFS-Servers zuwenden, sollen kurze Betrachtungen zur Vergangenheit, Gegenwart und Zukunft der NFS-Entwicklung unter Linux etwas Hintergrundwissen vermitteln...
Historie
Bereits 1984, also lange bevor Linus Torvalds auch nur annähernd an Linux dachte und die Computerwelt noch von den Mainframes regiert wurde, widmete sich das Unternehmen SUN Microsystems der Aufgabe, ein System zu entwickeln, das den transparenten Zugriff auf die auf entfernten Rechnern liegenden Daten und Programme ermöglichen konnte.
Nahezu ein Jahr nach dieser Ankündigung (1985) stellte SUN NFS Version 2 (NFS V2) der Öffentlichkeit vor. Das Herausragende dieser Präsentation waren jedoch nicht die technischen Finessen, die das System mit sich bringen würde, sondern die Veröffentlichung der Spezifikation an sich. SUN durchbrach zum ersten Mal die Heiligkeit der Geheimhaltung solcher Interna und ebnete damit auch unwillkürlich den Siegeszug von NFS.
SUN stellte allen interessierten Firmen die Entwicklungsergebnisse als Lizenz zur Verfügung und ermöglichte somit einen de-facto-Standard in der UNIX-Welt, der sich bis heute durchgesetzt hat und immer noch eine der erfolgreichsten UNIX-Technologien darstellt. Nach und nach wurde NFS auf weitere Plattformen wie System V, BSD, AIX, HP-UX und später auch Linux portiert, wo NFS zur Standardausstattung einer jeden Distribution gehört. Selbst viele Nicht-Unix-Systeme, die es zu einer gewissen Verbreitung gebracht haben, warten mit einer NFS-kompatiblen Implementierung auf.
Protokollkollegen
1991 veröffentlichte SUNSoft, eine Tochtergesellschaft von SUN, erstmals eine komplette Sammlung zusammenwirkender Protokolle namens ONC (Open Network Computing), in der alle Bestandteile der Netzwerkkommunikation vom Zugriff auf die Netzwerkhardware bis hin zu Netzwerkanwendungen integriert wurden. Der NFS-Dienst ist Teil dieser ONC-Protokoll-Suite (Abbildung 1) und vertritt dort die Anwendungsebene, d.h. mit dem NFS-Dienst wird direkt gearbeitet. Protokollsuiten
Wie auch das OSI-Modell hat sich die ONC-Protokollsuite als Schema in der Praxis nicht durchgesetzt, auch wenn Protokolle wie XDR (External Data Representation) und der Remote Procedure Call (RPC) untrennbar mit dem NFS-Dienst einhergehen. XDR dient der Konvertierung der zu übermittelnden Daten in ein standardisiertes Format. Dies ist notwendig, da das NFS-Protokoll nicht auf ein System und eine Hardware-Plattform beschränkt ist und unterschiedliche Systeme und Hardware mitunter unterschiedliche Darstellungen der Daten praktizieren.
Hinter dem » Entferntem-Prozedur-Aufruf« (RPC) steckt die Idee, dass Programme auf Funktionen zurückgreifen, die nicht zwingend auf dem gleichen Rechner erbracht werden, wobei sich der Funktionsaufruf aus Sicht des Programms nicht von einem »normalen« lokalen Funktionsaufruf unterscheidet. Der interessierte Leser findet im Abschnitt Remote Procedure Call des Kapitels »Netzwerk-Grundlagen« eine umfassende Diskussion der Mechanismen und Probleme des RPCs.
Auf der Anwendungsebene tummelt sich nicht nur der NFS-Dienst selbst, sondern auch noch (verwandte) Protokolle wie das Mount-Protokoll, der Netzwerk-Lock-Manager (NLM) und der Netzwerk-Status-Monitor (NSM). Das Mount-Protokoll ist für den »Einhängevorgang« des Dateisystems zuständig, ein konkretes Beispiel des doch recht komplexen Vorgangs folgt zu einem späteren Zeitpunkt . NLM und NSM ermöglichen den exklusiven Zugriff auf Dateien über Rechnergrenzen hinweg. Beide Dienste sind für den Betrieb von NFS nicht zwingend erforderlich, ob Sie sie benötigen, erfahren Sie im Abschnitt Interna .
Kernel-NFS vs. Nutzeradressraum-NFS
Wer mit der Materie wenig vertraut ist, wird womöglich zum ersten Mal mit beiden Begriffen konfrontiert sein. Eigentlich erübrigt sich eine Diskussion über Vor- und Nachteile, hat sich doch der kernel-basierte Serverdienst gegenüber der alteingesessenen Implementierung als im Nutzeradressraum tätiger Serverprozess eindeutig durchgesetzt. Und dennoch verlangt eine umfassende Betrachtung einen tieferen Blick hinter die Kulissen.
Der so genannte User-Space NFS Server, wie er vor wenigen Jahren noch jeder Linux-Distribution beilag, zeichnet sich vor allem durch eine einfach zu realisierende Implementierung aus. Allein die Tatsache, dass ein Client dieselbe Sicht auf ein gemountetes Dateisystem hat, wie auch der Server, ermöglicht ein simples Mapping von lokalen Gruppen- und Benutzeridentifikationen (gid, uid) auf die vom importierten Dateisystem verwendeten Nummern. Dem User-Space-NFS-Server stand hierzu ein Rpc-Dienst (rpc.ugidd) zur Seite, der anhand einer Tabelle die Umsetzung der Benutzeridentifikationen vornahm. Nicht zuletzt aus Sicherheitsgründen unterstützt der neue Kernel-NFS-Server nur eine stark eingeschränkte Variante dieses Verfahrens (vergleiche Squashing ).
Wenn der kernel-basierte Server so aufwändig zu implementieren ist, warum hat man es nicht beim User-Space NFS Server belassen? Im Großen und Ganzen führen alle Überlegungen auf einen Grund zurück: Im Kernel arbeitet der Server entschieden schneller!. Der alte User-Space-NFS-Server kannte kein Threading (vereinfacht ausgedrückt, kann ein thread-basiertes Programm mehrere Aufgaben quasi gleichzeitig verrichten). Dieses Manko hätte eine Reimplementierung sicher noch behoben, aber auf Grund der strikten Schutzmechanismen im Betriebssystem bleiben dem Kernel-Server etliche Kopieroperationen erspart, da er bspw. die Berechtigung besitzt, Daten direkt in den Speicherbereich der Netzwerkkarte zu befördern. Ein Server im Nutzeradressraum müsste hierzu erst den Kernel bemühen, was allein schon einen Taskwechsel - und damit Zeit - bedingt. Weitere Unzulänglichkeiten sind die fehlende Unterstützung für NLM (Network Lock Manager) und NSM (Network Status Monitor) sowie die leidige Beschränkung der Dateigröße auf 2GB.
Die Vorteile des Kernel-Space NFS Servers liegen neben dem Geschwindigkeitsgewinn in dessen erweitertem Funktionsumfang. So beherrscht er mittels der NLM und NSM Protkolle das Setzen von Dateisperren auf exportierten Verzeichnissen. Und da die Überwachung der exports-Datei als Systemruf implementiert ist, müssen Server und Mountd nicht explizit über Änderungen unterrichtet werden. Die (theoretische) Beschränkung der Dateigröße liegt nun bei 263 Bits.
Leider besitzt auch die Kernelrealisierung noch eine Schwäche. So werden Dateisysteme, die sich unterhalb eines exportierten Verzeichnisses befinden, nicht automatisch exportiert (bis auf einen Fall; siehe später). Für diese wird ein extra Eintrag in der exports-Datei und damit clientseitig ein weiterer Mountvorgang notwendig.
So komplex obige Ausführungen auch anmuten mögen, aus Sicht des Administrators bestehen bez. der Einrichtung von NFS keinerlei Unterschiede zwischen User- und Kernel-Space NFS.
Ausblick
Im kurzen historischen Abriss war von NFS Version 2 die Rede. Version 3 ist seit Jahren existent und an Version 4 wird gestrickt. Die aktuellen NFS-Server (Kernelversionen ab 2.2.19) unterstützen alle Forderungen der Version 2 und bereits wesentliche Teile von Version 3. Die letzte »Hürde« (NFS via TCP) zur vollständigen Umsetzung von Version-3-Funktionalität ist als experimenteller Patch (ab Kernel 2.4.19) bereits genommen, die stabile Version ist somit nur noch eine Frage der Zeit. Auch Entwicklungen zur Umsetzung von NFS der 4. Version sind angelaufen.
Schritte zum Serverstart
Ports, Ports, Ports
Da eine Kommunikation zwischen zwei Rechnern über sogenannte Sockets läuft, also die IP-Adresse und die zugehörige Portnummer eines Dienstes, muss natürlich der Client, der seine Anfrage an den Server richtet, auch diese Portnummer kennen. Auf Grund der Fülle existenter RPC-Dienste werden Portnummern für diese nicht mehr strikt statisch vergeben, sondern über einen zusätzlichen Dienst - den Portmapper oder auch RPC-Bind (SUN) genannt - verwaltet. Der Portmapper selbst lauscht an einem festgelegten Port (111 sowohl über UDP als auch TCP ).
Dieser Portmapper ist in den meisten Distributionen standardmäßig installiert und wird oft durch ein Init-Skript in den Netzwerk-Runleveln beim Booten des Systems gestartet. Wird der Portmapper nur selten benötigt, spricht nichts gegen einen automatischen Start bei Bedarf durch den [x]inet-Daemonen .
Der Portmapper verwaltet eine Art kleine Datenbank, in der er verschiedene Informationen zu allen auf dem System aktiven RPC-Diensten hält. Ein RPC-Dienst muss sich deshalb beim Start beim Portmapper registrieren und ihm u.a. die von ihm verwendete Portnummer mitteilen. Bei Anfragen eines RPC-Clients an den Portmapper nach einem konkreten RPC-Dienst (PMAPPROC_GETPORT()), durchsucht dieser seine Datenbasis und übergibt, falls der Dienst verfügbar ist, dessen Portnummer. Alle Clientzugriffe erfolgen später direkt an diesen Port (also unter Umgehung des Portmappers; Abbildung 2). Kontaktaufnahme des Clients zum Server
Abbildung 2: Kontaktaufnahme des Clients zum Server
RPC-Dienste und Sicherheit
Der Zugang zu fast jedem RPC-Dienst unter Linux wird in aktuellen Programmversionen durch die Konfigurationen der Dateien /etc/hosts.allow und /etc/hosts.deny geregelt. Sie können leicht feststellen, ob die Dateien für ein Programm relevant sind:
user@sonne> strings /usr/sbin/rpc.mountd | grep hosts hosts_access_verbose hosts_allow_table hosts_deny_table /etc/hosts.allow /etc/hosts.deny @(#) hosts_ctl.c 1.4 94/12/28 17:42:27@(#) hosts_access.c 1.21 97/02/12 02:13:22
Insofern ein Dienst nicht in einer der Dateien »hosts.allow« bzw. »hosts.deny« aufgeführt ist, ist der Zugang zu diesem gewährt. In der Datei »hosts.allow« kann der Zugang explizit erlaubt und in »hosts.deny« verboten werden, wobei bei widersprüchlichen Einträgen in beiden Dateien die Angaben aus »hosts.allow« gelten.
In sicherheitskritischem Umfeld ist es nicht ungewöhnlich, zunächst pauschal sämtliche Dienste in »hosts.deny« zu sperren, um die wirklich benötigen in »hosts.allow« explizit für auserwählte Rechner zuzulassen. Bez. der auf einem NFS-Server notwendigen Dienste, wären folgende Einträge in die Dateien erforderlich, um den Zugriff für Rechner des lokalen Netzwerks (192.168.100.0) zuzulassen:
# Alles verbieten ALL : ALL root@sonne> vi /etc/hosts.allow # Alle für NFS notwendigen Dienste für die lokale Domain freigeben: portmap : 192.168.100.0/255.255.255.0 mountd : 192.168.100.0/255.255.255.0 lockd : 192.168.100.0/255.255.255.0 statd : 192.168.100.0/255.255.255.0rquotad : 192.168.100.0/255.255.255.0
Die Namen der einzelnen Dienste könnten auf Ihrem System von denen im Beispiel abweichen. Im Zweifelsfall sollten Sie nach der Registrierung der RPC-Dienste beim Portmapper die Namen der Ausgabe von »/usr/sbin/rpcinfo -p« entnehmen (mehr Informationen dazu im weiteren Text). »lockd« und »statd« sind einzig erforderlich, wenn Programme auf dem Client mit Dateisperren arbeiten (vergleiche Anmerkungen in der Einleitung); der RPC-Dienst »rquotad« ist notwendig, wenn auf den exportierten Verzeichnissen Quotas Verwendung finden.
Registrierung
Vergewissern Sie sich zunächst, dass der Portmapper auf Ihrem System aktiv ist. Dies kann entweder über die Statusabfrage des Runlevelskripts (falls ein solches existiert) erfolgen oder durch Suche in der Ausgabe des Kommandos ps :
root@sonne> /etc/init.d/portmap status Checking for RPC portmap daemon: running # Abfrage mittels ps user@sonne> ps ax | grep portmap 399 ? S 0:00 /sbin/portmap1578 pts/3 S 0:00 grep portmap
Ist der Portmapper inaktiv, dann starten Sie ihn entweder über das Runlevelskript oder per Hand:
root@sonne> /etc/init.d/portmap start Starting RPC portmap daemon done # Start per Handroot@sonne> /sbin/portmap
In den aktuellen Distributionen erledigt den Start des NFS-Servers und aller weiteren notwendigen Dienste ein Skript, bei SuSE ist dies bspw. »/etc/init.d/nfsserver«:
root@sonne> /etc/init.d/nfsserver startStarting kernel based NFS server done
Existiert kein solches Skipt, müssen Sie die Dienste per Hand aktivieren:
root@sonne> /sbin/rpc.lockd root@sonne> /usr/sbin/rpc.mountd root@sonne> /usr/sbin/rpc.nfsdroot@sonne> /usr/sbin/rpc.rquotad
Die Dienste »/sbin/rpc.statd« und »/sbin/rpc.lockd« bzw. »/sbin/rpc.rquotad« sind nicht zwingend notwendig (siehe Anmerkungen in der Einleitung und unter Interna ).
Vom erfolgreichen Registrieren der RPC-Dienste beim Portmapper können Sie sich durch einen Aufruf von »rpcinfo« überzeugen. In Verbindung mit der Option »-p« erfahren Sie, welche Dienste mit welchen internen Daten aktuell verwaltet werden:
Program Vers Proto Port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100021 1 udp 1024 nlockmgr 100021 3 udp 1024 nlockmgr 100024 1 udp 1025 status 100024 1 tcp 1024 status 100011 1 udp 969 rquotad 100011 2 udp 969 rquotad 100005 1 udp 1033 mountd 100005 1 tcp 1025 mountd 100005 2 udp 1033 mountd 100005 2 tcp 1025 mountd100003 2 udp 2049 nfs
Die Ausgaben könnten auf Ihrem System durchaus von obigem Beispiel abweichen, so sind abweichende Portnummern oder ähnliche Namen für die Dienste ebensowenig Besorgnis erregend, wie mehrfaches Auftauchen eines RPC-Dienstes in der Tabelle, da in vielen Konfigurationen aus Effizienzgründen gleich mehrere Instanzen eines Dienstes aktiviert werden.
Verzeichnisexport
Exportfs
Bevor ein Client ein Verzeichnis vom Server importieren kann, muss dieser dieses explizit mit den erforderlichen Rechten exportieren. Der Export eines Verzeichnisses erfolgt mit dem Kommando exportfs (das Kommando existiert nur in Zusammenhang mit dem Kernel-NFS):
/usr/sbin/exportfs [-av] -u [Client:/Pfad..]/usr/sbin/exportfs -r [-v]
Der Export von Verzeichnissen mittels »exportfs« ist zumeist nur in der Testphase des NFS-Servers oder bei einmaliger Freigabe eines Verzeichnisses erforderlich. »exportfs« wird hauptsächlich genutzt, um nach Änderungen in der Datei »/etc/exports« den Server (genauer: rpc.nfsd und rpc.mountd) zu instruieren, seine Konfiguration neu einzulesen. Bei den Mountoptionen des Kommandos handelt es sich um eben diese, die anschließend in Zusammenhang mit der Datei »/etc/exports« vorgestellt werden; an dieser Stelle verzichten wir auf ihre Diskussion und veranlassen in einem ersten Beispiel den NFS-Server, das Verzeichnis »/home/user« für den Rechner »venus« freizugeben:
Prinzipiell können Sie für die Rechnernamen dieselbe Syntax wie in »/etc/exports« verwenden; vergessen Sie jedoch nicht, enthaltene Sonderzeichen vor Interpretation durch die Shell zu schützen. Wird - wie im Beispiel - auf Mountoptionen verzichtet, gelten async, ro, root_squash, secure (Erklärung im Anschluss).
Um das Verzeichnis vom Export wieder auszuschließen, ist die Option »-u« dienlich:
Die Option »-a« exportiert alle (auf der Kommandozeile und in /etc/exports angegebenen) Verzeichnisse; in Zusammenhang mit »-u« werden sämtliche exportierten Verzeichnisse vom Export ausgeschlossen. Um in solchen Fällen die Auswertung der Datei »/etc/exports« zu verhindern, dient »-i«. Schließlich synchronisiert die Option »-r« die aktuelle Datenbasis des NFS-Servers (/var/lib/nfs/xtab) mit den Einträgen der Datei »/etc/exports«.
Nach Änderungen in der Datei »/etc/exports« führt folgender exportfs-Aufruf zu einer Aktualisierung beim Server:
root@sonne> exportfs -ra
Anmerkung: Beim älteren User-Space-NFS-Server gelingt der Export von Verzeichnissen einzig über Einträge in der Datei »/etc/exports«. Anschließend muss dem Serverprozess das Signal SIGHUP gesendet werden (kill -HUP <Prozess-ID des Servers>).
Die Datei /etc/exports
Anstatt Dateisysteme einzeln via »exportfs« zu exportieren, wird die Konfiguration mittels der Datei »/etc/exports« bevorzugt (...und in Verbindung mit dem User-Space-NFS-Server ist dies die einzige Möglichkeit der Konfiguration).
Der Aufbau eines Eintrags in die Datei ist einfach:
Verzeichnis bezeichnet das zu exportierende Verzeichnis. Es folgt eine Liste der Client-Rechner, die zum Importieren dieses Verzeichnisses befugt sind. Optional kann der Zugriff auf die Daten für einen Client gegenüber der Voreinstellung (async, ro, root_squash, secure) weiter eingeschränkt oder auch gelockert werden.
Die Syntax für Client ist etwas weiter gefasst. Hier sind nicht nur die Angabe starrer Rechnernamen gestattet, sondern ebenso die Bezeichnung von Netzgruppen (die in der Datei /etc/netgroup definiert sein müssen) oder die Verwendung von Wildcards zur Definition von Mustern. Damit ergeben sich folgende Varianten zur Angabe:
erde.galaxis.de Angabe eines konkreten Rechners (oder auch IP-Adresse)
@Gateways Bezug auf eine Netzgruppe, die der Datei [Linuxfibel - Netzwerk Server - NFS Server#Die Datei /etc/netgroup|/etc/netgroup]] definiert sein muss
*.galaxis.de Angabe von Mustern; hier: alle Rechner aus der Domäne »galaxis.de«
192.168.100.0/255.255.255.0
192.168.100.0/22 Angabe von IP-Netwerken inklusive Subnetzmaske , welche für den Fall, dass allein führende Bits zur Maskenbildung herangezogen werden, auch als Anzahl der Bits (22 im Beispiel) spezifiziert werden kann
Jeder Angabe eines Clients kann eine Liste vom Optionen folgen, die den Zugriff auf die exportierten Daten steuern. Innerhalb der kommaseparierten Liste sind keine Leerzeichen statthaft! Mögliche Werte sind:
secure, insecure Client-Anfragen werden nur von vertrauenswürdigen Ports (Portnummern unterhalb 1024) akzeptiert (»secure«, Voreinstellung); mit »insecure« werden auf Anfragen an höhere Ports akzeptiert
ro, rw Das Verzeichnis wird schreibgeschützt (»read only«, Voreinstellung) bzw. mit vollen Lese- und Schreibrechten für den Client (»read/write«) exportiert
sync, async Der Server darf den Vollzug eines Schreibvorgang dem Client erst melden, wenn die Daten tatsächlich auf die Platte geschrieben wurden (Ausschalten des Plattencaches). Die Voreinstellung ist async.
wdelay, no_wdelay Die Option wird nur in Zusammenhang mit »sync« beachtet und erlaubt dem Server die Bestätigung eines Schreibvorgangs zu verzögern, falls mehrere Schreibvorgänge von einem Client zur gleichen Zeit im Gange sind. Anstatt jeden zu bestätigen, sendet der Server nur eine einzige Antwort nach Vollzug aller Schreiboperationen (betrifft »wdelay«, Voreinstellung).
hide, nohide Exportiert der Server ein Verzeichnis, in dem wiederum ein anderes Dateisystem gemeountet ist, so wird dieses nicht an einen Client exportiert (»hide«, Voreinstellung). Dies bedeutet allerdings, dass die Dateisysteme weiterhin alle einzelnd auf der Server-Seite exportiert werden müssen jedoch nicht alle expliziet auf der Client gemountet werden müssen. Die »nohide«-Option (also den impliziten Export) funktioniert jedoch nur, wenn es sich bei der Clientangabe um einen Rechnernamen (keine Wildcards, IP-Netzwerke und Netzgruppen!) handelt.
subtree_check, no_subtree_check Werden nur Teile eines Dateisystems vom Server exportiert, so muss der Server prüfen, dass Zugriffe nur auf Dateien erfolgen, die innerhalb dieses Teilbaums liegen (»subtree_check«, Voreinstellung). Dies erhöht zwar die Sicherheit allerdings auf Kosten der Geschwindigkeit, sodass die Prüfung mit »no_subtree_check« abgeschalten werden kann.
root_squash, no_root_squash Root erhält die UserID des Pseudobenutzers »nobody«, womit der Root-Benutzer des Client-Rechners keine Root-Rechte auf dem vom Server importierten Verzeichnis erhält (Voreinstellung); mit »no_root_squash« bleiben die Root-Rechte auf Clientseite auf dem Verzeichnis erhalten.
all_squash, no_all_squash Alle Zugreifenden erhalten die Nobody-UID; Voreinstellung ist »no_all_squash«, womit die Nutzerkennungen erhalten bleiben
anongid=gid Squashing der Gruppe; die Gruppen-ID wird auf »gid« gesetzt. Bei dieser Option kann Root entscheiden, mit welcher Server-GID die Client-Benutzer arbeiten sollen, sobald sie Zugriff auf den Server haben
anonuid=uid Squashing des Benutzers. Die zugreifenden Benutzer bekommen die UID »uid« verpasst
Die Optionen zum Verändern der Nutzerkennungen werden als »Squashing« bezeichnet und werden im folgenden Abschnitt detailliert diskutiert.
Die Datei /etc/exports - Ein Beispiel
Als reales Szenario nehmen wir an, dass unser NFS-Server (»sonne.galaxis.de«) als Datei- und als NIS-Server konfiguriert wurde. Die zentrale Aufgabe eines NIS-Servers ist immer noch die Bereitstellung einer zentralen Benutzerverwaltung, in Kombination mit einen NFS-Server werden meist auch die Heimatverzeichnisse der Benutzer zentral gehalten, sodass ein Benutzer sich an einen beliebigen Rechner eines Pools anmelden kann und überall seine gewohnte Umgebung vorfinden wird.
Des Weiteren gehen wir davon aus, dass die Clients nur über eine beschränkte Plattenkapazität verfügen, sodass sie etliche Daten, die nicht der Grundfunktionalität dienen, ebenso via NFS importieren (wir gehen jetzt nicht soweit, festplattenlose Clients in die Betrachtung einzubeziehen, die sogar ihr Root-Dateisystem und den Swap via NFS beziehen).
In der nachfolgenden Beispieldatei finden Sie weitere Anmerkungen in Form von Kommentaren, warum welche Option für welches Verzeichnis gesetzt wurde; die Überlegungen sollten auf etliche Rahmenbedingungen übertragbar sein.
# Wir nehmen an, dass /home auf einer eigenen Partition liegt, sodass sich die Prüfung, ob eine Datei innerhalb des exportierten Verzeichnisses liegt, erübrigt. Dass Benutzer innerhalb ihrer Heimatverzeichnisse auch Schreibrechte erhalten sollten, ist verständlich. Da unsere Netzwerk als sichere Zone anzusehen ist, verzichten wir auf die Einschränkung der zulässigen Portnummern: /home *.galaxis.de(rw,no_subtree_check,insecure) # Wie der Name schon sagt, sind Daten unter /usr/share geeignet, um an zentraler Stelle für verschiedene Clients bereit gestellt zu werden. Kein Client muss diese Daten veränern können, deshalb setzen wir gleich die Benutzerkennungen auf den sehr restriktiven Zugang »nobody«/usr/share *.galaxis.de(ro,all_squash)
Abschließend sei darauf hingeweisen, dass auf Clientseite beim Import eines Verzeichnisses die Rechte weiter eingeschränkt werden können. Die Informationen dazu finden Sie im Abschnitt zum NFS-Client .
Squashing
Gerade wurde bei den Optionen und Parametern der Begriff »Squashing« eingeführt, doch was bedeutet er?
Lassen Sie es mich an einem Beispiel erklären: Auf dem System »sonne« (NFS-Server) existieren in einem exportierten Verzeichnis folgende Dateien:
user@sonne> ls -l
-rw-r----- 1 root root 166 Apr 27 10:45 foo.bar -rw------- 1 tux users 16 Apr 27 10:45 testdaten.txt
Des weiteren existieren Benutzer mit folgender UID: root 0 tux 501
Auf System »venus« (unser NFS-Client) existieren Benutzer mit folgenden UIDs: root 0 alf 501 tux 502
Was passiert nun, wenn wir auf dem Client eine Serverfreigabe mounten?
Dazu muss man wissen, dass Unix die Zugriffsrechte nicht aufgrund der Benutzernamen verwaltet, sondern einzig anhand der zugrundeliegenden UIDs. In unserem Falle hat der Benutzer »alf« (auf dem Client) plötzlich Zugriff auf die Datei »testdaten.txt« von Benutzer «tux«, da beide dieselbe UID 501 besitzen. Gleiches gilt natürlich ebenso für den Benutzer »root«.
Um dies zu verhindern, gibt es das »Squashing«. Hierbei werden die UIDs und GIDs der auf die gemounteten Verzeichnisse zugreifenden Benutzer auf eine neutrale UID (der Pseudouser nobody mit UID -2) und GID (nogroup mit GID -2) gesetzt, wenn dieses mit der Option »all_squash« exportiert wurde. Die UID 0 (GID 0; also Root) wird in der Voreinstellung stets nach »nobody/nogroup« gemappt; erst die Option »no_root_squash» verhindert die Umsetzung.
Der alte User-Space-NFS-Server erlaubte das »Squashen« jeder UID auf jede beliege andere und ebenso konnte jede Gruppenkennung (GID) auf jede andere gemappt werden. Der neuer Kernel-NFS-Server arbeitet wesentlich restriktiver und gestattet einzig, anstatt dem Pseudobenutzer »nobody« bzw. der Pseudogruppe »nogroup« mittels »anonuid=<UID>« bzw. »anonguid=<GID>« andere Kennungen zu vergeben. Diese gelten dann jedoch für beliebige Gruppen oder Benutzer.
Bez. unserer oben angegebenen Benutzerstrukturen würde bei Export des Verzeichnisses mittels der Option »all_squash« der Client-Benutzer »alf« nur noch ein »Nobody« sein und hätte somit nur Lesezugriff auf die Datei »testdaten.txt«
Etwas Statistik
Nicht zuletzt beim Aufspüren von Fehlkonfigurationen sind zwei Kommandos zur Diagnose des NFS-Servers nützlich. Zum einen erlaubt showmount einen Einblick sowohl auf die vom Server bereitgestellten Dateisysteme als auch auf die momentan aktiven Clients. Zum zweiten erlaubt nfsstat die Auswertung zahlreicher statistische Daten des Kernel-NFS-Servers.
showmount
/usr/sbin/showmount [ -adehv ] [ NFS-Server]
Ohne Argumente aufgerufen, listet das Kommando die Namen der NFS-Clients auf, die aktuell Verzeichnisse vom Server importiert haben; bei Verwendung der Option »-a« werden zusätzlich die Verzeichnisnamen aufgeführt:
All mount points on sonne: venus.galaxis.de:/home/ venus.galaxis.de:/usr/share/erde.galaxis.de:/home/
Um einzig die aktuell von Clients importierten Verzeichnisnamen anzuzeigen, nicht aber die Namen der Clientrechner selbst, dient die Option »-d«. »-h« schreibt eine Kurzhilfe aus; »-v« die Versionsnummer des Programms.
Vor allem für Clientrechner interessant ist die Option »-e«, mit der sie, wenn Sie auf der Kommandozeile noch den Namen eines NFS-Servers angeben, testen können, welche Verzeichnisse ein Server für welchen Client exportiert:
Export list for sonne.galaxis.de: /home *.galaxis.de/usr/share *.galaxis.de
nfsstat
Der Zugang zu den Statistiken im Kernel trägt eher informativen Charakter und verdeutlichen, welche Anforderungen die Clients tatsächlich stellen. Die Unterscheidung nach NFS Version 2 und 3 zeigt, in welchem Verhältnis die Clients nach dem alten bzw. nach dem neuen Protokoll arbeiten; im nachfolgend dargestellten Beispiel habe ich der besseren Übersicht wegen die Tabelle für die Versionen 2 entfernt.
Die Optionen des Kommandos helfen, die Ausgaben auf einen konkreten Typ zu beschränken. So begnügt sich »nfsstat -s« auf die Ausschrift der Statsitik der Serverseite, während »nfsstat -c« nur die Client-Daten offenbahrt.
»nfsstat -r« beschränkt sich auf Angabe der RPC-relevanten Daten; »nfsstat -n« tut dasselbe für die NFS-spezifischen Informationen.
Server rpc stats: calls badcalls badauth badclnt xdrcall 20860 0 0 0 0 Server nfs v3: null getattr setattr lookup access readlink 0 0% 264 1% 0 0% 1148 5% 14726 70% 32 0% read write create mkdir symlink mknod 4485 21% 0 0% 0 0% 0 0% 0 0% 0 0% remove rmdir rename link readdir readdirplus 0 0% 0 0% 0 0% 0 0% 188 0% 14 0% fsstat fsinfo pathconf commit 1 0% 2 0% 0 0% 0 0% Client rpc stats: calls retrans authrefrsh 775 0 0 Client nfs v3: null getattr setattr lookup access readlink 0 0% 263 33% 0 0% 0 0% 494 63% 2 0% read write create mkdir symlink mknod 1 0% 0 0% 0 0% 0 0% 0 0% 0 0% remove rmdir rename link readdir readdirplus 0 0% 0 0% 0 0% 0 0% 0 0% 14 1% fsstat fsinfo pathconf commit0 0% 1 0% 0 0% 0 0%
Unter Kategorie können nochmals die Statistiken speziell für RPC (»nfsstat -o rpc«) und NFS (»nfsstat -o nfs«) abgerufen werden. Zusätzlich sind Informationen über Auslastung des Transportprotokolls (»nfsstat -o net«), des Dateihandle-Caches (»nfsstat -o fh«) und des Antwortcaches (»nfsstat -o rc«) abrufbar.
Server packet stats: packets udp tcp tcpconn 0 20860 0 0 Client packet stats: packets udp tcp tcpconn0 0 0 0
Der Mountvorgang intern
Die Abläufe eines vom NFS-Clients initiierten Dateiimports sind recht komplex. Die Verwendung des hierzu notwendigen Kommando mount finden Sie im Abschnitt zum NFS-Client . Hier schauen wir hinter die Kulissen, also auf das Zusammenspiel der einzelnen Komponenten bis letztlich das Dateihandle, eine vom Server vergebene eindeutige Kennziffer für das Verzeichnis, zum Client gelangt.
Ausgangspunkt sei folgender erstmaliger Mount-Aufruf:
Anmerkung: Bei entsprechender Konfiguration kann ein Mountvorgang auch einem »normalen« Benutzer gestattet werden oder gar per Automounter automatisch bei Bedarf erfolgen.
Zum Zeitpunkt der ersten Kontaktaufnahme zum NFS-Server fehlt dem Client die Kenntnis der korrekten Portnummer, an dem dieser wartet. Deshalb geht die erste Anfrage an den Portmapper des Servers, an welchem Port der Mount-Daemon wartet. Mittels einer weiteren Anfrage beim Portmapper sollte der Client auch noch die Portnummer des NFS-Daemons in Erfahrung bringen (falls notwendig, erfragt der Client auch noch die Portnummern der RPC-Dienste NSM und NLM). Die Prinzipien des Verfahrens sollten Ihnen aus dem Abschnitt Schritte zum Serverstart bekannt sein. Einmal erfragte Portnummern werden solange lokal vorgehalten, bis ein Zugriff auf einen solchen Port einen Fehler meldet (oder der Client neu bootet;-).
Mit der Erkenntnis, an welchem Port der Mount-Daemon des Servers wartet, wendet sich der Client nun direkt an diesen. Der Mount-Daemon durchsucht nun die Datei »/var/lib/nfs/etab«, ob das erwünschte Verzeichnis zum Export freigegen ist und ob der Client zum Import berechtigt ist.
/usr/share *.galaxis.de(ro, async, wdelay, hide, secure, root_squash, all_squash,subtree_check, secure_locks, mapping=identity, anonuid=-2, anongid=-2)/home/ *galaxis.de(rw, async, wdelay, hide, secure, root_squash, no_all_squash, no_subtree_check, secure_locks, mapping=identity, anonuid=-2, anongid=-2)
Verlaufen die Überprüfungen erfolgreich, so wendet sich der Mount-Daemon an den NFS-Daemon (Funktion GETFH()), der ein eindeutiges Dateihandle, das das exportierte Verzeichnis referentiert, erzeugt. Dieses Handle ist ein Datenobjekt und enthält eine eindeutige Zufallszahl, die die Identifikation der Datei (ein Verzeichnis ist unter Unix letztlich auch nur eine Datei) gewährleisten soll und nur einmalig vergeben wird. Dieses Dateihandle übergibt der NFS-Daemon dem Mount-Daemon, der es zum Client sendet (Abbildung 3). Ablauf eines NFS-Mounts
Abbildung 3: Ablauf eines NFS-Mounts
Alle weiteren Zugriffe auf Dateien des importierten Verzeichnisses erfolgen durch direkten Kontakt zwischen NFS-Client und dem NFS-Daemon-Prozess. Der Client gibt jeweils das Dateihandle an, womit der Server das Verzeichnis kennt, von dem aus er nach angeforderten Dateien suchen muss. Was in der Abbildung nicht dargestellt wurde, ist die eventuell notwendige Interaktion zwischen Lock-Manager und Status-Monitor, falls beim Zugriff auf Dateien mit Sperren gearbeitet werden soll.
Interna
Rein informellen Charakter tragen die weiteren Ausführungen, die Apsekte ansprechen, die für die Administration von NFS selbst unerheblich sind.
Cachefs
Oftmals ist es wünschenswert, wenn es eine Art Zwischenspeicher für die Netzzugriffe gibt, um die Netzbelastung so gering wie möglich zu halten. Hierfür gibt es von SUN (mal wieder!) ein Dateisystem namens Cachefs, das genau dieses »Caching« übernimmt. Leider existiert noch keine Implementierung dieses Dateisystems für Linux, jedoch wird es unter anderen Unixen häufig verwendet. Bei Cachefs wird ein Puffer-Verzeichnis angelegt, das nach und nach mit den vom Server angeforderten Daten gefüllt wird. Bei jedem Datenzugriff wird nun zunächst geprüft, ob diese eventuell bereits im lokalen Puffer enthalten sind. Falls ja, muss die Datei nicht erst erneut übers Netz vom Server geladen werden, was einen mitunter erheblichen Geschwindigkeitsvorteil mit sich bringt, da lokale Bus- und Dateisysteme immer schneller sind als Netzleitungen (oder haben sie ein Gigabit-Ethernet zu Hause?).
CacheFS unter Linux = FS-Cache siehe : http://gentoo-wiki.com/HOWTO_FS-Cache http://en.wikipedia.org/wiki/CacheFS
Quota
Quotas dienen der Beschränkung des einem Benutzer zur Verfügung stehendem Plattenspeicherplatzes. Die Quotas selbst werden nur auf dem Server eingerichtet und ihre Einhaltung überwacht. Um Benutzern auf den Clients eine Abfrage ihres Quotastatus zu ermöglichen, ist auf dem NFS-Server der RPC-Dienst rpc.rquotad zu starten.
Network State Monitor (NSM) und Network Lock Manager (NLM)
Um gleichzeitige Zugriffe auf einunddieselben Dateien koordinieren zu können, behilft sich NFS eines Network-Lock-Managers (rpc.lockd) und eines Network-State-Monitors (rpc.statd). Das allein garantiert noch keine Dateisperren, denn diese müssen die auf NFS-importierte Dateien zugreifenden Programme auf Clientseite implementieren. Und dies tun bis heute die wenigsten Programme unter Linux. Daher ist es in den meisten Linuxnetzwerken gar nicht erforderlich, rpc.statd und rpc.lockd zu aktivieren.
Prinzipiell fordert ein entsprechend realisiertes Programm vom Kernel eine Dateisperre an. Der Kernel erkennt, dass die Datei auf einem via NFS gemountetem Dateisystem liegt und leitet die Anforderung an den lokalenLock-Manager weiter. Dieser sendet die Anforderung an den Lock-Daemon auf dem Server, welcher den Vorgang akzeptiert oder ablehnt. Das Ergebnis schickt er zum Lock-Daemon des Clients zurück, der es dem Kernel reicht.
Angenommen, während einer aktiven Dateisperre startet entweder der Client oder der Server neu, was passiert mit den Sperren? Jetzt kommt der Status-Monitor ins Spiel. Wenn auf Serverseite der Lock-Manager für einen Client eine Dateisperre anlegt, so unterrichtet er den Status-Monitor, welcher den Namen des Client-Rechners unter /var/lib/nfs/sm ablegt. Auf Clientseite erfährt der Status-Monitor die akzeptierte Sperre ebenso vom lokalen Lock-Manager, nur speichert er den Namen des Servers, von dem die Sperre gesetzt wurde.
Bootet nun ein Client neu, prüft der lokale rpc.statd sofort, ob irgendein Server zu unterrichten ist. Falls ja, kontaktiert er dessen Status-Monitor, der den Lock-Manager auf Serverseite unterrichtet, welcher wiederum alle Dateisperren des Clients aufhebt.
Fällt allerdings der Server aus, so unterrichtet nach einem Neustart dessen Status-Monitor die Kollegen auf allen Clients, die aktuelle Dateisperren besaßen. Die Lock-Manager auf den Clients versuchen nun zunächst die Dateisperren vom Server erneut anzufordern. Der Lock-Manager auf dem Server wird die durch den Neustart ungültigen Sperren noch »eine Zeit lang« reservieren und einzig dem »alten« Besitzer (also Client) gestatten, die Sperre unverzüglich anzufordern. So wird dem Client eine Chance erteilt, die verlorenen Sperren zu erneuern.
Unterschiede NFSV2 und NFSV3
Obwohl NFS V2 schon mehrere Jahre nach seiner Fertigstellung einen neuen großen Bruder erhielt (NFS V3), ist es trotzdem immer noch ein Standard und wird bei Linux weitestgehend eingesetzt. Langsam aber sicher findet der Umstieg auf NFS V3 statt, der aus Kompatibiltätsgründen fast alle alten Prozeduren übernimmt und neue Eigenschaften einbringt. So kann bei Version 3 nun zwischen den beiden Protokollen UDP und TCP ausgewählt werden, was bei Einsatz von TCP eine Entlastung des Dienstes bedeutet, da TCP nun die Fehlersicherung übernimmt und somit eine sichere Leitung gewährleistet - jedoch zum Preis einer erhöhten Netzbelastung (an der TCP-Unterstützung durch den Kernel-NFS-Daemon wird derzeit gearbeitet; vergleiche »Ausblick« in der Einleitung).
Die Größenlimits werden den heutigen Verhältnissen angemessener gestaltet bzw. ganz aufgehoben. Es wird ein asynchroner, zusätzlicher Schreib- und Lesemodus eingeführt, der die Geschwindigkeit deutlich erhöhen wird. Asynchrones Schreiben in NFS-3
Abbildung 7: Asynchrones Schreiben in NFS-3
Dabei wird nicht mehr wie beim synchronen Zugriff ein Arbeitsvorgang komplett abgeschlossen, sondern die gecachten Daten werden beim Server zwischengespeichert und »bei geeigneter Gelegenheit« auch gesammelt festgeschrieben. Erst auf die endgültige Bestätigung hin verwirft der Client seine Daten im Cache.
Auch bei den Lesezugriffen wurden neue Prozeduren eingeführt. So wurden beim Objektaufruf (bspw. ls -al) zuerst alle Daten übertragen (READDIR()) und danach jeweils die Attribute (GETATTR()) der Objekte. Dies wird in Version 3 durch eine vollständig neue Prozedur (READDIRPLUS()) ersetzt, die alles in einem Aufwasch erledigt und die erhoffte Steigerung der Geschwindigkeit nach sich zieht.
NFS nach Version 3 arbeitet anstatt mit 32 Bit mit 64 Bit langen Dateizeigern, sodass auch hier die insbesondere für Datenbankanwendungen schmerzlichen Schranken der Datei- und Dateisystemgrößenbeschränkung fallen.
Mittlerweile wird eine vierte Version (NFSV4) erstellt. Die Tests sind weitestgehend abgeschlossen und nun wird an einer Verabschiedung, die voraussichtlich 2002 erfolgen wird, gearbeitet.
NFS Clients
Das Network Filesystem ist die gebräuchlichste Methode unter Unix, um Verzeichnisse über Rechnergrenzen hinweg verfügbar zu machen. Einen kurzen Abriss zur Historie und Intention des NFS erhalten Sie im Abschnitt zum NFS-Server .
Voraussetzungen
Kernelunterstützung
Die Unterstützung des NFS-Dateisystems ist Aufgabe des Kernels. Vermutlich integriert der aktuelle Kernel bereits die erforderliche Eigenschaft; ein Blick in die Datei »/proc/filesystems« schafft Gewissheit:
nodev sockfs nodev tmpfs nodev pipefs nodev proc ext2 nodev devpts reiserfsnodev supermount
Im Beispiel fehlt offensichtlich ein entsprechender Eintrag für das NFS-Dateisystem. Bei aktuellen Kerneln, die heutigen Distributionen beiliegen, muss das noch nichts bedeuten... Eventuell ist die Unterstützung im Kernel nur als Modul kompiliert, und solange das Modul noch nicht geladen wurde, wird der Kernel das Dateisystem auch nicht kennen. Das Modul sollte nun von Hand geladen werden:
Eine Ausschrift der Art » modprobe: Can't locate module nfs « resultiert entweder aus einer falschen Konfiguration der Modulabhängigkeiten (unwahrscheinlich) oder aber aus einer fehlenden Unterstützung durch den Kernel. Die Generierung eines neuen Kernels wird notwendig sein...
Bei erfolgreichem »modprobe«-Aufruf erscheint folgende Zeile am Ende der Datei »/proc/filesystems«:
nodev supermountnodev nfs
Portmapper
Für die Grundfunktionalität eines NFS-Clients ist die Aktivierung des Portmappers nicht notwendig. Erst wenn Programme mit Dateisperren auf importierten NFS-Verzeichnissen arbeiten, werden auf Clientseite zwei RPC-Dienste (»rpc.lockd« und »rpc.statd«) und damit der Portmapper erforderlich.
Das Vorgehen zum Start des Portmappers und der beiden Dienste erfolgt analog zur Beschreibung im NFS-Server-Abschnitt . Beachten Sie auch die dortigen Hinweise zu ggf. erforderlichen Sicherheitseinstellungen in den Dateien »/etc/host.allow« und »/etc/hosts.deny«. Ebenfalls in der Abhandlung zum Server finden Sie eine Diskussion zur Arbeitsweise von Network-Lock-Manager (»rpc.lockd«) und Network-Status-Monitor (»rpc.statd«).
Bei aktuelleren RedHat- und SuSE-Distributionen finden Sie oft ein Skript /etc/init.d/nfs, über das Sie komfortabel den Client starten und beenden können (genau genommen startet das Skript auch nur die beiden RPC-Dienste und mountet alle in der Datei /etc/fstab erwähnten NFS-Dateisysteme).
Mounten eines NFS-Dateisystems
Welcher Server bietet was?
Für gewöhnlich wird der Administrator eines NFS-Servers die Verzeichnisse nur für konkrete Rechner exportieren und den Verantwortlichen dieser Clients alle notwendigen Informationen zum Zugriff zukommen lassen. Dennoch kann von einem Client leicht verifziert werden, ob ein Rechner als NFS-Server fungiert und welche Verzeichnisse er welchen Rechnern zur Verfügung stellt.
Das Kommando »showmount« dient zur Abfrage eines Servers. Werden, abgesehen vom Servernamen, keine weiteren Optionen angegeben, so werden die aktuell zum Server verbundenen Clients aufgelistet:
All mount points on sonne.galaxis.de: erde.galaxis.devenus.galaxis.de
Aus Sicht eines NFS-Clients ist die Option »-e« nützlich, die dem Server Auskunft über die exportierten Verzeichnisse entlockt:
Export list for sonne.galaxis.de: /home *.galaxis.de/usr/share *.galaxis.de
Eine umfassende Beschreibung von »showmount« finden Sie im Abschnitt zum NFS-Server.
Das Mount-Kommando
Auch zum Mounten von NFS-Verzeichnissen dient das Kommando mount . Es gelten dieselben Voraussetzungen wie zum Einhängen lokaler Dateisysteme: Die notwendigen Rechte müssen gegeben sein (auch auf Serverseite) und der Mountpunkt - also das Zielverzeichnis - muss existieren .
Der Aufruf von mount folgt nun diesem Schema:
Anstatt des Servernamens ist auch die Angabe einer IP-Adresse zulässig. Neben den allgemein gültigen Optionen für das Mountkommando steuern NFS-spezifische Optionen vor allem das Verhalten des Kommandos im Fehlerfall. Wir widmen uns ihnen im folgenden Abschnitt.
Als konkretes Beispiel soll vom NFS-Server »sonne.galaxis.de« das dort freigegebene Verzeichnis »/home« importiert werden. Als Mountpunkt wurde lokal ein Verzeichnis »/mnt/home« erzeugt. Der Aufruf sieht wie folgt aus:
Etwas Komfort
Da Administratoren - allen voran »Unix-ler« - bekanntlich recht bequeme Menschen sind und nach Automatisierung streben, gibt es auch hier einen Weg, um den Mount-Aufruf zu vereinfachen. Die kürzere und elegantere Schreibweise wäre ein Eintrag in die Datei /etc/fstab , die statische Informationen über Dateisysteme, ihre Mountpunkte und Optionen enthält.
Eine typische fstab-Datei könnte wie folgt aussehen:
/dev/hda3 / ext3 defaults 1 2 /dev/hda1 /boot ext3 defaults 1 2 /dev/cdrom /media/cdrom auto ro,noauto,user,exec 0 0 /dev/fd0 /media/floppy auto noauto,user,sync 0 0 devpts /dev/pts devpts defaults 0 0 proc /proc proc defaults 0 0 usbdevfs /proc/bus/usb usbdevfs noauto 0 0 /dev/hda2 swap swap pri=42 0 0 # NFS-Einträge sonne:/home /home nfs bg,soft,intr,retry=5 0 0sonne:/usr/share /usr/share nfs defaults 0 0
Zur Bedeutung der einzelnen Felder finden Sie Erläuterungen im Abschnitt Dateisysteme, /etc/fstab des Kapitels »Systemadministration«. Wichtig für unser Beispiel sind die beiden letzten Einträge. Anstelle der Gerätedatei bei lokalen Dateinamen tritt nun das zu importierende Verzeichnis in der Form »Server:/Pfad«. Als Typ des Dateisystems muss »nfs« in die dritte Spalte eingetragen werden. Die beiden letzten Spalten sollten bei importierten Verzeichnissen stets »0« sein, da sowohl ein Backup als auch eine Überprüfung des Dateisystems Aufgabe des Servers (der Rechner, auf dem diese Dateisysteme lokal liegen) ist.
Und der Zweck solcher Einträge?
Zum einen genügt nun ein einziger Aufruf, um alle in der Datei benannten NFS-Verzeichnisse gleichzeitig zu importieren:
Zum anderen sinkt selbst bei Import einzelner Einträge der Tippaufwand, da als Argument für das Kommando »mount« entweder die Angabe der Server-Pfad-Kombination oder auch nur die Angabe des lokalen Mountpunkts genügt. Mit jedem der beiden folgenden Aufrufe könnte das Verzeichnis »/home« vom Server »sonne« gemountet werden:
root@erde> mount sonne:/home # Angabe des lokalen Mountpunktsroot@erde> mount /home
Mount-Optionen
Durch gezielten Einsatz einiger Optionen des mount -Kommandos lassen sich die Zugriffe auf Daten eines NFS-Verzeichnisses mitunter erheblich beschleunigen. Auch kann das Verhalten im Fehlerfall über Argumente gesteuert werden. Selbstverständlich lassen sich solche Angaben auch in der /etc/fstab dauerhaft nieder schreiben.
Die das NFS betreffenden Optionen sind:
rw, ro | Schreib- und Lesezugriff bzw. Nur-Lese-Zugriff. Beachten Sie, dass die Rechte höchstens weiter eingeschränkt werden können, d.h. ein vom Server nur-lesend-exportiertes Verzeichnis kann lokal nicht zum Schreiben freigegeben werden, umgekehrt kann die Schreibberechtigung lokal verboten werden, selbst wenn der Server diese zuließe |
fg | Jeder gescheiterte Mountvorgang wird eine Fehlermeldung erzeugen; der Vorgang läuft im Vordergrund (»foreground«). |
bg | Scheitert der Mountvorgang im ersten Versuch, wird er im Hintergrund (»background«) solange wiederholt, bis er erfolgreich war oder »retry« erreicht wurde. |
retrans=zahl | Anzahl der Wiederholungsversuche, um einen Mount durchzuführen. Der Default-Wert liegt bei 5 |
hard | Ein Programm wird während des Zugriffs auf ein NFS-Verzeichnis hängen bleiben, falls der Server zusammenbricht. Nach Wiederanlaufen des Servers fährt das Programm mit seiner Arbeit fort. ein hängendes Programm, kann nur unterbrochen werden, wenn die Option »intr« angegeben wurde. |
soft | Der Kernel wird, falls der Server eine bestimmte Zeit lang (»retrans*timeo«) nicht antwortet, einen Fehler generieren und die auf den Server wartenden Prozesse informieren. Die Zeitdauer zwischen den Versuchen kann mit »timeo=Sekunden« eingestellt werden. |
intr, nointr | Möglichkeit des Abbruchs durch eine Tastenkombination (»interrupt«) bzw, das Verhindern derselben |
remount | Aushängen eines Verzeichnisses, um es sofort wieder (beispielsweise mit neuen Optionen) einzuhängen |
suid, nosuid | Möglichkeit zur Benutzung des SUID-Bits auf dem eingehängten Dateisystem |
retry=zahl | Anzahl der erfolglosen Mount-Versuche (Voreinstellung ist 10000), bis endgültig abgebrochen wird |
wsize=zahl | Setzt die Blockgröße beim Schreiben über NFS auf »Bytes« byte. Voreinstellung ist 1024, sollte aber auf 8192 gesetzt werden. |
rsize=zahl | Setzt die Blockgröße beim Lesen über NFS auf »Bytes« byte. Voreinstellung ist 1024, sollte aber auf 8192 gesetzt werden. |
timeo=zahl | Zeitspanne für Wiederholversuche, angegeben in Zehntelsekunden |
proto=protokoll | ab Version 3: Angabe des Protokolls (UDP oder TCP) |