RPC, NFS a automount

Milan Matlák, xmatlak (at) fi.muni.cz


Obsah


 

RPC

Mechanismus RPC je jedna z možných implementací obecného principu volání vzdálených procedur, kterou vyvinula firma Sun Microsystems a která se ujala a stala všeobecně uznávaným standardem v rámci rodiny protokolů TCP/IP kodifikovaný v dokumentech RFC. V systémech Linux je RPC realizován jako balík, který poskytuje aplikacím typu klient-server mechanismus vzdáleného volání procedur ve formě kolekce nástrojů a knihoven funkcí. V ideálním případě se určitým způsobem tedy dá na RPC nahlížet jako na určitou mezivrstvu zajišťující aplikacím transparentnost lokality výkonu procedur. V cestě dosažení tohoto ideálního stavu ale stojí některé technické problémy, o kterých se zmíníme později. Mezi aplikace postavené na RPC patří např. NIS (Network Information System) a níže popsaný NFS (Network File System).


Jak RPC funguje?

V tomto textu se nebudeme zabývat konkretní specifikací komunikačního protokolu RPC mezi klientem a serverem, přesto si však nastíníme dostačující popis funkce.

Pokud chce server poskytovat služby, resp. procedury, založené na RPC, je nezbytné aby dokázal okolí propagovat, co a jakým způsobem nabízí. Tuto základní úlohu plní démon tzv. portmapper neboli RPC library dispatcher, u kterého server-side programy registrují (1 - viz schéma níže) své procedury. Proceduře takto registrované je portmapperem přidělen přístupový TCP/IP port, na který se pak klienti mohou obracet se svými požadavky. Nabízí se zde ihned otázka, jakým způsobem se klient doví, na kterém portu má příslušnou proceduru hledat. Odpovědí na snadě je, že mu to prozradí portmapper (3)(4), který je pevně spojen s TCP/IP portem 111. V Linuxu se program na mapování portů nazývá /sbin/portmap nebo /usr/sbin/rpc.portmap. Kromě toho, že je třeba zajistit, aby se mapovač automaticky spouštěl při startu systému, není třeba žádná další konfigurace.

Základní princip jsme si tedy nastínili, ovšem tak jednoduché to ve skutečnosti není. Je zde spousta nezbytností, které je třeba zajistit. Jako první si uveďme potřebu se nějak dohodnout na tom jak procedury jednoznačně identifikovat. Firma Sun spravuje seznam tzv. čísel programů, které identifikují kolekci procedur, a snaží se tak předcházet situacím, kdy by dva různě orientované programy využívající RPC mohli používat stejné identifikace svých poskytovaných procedur. Rozsah čísel programů pod správou Sun je 0-1fffffff. Rozsah 20000000-3fffffff je pak poskytnut k volnému využití. V režii vývojářů jednoznačně identifikovatelných programů je pak stanovení čísel procedur a jejich verzí. Tyto tři čísla reprezentují jednoznačnou identifikaci vzdálené procedury a jsou využívána zejména během procesu registrace u portmapperu a při dotazování klienta na přístupový port procedury, na němž naslouchá tzv. spojka (stub).
Seznam definující přiřazení názvů služeb k číslům programů je obvykle uložen v souboru /etc/rpc, jehož část ukazuje následující výpis, kde si můžete všimnout jaké je programové číslo NFS.

#ident	"@(#)rpc	1.11	95/07/14 SMI"	/* SVr4.0 1.2	*/
#
#	rpc
#
portmapper  100000	portmap sunrpc rpcbind
rstatd      100001	rstat rup perfmeter rstat_svc
rusersd     100002	rusers
nfs         100003	nfsprog
ypserv      100004	ypprog
mountd      100005	mount showmount
ypbind      100007
walld       100008	rwall shutdown
yppasswdd   100009	yppasswd
etherstatd  100010	etherstat
rquotad     100011	rquotaprog quota rquota 
Příkazem rpcinfo -p se pak také můžete portmapperu zeptat, jaké služby pod jeho správou běží. Výstupem může být něco takového:
program vers proto   port
100000    2   tcp    111  portmapper
100000    2   udp    111  portmapper
100011    1   udp    749  rquotad
100011    2   udp    749  rquotad
100005    1   udp    759  mountd
100005    1   tcp    761  mountd
100005    2   udp    764  mountd
100005    2   tcp    766  mountd
100005    3   udp    769  mountd
100005    3   tcp    771  mountd
100003    2   udp   2049  nfs
100003    3   udp   2049  nfs
Spojka se vyskytuje jak na straně serveru tak i klienta. Na straně klienta se stará zejména o kódování (marshalling nebo též serializing) argumentů, případně pomocných objektů, pokud se jedná o volání odkazem, a o uskutečnění přenosu, čili odeslání (5) dotazu, čekání na přijetí odpovědi a její zpětné dekódování (unmarshalling nebo též deserializing). O (de)kódování si povíme později. Na straně serveru se spojky starají o přijetí dotazu, jeho dekódování, volání příslušné procedury (6) s danými parametry, převzetí výsledku, jeho kódování a zaslání odpovědi klientovi (7).

Ještě poznamenejme, že patrně v zájmu snazší implementace zavedla firma Sun konvenci, že všechny vzdálené procedury mají právě jeden vstupní parametr, a právě jeden výstupní parametr. Zdá-li se vám to příliš omezující, vězte, že pokud by bylo zapotřebí předat více parametrů, mohou být zabaleny do jedné datové struktury a předány vzdálené proceduře prostřednictvím jednoho ukazatele, která musí být samozřejmě v rámci vzdáleného volání přenesena na server.

eXternal Data Representation (XDR)

Jak už jsme zmínili výše, je pro potřeby předání dat mezi klientem a serverem nutno tato data kódovat, resp. zpracovat do podoby, které budou rozumět obě strany, zejména pokud se jedná o jiné počítačové architektury, kdy by např. chyba v určení velikosti integeru nebo endianitě mohla způsobit nežádoucí chyby.
Firma Sun pro implementaci a realizaci svého RPC mechanismu využívá standardu XDR, který je popsán v RFC 1832.

Standard XDR tedy definuje jednotný způsob reprezentace přenášených dat, nezávislý na konkrétní architektuře jejich odesilatele i příjemce. Kromě toho je součástí XDR také jazyk pro nezávislý popis těchto dat. Po stránce implementační souvisí s tímto standardem také konkrétní konverzní rutiny, které mají nejčastěji formu knihovních rutin, a jsou obvykle označovány jak XDR filtry.

RPC autentizační mechanismy

Z důvodu větší bezpečnosti a omezení přístupu k RPC službám byly zavedeny autentizační mechanismy popsané zejména v RFC 2695, kde je mimojiné popsán celý autentizační protokol. Způsobů jak se v prostředí RPC autentizovat je vícero, např. zasláním UID a GID uživatele, autentizace vůči systému kerberos a nebo pomocí asymetrické kryptografie. Šifrování jednotlivých zpráv je pak prováděno pomocí symetrického (DES) konverzačního klíče, který generuje klient a zasílá jej serveru při prvním RPC volání.

Literatura

 


NFS

Network File System byl vyvinut, aby umožnil připojení diskových oddílů vzdáleného stroje (počítače) stejně jako by se připojoval lokální disk. Umožňuje tak rychlé a transparentní sdílení souborů napříč sítí. Pro představu existuje více systémů, které fungují podobně jako NFS, např. Samba, která poskytuje souborové a tiskové služby klientům OS Windows.

Verze NFS

NFS ver. 1- prototypová verze, která nebyla nikdy použita.
NFS ver. 2- první distribuovaná verze
- ačkoliv byla tato verze podporována již od jádra verze 1.2, budete potřebovat jádro alespoň verze 2.2.18 pokud chcete kombinovat Linux NFS s NFS ostatních OS, používat spolehlivé zamykání souborů, nebo updatovat na NFS verze 3.
- přidává podporu Secure RPC (autentizace, šifrování).
NFS ver. 3- pro plnou funkcionalitu této verze je potřeba jádra verze alespoň 2.4, zejména tedy pokud chcete mít možnost pracovat se soubory většími než 2GB.
NFS ver. 4- zahrnuje např. podporu kopírování a přesouvání souborů i s jejich metainformacemi. Navíc také podporu silnější bezpečnosti, kombinovaných operací, klientské mezipaměti a internacionalizace.

Jak NFS funguje?

Jak už víme, je NFS postaveno na bázi RPC služeb. Budeme-li chtít připojit adresář na disku vzdáleného stroje, použijeme známého programu mount, kterému sdělíme parametrem -t nfs, že jej chceme zpřístupnit ze vzdáleného stroje. Například, chceme-li připojit adresář /exports/home/novak nacházející se na stroji zeus tak, aby byl přístupný lokálně přes /home/novak, pak to učiníme takto:

$ mount -t nfs zeus:/exports/home/novak /home/novak
Příkaz mount se pokusí pomocí RPC procedur spojit s připojovacím démonem mountd, který běží na počítači zeus. Samozřejmě po úspěšné autentizaci a předání komunikačního klíče pak již služby jádra klienta samozřejmě rozpoznávají, zda-li mají data získávat lokálně nebo pomocí RPC volat vzdálené procedury, které to za ně učiní.

Konfigurace NFS

Pro používání NFS, jak je patrno z předchozího textu, je potřeba mít v jádru zahrnutou podporu NFS. Zda-li náš systém podporuje NFS zjistíme v souboru /proc/filesystems a nebo se můžeme pokusit připojit nějaký vlastní lokální adresář.

Na straně klienta

Konfigurace NFS na straně klienta je poměrně snadná. Výše jsme si uvedli jeden ze způsobu připojení vzdáleného souborového systému, ovšem výhodnější je pro tyto potřeby definovat si záznamy v /etc/fstab.

Některé užitečné volby programu mount:

rsize=n wsize=n tyto volby určují velikost datagramu, které budou použity pro operace čtení a zápis. Implicitně 1kB.
timeo=n Specifikuje v desetinách sekundy, jak dlouho bude klient čekat na splnění požadavku. Implicitně 0.7 sekundy.
hard Pokud selže požadavek na server, pak, pokud není zadána volba intr, nelze klientský program ukončit. Ten svou činnost obnoví poté, co server začne být opět funkční. Zabraňuje se tak porušení struktury souborů.
soft Opak volby hard. Silně se nedoporučuje používat tuto volbu v případech, kdy nechceme, aby řízení přešlo na jinou aplikaci, dokud nejsou všechna data odeslána. (Např. v případě zpracování adresáře elektronické pošty.)
intr Tato volba povolí signálům přerušit volání systému NFS.
bg Připojení na pozadí. Je-li první pokus o připojení neúspěšný (např. spadlý server), přesune se proces na pozadí a bude se dál pokoušet o připojení. Tento parametr je výhodné používat pro připojení, která jsou součástí spouštěcího procesu. Proces spouštění tak není ohrožen, nepodaří-li se připojit sdílené diskové oddíly.
retrans=r  Hodnota r představuje maximální počet pokusů o připojení v systémech s měkkým připojením.

Na straně serveru

Pro konfiguraci NFS serveru je potřeba mít běžící démony: rpc.portmap, rpc.nfsd, rpc.mountd, rpc.lockd, rpc.statd a rpc.rquotad.
rpc.portmap  bez něj by nám NFS nefungovalo.
rpc.nfsd jde o hlavní část síťového souborového systému NFS, která zpracovává jednotlivé požadavky.
rpc.mountd je-li dán požadavek na připojení diskového oddílu, kontroluje, zda má klient odpovídající přístupová práva. Informace o právech jsou uloženy kde jinde než v /etc/exports.
rpc.statd tento démon zajišťuje uzamykání souborů v prostředí klient-server.
rpc.lockd démon rpc.statd používá démona rpc.lockd k zajištění obnovy zámků na spadlých systémech.
rpc.rquotad zajišťuje rozhraní mezi NFS a správcem kvót.

Zda-li vám běží zjistíte pomoci rpcinfo -p.
Pokud nikoliv pak (a samozřejmě máte NFS server nainstalovaný) pak:

$ /etc/rc.d/init.d/nfs start
  nebo
$ service nfs start

Konfigurace se provádí v souboru /etc/exports, kde jsou specifikovaný komu a za jakých podmínek je umožněno co připojit. Jeho formát je následující:

directory  machine1(option11,option12,...) machine2(option21,option22,...) ...
Kde directory určuje adresář, který má být sdílen, machineX jsou jména či IP adresy stanic klientů NFS a optionYY jsou volby resp. přístupová práva, která jsou daným klientům k tomuto adresáři přiděleny. Místo IP či názvu stroje lze také použít identifikaci sítě, kdy se za IP uvede lomítko a maska sítě.

Volby mohou být některé z následujících:
ro pouze pro čtení.
rw pro čtení i zápis.
noaccess klientovi bude odepřen přístup do všech podadresářů daného adresáře. Tímto způsobem jsme schopni povolit přístup třeba např. do všech podadresářů adresáře /data vyjma /data/jen_pro_karla.
no_root_squash root připojující se z klienta bude rootem i na exportovaném svazku.
no_subtree_check  pokud se připojuje celý svazek, pak tato volba urychlí připojení.
squash_uids=uid_list uid_list je čárkami oddělený seznam UID uživatelů, kterým chcete odepřít přístup. Je možné použít také rozsahy např. squash_uids=100-200,301
squash_gids=gid_list  obdobně jako v případě squash_uids=uid_list

Příklad /etc/exports:

/usr/local   192.168.10.2(ro) 192.168.10.5(rw)
/home        192.168.0.0/255.255.255.0(rw,no_root_squash)
/export/fun  *.lab.fi.muni.cz(ro)

Demon mountd je obvykle informován o tom, které adresáře jsou jeho prostřednictvím připojeny k daným hostům. Tyto informace lze získat pomocí programu showmount.

Pokud chcete, aby se případné změny v /etc/exports projevily bez nutnosti restartovat NFS server, použijte příkazu exportfs. Použít ho můžete mimojiné také k ručnímu nastavení sdílení bez nutnosti měnit /etc/exports.

Použít můžete následujících voleb:
-a exportuje všechny záznamy v souboru /etc/exports.
-r opětovně exportuje všechny záznamy v souboru /etc/exports.
-u client:/dir/to/mount  neexportovat adresář /dir/to/mount pro klienta client.
-o options zde je možné zadávat stejné volby, jaké se používají v /etc/exports. Budou se však vztahovat k souborovému systému určenému v příkazovém řádku exportfs.
-v bude vypisovat, co dělá.

Chcete-li například exportovat adresář /export/stuff pro klientskou stanici hera s právy pro čtení a zápis a no_root_squash napište

$ exportfs -o rw,no_root_squash hera:/export/stuff

Ke zvýšení bezpečnosti a omezení přístupu k exportovaným svazkům slouží také soubory /etc/hosts.allow a /etc/hosts.deny.

Literatura


 

Automount

Konfigurace Autofs

Automount je démon, který zajišťuje automatické připojování a odpojování svazků. Je spouštěn skriptem /etc/rc.d/init.d/autofs. Autofs je implementován v prostoru jádra, takže je potřeba mít v jádře jeho podporu zakompilovánu. Autofs podporují všechny jádra 2.2 a výše. Používá konfigurační soubor /etc/auto.master, jehož formát je:

mount_point map_type:map_name options 
kde mount_point je místo připojení, map_type jedno z file, program, yp, nisplus nebo hesiod, map_name jméno mapovacího souboru (o něm později) a options jsou nepovinné volby (např. --timeout=n určující po kolika sekundách se má daný souborový systém odpojit po posledním použití).

Příklad /etc/auto.master:

/usr/mnt  /etc/auto.misc  --timeout=60
Příklad auto.misc určeného v /etc/auto.master:
kernel  -ro,soft,intr   ftp.kernel.org:/pub/linux
boot    -fstype=ext2    :/dev/hda1
floppy  -fstype=vfat    :/dev/fd0
Je patrno, že položka /usr/mnt v auto.master nedefinuje mountpoint, ale obecně množinu mountpointů, které jsou definovány v souboru určeného druhou položkou, v našem případě /etc/auto.misc.
Soubor /etc/auto.misc, jak vidno, se skládá z řádků, kde jednotlivé položky po řadě představují: mountpoint (v našem případě např. /usr/mnt/floppy), volby připojení a to, co chceme připojit. Všimněme si prvního řádku, kde se jedná o připojení přes NFS.

Konfigurace Amd

Jiným oblíbeným automounterem je Amd. Konfiguruje se v souboru /etc/amd.conf. Aby se změny v tomto konfiguračním souboru projevily ihned, je třeba Amd restartovat. Může vypadat následovně:

/defaults       opts:=rw;type=nfs
# where you have your home directory
home            type:=nfs;rhosts:=home;rfs:=/home
# where you have your incoming emails
mail            type:=nfs;rhosts:=mail;rfs:/var/spool/mail
# Replace with the server you have access to
server1         type:=nfs;rhosts:=server1;rfs:=/server1
kde první položka představuje mountpoint v adresáři, který definujete parametrem -a dir při spouštění Amd démona. Obvykle je to adresář /.automount. Ostatní položky na řádku definují co a jak se má k danému mountpointu připojovat.

Pokud démon Amd běží, pak se svazky připojují jakmile se je pokusíte zpřístupnit např. příkazem ls /.automount/home/karel. Po určité časové prodlevě, po které nebyl svazek zpřístupněn, se opět automaticky odpojí. Tímto způsobem se tedy snadno řeší připojování třeba domovského adresáře, při přihlášení uživatele, a odpojení při jeho odhlášení.

Literatura