UCSPI
(v0.1) |
(frissítés 2007) |
||
32. sor: | 32. sor: | ||
Ha létrejön a kapcsolat, ''tool'' elindítja a kliens- vagy szerveralkalmazást. |
Ha létrejön a kapcsolat, ''tool'' elindítja a kliens- vagy szerveralkalmazást. |
||
+ | |||
+ | Vegyük észre, hogy igazából itt a ''tool'' is csak egy olyan program, mint mondjuk a <tt>chpst</tt>a [[A runit működése|runit]]nál: beállít valamilyen kezdeti környezetet, majd <tt>exec()</tt> hívással ebben a környezetben indít el egy gyermekfolyamatot. Itt a környezet létrehozásához néhány socket megnyitása is hozzá tartozik. |
||
Így amúgy elvileg megfordíthatjuk a kliens-szerver működést: pl. megcsinálhatjuk, hogy az <tt>axfrdns</tt>-ünk "kapcsolódjon" egy (UCSPI-t támogató) AXFR-kliensre. |
Így amúgy elvileg megfordíthatjuk a kliens-szerver működést: pl. megcsinálhatjuk, hogy az <tt>axfrdns</tt>-ünk "kapcsolódjon" egy (UCSPI-t támogató) AXFR-kliensre. |
||
− | Az UCSPI-kliens által indított alkalmazás a 6-os fájlleírón olvashatja a szerver üzeneteit, a 7-es fájlleiróra pedig írhatja azt, amit a szervernek mondani szeretne. |
+ | Az UCSPI-kliens által indított alkalmazás |
+ | * a 6-os fájlleírón olvashatja a szerver üzeneteit, |
||
+ | * a 7-es fájlleiróra pedig írhatja azt, amit a szervernek mondani szeretne. |
||
+ | * Az stdin-t és az stdout-ot a szülőjétől örökli (ha interaktívan futtatjuk, a konzol marad az stdin/stdout). |
||
+ | ** Így nem UCSPI-felhasználásra készült program sajnos nem használható UCSPI-kliensként (mert nem tudják, hogy a 6-os és a 7-es fájlleíró különleges). Workaround (nem próbáltam, de mennie kéne): |
||
+ | <pre> |
||
+ | #!/bin/zsh |
||
+ | exec $1 $@ >&7 <&6 |
||
+ | </pre> |
||
+ | |||
+ | (Ez egy olyan script, ami a neki átadott programot úgy futtatja, hogy annak az stdin/stdout párosára rámásolja a saját 6-os ill. 7-es fájlleíróját.) |
||
== Protokollfüggetlenség == |
== Protokollfüggetlenség == |
||
85. sor: | 87. sor: | ||
-rcn-kr.blackholes.us \ |
-rcn-kr.blackholes.us \ |
||
-rblackholes.wirehub.net \ |
-rblackholes.wirehub.net \ |
||
− | -rassholes.madscience.nl \ |
||
− | -runconfirmed.dsbl.org \ |
||
− | -rlist.dsbl.org \ |
||
− | -rdnsbl.njabl.org \ |
||
− | -rsbl.spamhaus.org \ |
||
− | -rwork.drbl.croco.net \ |
||
− | -rspamsources.fabel.dk \ |
||
− | -ropm.blitzed.org \ |
||
/usr/sbin/qmail-smtpd |
/usr/sbin/qmail-smtpd |
||
</pre> |
</pre> |
||
101. sor: | 95. sor: | ||
* <tt>softlimit</tt>: a [[daemontools]] csomag egyik <tt>chpst</tt>-szerű segédprogramja, erőforráskorlátokat állít be, majd <tt>exec</tt>-kel elindít egy gyermekfolyamatot. |
* <tt>softlimit</tt>: a [[daemontools]] csomag egyik <tt>chpst</tt>-szerű segédprogramja, erőforráskorlátokat állít be, majd <tt>exec</tt>-kel elindít egy gyermekfolyamatot. |
||
* <tt>envuidgid</tt>: szintén a daemontoolsból van; ez az UID és a GID környezeti változókat állítja be a megadott user (itt <tt>qmaild</tt>) user- ill. group ID-jára. |
* <tt>envuidgid</tt>: szintén a daemontoolsból van; ez az UID és a GID környezeti változókat állítja be a megadott user (itt <tt>qmaild</tt>) user- ill. group ID-jára. |
||
+ | ** Így külön programba szerveződött ki az NSS (Name Service Switch) kezelése; a gyermekfolyamat már numerikus ID-kat kap az UID/GID változókban. |
||
* <tt>tcpserver</tt>: egy TCP-porton figyel. A paraméterek jelentése: |
* <tt>tcpserver</tt>: egy TCP-porton figyel. A paraméterek jelentése: |
||
** -U: a port megnyitása után válts az UID változóban megadott user- és a GID változóban megadott group ID-ra. |
** -U: a port megnyitása után válts az UID változóban megadott user- és a GID változóban megadott group ID-ra. |
||
109. sor: | 104. sor: | ||
** -t3: legfeljebb 3 másodpercig próbálkozz a <tt>TCPREMOTEINFO</tt> (távoli usernév) megszerzésével. |
** -t3: legfeljebb 3 másodpercig próbálkozz a <tt>TCPREMOTEINFO</tt> (távoli usernév) megszerzésével. |
||
** -x /etc/tcp.smtp.cdb: a megadott cdb-fájlban felsorolt szabályok szerint egyes kliensek számára állíts be további környezeti változókat is. |
** -x /etc/tcp.smtp.cdb: a megadott cdb-fájlban felsorolt szabályok szerint egyes kliensek számára állíts be további környezeti változókat is. |
||
− | ** -X: akkor is fogadd el a kapcsolatokat, ha a megadott cdb-fájl nem létezne. |
+ | ** -X: akkor is fogadd el a kapcsolatokat, ha a megadott cdb-fájl nem létezik. |
− | ** 0: a 0.0.0.0-ás IP-n (vagyis a gép összes interface-én) nyújtsd a szolgáltatást. |
+ | ** 0: a 0.0.0.0-ás IP-n (vagyis a gép összes interface-ének összes IP-jén) nyújtsd a szolgáltatást. |
− | ** smtp: az "smtp" nevű szolgáltatás portján figyelj. |
+ | ** smtp: az "smtp" nevű szolgáltatás portján figyelj (általában a <tt>/etc/services</tt> fájlban vannak a szolgáltatásnév-portszám-párosok). |
* <tt>rblsmtpd</tt>: ez egy minimális smtp-szerver, ami megnézi, hogy a kliens (<tt>TCPREMOTEIP</tt>) szerepel-e a megadott RBL-ekben, és ha igen, mond neki egy 451-et; ha nem, elindítja a megadott programot, ami itt a <tt>qmail-smtpd</tt>, és átadja neki a klienst. |
* <tt>rblsmtpd</tt>: ez egy minimális smtp-szerver, ami megnézi, hogy a kliens (<tt>TCPREMOTEIP</tt>) szerepel-e a megadott RBL-ekben, és ha igen, mond neki egy 451-et; ha nem, elindítja a megadott programot, ami itt a <tt>qmail-smtpd</tt>, és átadja neki a klienst. |
||
* <tt>qmail-smtpd</tt>: végül elindul maga a qmail-smtpd és lebonyolítja az SMTP-tranzakciót. |
* <tt>qmail-smtpd</tt>: végül elindul maga a qmail-smtpd és lebonyolítja az SMTP-tranzakciót. |
A lap 2007. december 14., 01:05-kori változata
UCSPI: UNIX Client-Server Program Interface (elvileg úgy kéne ejteni, hogy ooks-pie, úkszpáj; mi maradjunk az ú-cé-es-pé-í-nél :)
Tartalomjegyzék |
1 Mire való?
Kliens-szerver architektúrájú programok egymás közötti kommunikációjának néhány konvencióját fekteti le.
Alapötlet: válasszuk szét a programok hálózati részét a nemhálózati résztől. Ezt gyakran meg lehet tenni, mert egy kliensprogram számára igazából csak az a fontos, hogy beszélhessen egy szerverrel, de igazából mindegy neki, hogy ez milyen konkrét átviteltechnikával történik.
Az UCSPI a kliens számára biztosít két fájldeszkriptort: amit az egyikbe ír, azt megkapja a szerver, és amit a szerver mond, azt kiolvashatja a másikból.
Szerveroldalon kb. úgy működik, mint az inetd: figyel egy (csak egy!) porton, és ha kapcsolat jön, elindítja a szerveralkalmazást úgy, hogy a standard inputja és outputja is a kapcsolat socketje legyen.
Előnyök:
- (Majdnem) független a protokolltól; pl. elvileg transzparens a számára, hogy IPv4 vagy IPv6 van alatta.
- A hálózati funkciót elválasztja az alkalmazástól, így egy egyszerű shellscript is lehet szerver vagy kliens.
- Egy csomó információt környezeti változókba rak, így akár scriptekből is könnyen felhasználhatjuk őket.
- A nem kifejezetten UCSPI-hez írt (szerver)programok jó része is működik így.
- Azáltal, hogy egy szerver csak egy porton figyel, a szerverek konfigurációja automatikusan szét van választva; futhatnak különböző chrootban stb.
2 Alapvető működés
Egy UCSPI-eszköz parancssora ilyesmi:
[tool] [options] [address] [application]
- tool: maga az eszköz
- options: a saját opciói, pl. verbozitás
- address: szerver esetén itt kell figyelni, kliens esetén ide kell kapcsolódni
- application: az elindítandó kliens vagy szerver neve és opciói
Ha létrejön a kapcsolat, tool elindítja a kliens- vagy szerveralkalmazást.
Vegyük észre, hogy igazából itt a tool is csak egy olyan program, mint mondjuk a chpsta runitnál: beállít valamilyen kezdeti környezetet, majd exec() hívással ebben a környezetben indít el egy gyermekfolyamatot. Itt a környezet létrehozásához néhány socket megnyitása is hozzá tartozik.
Így amúgy elvileg megfordíthatjuk a kliens-szerver működést: pl. megcsinálhatjuk, hogy az axfrdns-ünk "kapcsolódjon" egy (UCSPI-t támogató) AXFR-kliensre.
Az UCSPI-kliens által indított alkalmazás
- a 6-os fájlleírón olvashatja a szerver üzeneteit,
- a 7-es fájlleiróra pedig írhatja azt, amit a szervernek mondani szeretne.
- Az stdin-t és az stdout-ot a szülőjétől örökli (ha interaktívan futtatjuk, a konzol marad az stdin/stdout).
- Így nem UCSPI-felhasználásra készült program sajnos nem használható UCSPI-kliensként (mert nem tudják, hogy a 6-os és a 7-es fájlleíró különleges). Workaround (nem próbáltam, de mennie kéne):
#!/bin/zsh exec $1 $@ >&7 <&6
(Ez egy olyan script, ami a neki átadott programot úgy futtatja, hogy annak az stdin/stdout párosára rámásolja a saját 6-os ill. 7-es fájlleíróját.)
3 Protokollfüggetlenség
Elvileg az UCSPI "nagyjából" protokollfüggetlen.
Egy-egy tool általában egy protokollt támogat; gondoljunk rájuk úgy, mint hálózati kommunikációs backendekre.
Egy protokoll a következő dolgokat határozza meg:
- address' formátumát és jelentését;
- azt, hogy milyen környezeti változókat kell beállítani.
Így persze lehet olyan kliens- vagy szerveralkalmazást írni, ami protokollfüggő, mert olyan környezeti változót szeretne, ami csak az egyik protokollra jellemző, de nem muszáj.
A toolok a következő környezeti változókat állítják be:
- PROTO: a protokoll, amit használunk. TCP esetén pl. TCP.
- PROTOLOCAL*: a kapcsolat helyi végére jellemző adatok, pl:
- TCPLOCALIP: a kapcsolathoz tartozó helyi IP-cím;
- TCPLOCALPORT: a kapcsolathoz tartozó helyi port;
- TCPLOCALHOST: a helyi IP-hez tartozó név (vagy üres);
- PROTOREMOTE*: a kapcsolat túlvégére jellemző adatok, pl:
- TCPREMOTEIP: a távoli IP (szervernél a kliens IP-je, kliensnél a szerver IP-je);
- TCPREMOTEPORT, TCPREMOTEHOST: értelemszerű;
- TCPREMOTEINFO: távoli usernév (ident/auth szolgáltatás révén), vagy üres.
A szervertoolok általában a kliens IP-jének/nevének függvényében egyéb környezeti változókat is be tudnak állítani.
4 Példa
Minden ilyesmit példákon keresztül a legegyszerűbb megérteni.
4.1 qmail-smtpd
Nézzük pl. a qmail SMTP-daemonját, a qmail-smtpd-t. Ez egy elég egyszerű kis program, ami a konfigurációja jelentős részét környezeti változókból veszi. Saját hálózatkezelés nincs benne; az ucspi-tcp csomag tcpserver programja (ami egy UCSPI-szervertool) nyújtja neki a TCP-porton való figyelést, mint szolgáltatást.
Egy qmail-smtpd-parancssor pl. a következőképpen festhet:
#!/bin/sh exec 2>&1 exec env - PATH="$PATH" \ /usr/bin/softlimit -d 10485760 \ envuidgid qmaild \ /usr/bin/tcpserver -U -c20 -v -h -p -t3 -x /etc/tcp.smtp.cdb -X 0 smtp \ /usr/bin/rblsmtpd \ -rcn-kr.blackholes.us \ -rblackholes.wirehub.net \ /usr/sbin/qmail-smtpd
Lássuk, mi minden van itt:
- env: környezettisztítás; egyedül a PATH változót örökítjük át a gyermekfolyamatainkra.
- softlimit: a daemontools csomag egyik chpst-szerű segédprogramja, erőforráskorlátokat állít be, majd exec-kel elindít egy gyermekfolyamatot.
- envuidgid: szintén a daemontoolsból van; ez az UID és a GID környezeti változókat állítja be a megadott user (itt qmaild) user- ill. group ID-jára.
- Így külön programba szerveződött ki az NSS (Name Service Switch) kezelése; a gyermekfolyamat már numerikus ID-kat kap az UID/GID változókban.
- tcpserver: egy TCP-porton figyel. A paraméterek jelentése:
- -U: a port megnyitása után válts az UID változóban megadott user- és a GID változóban megadott group ID-ra.
- -c20: legfeljebb 20 párhuzamos kapcsolatot fogadj el (legfeljebb ennyi példány futhat a qmail-smtpd-ből).
- -v: légy szószátyár (mindenféle státusz-üzenetekkel szórakoztat minket).
- -h: oldd fel a kliens nevét a DNS-ben és állítsd be a TCPREMOTEHOST változót a qmail-smtpd elindítása előtt.
- -p: paranoid működés: az imént kapott neved oldd fel a DNS-ben, és ha a kapott A rekordok egyike sem egyezik meg a kliens IP-jével, töröld a TCPREMOTEHOST változót.
- -t3: legfeljebb 3 másodpercig próbálkozz a TCPREMOTEINFO (távoli usernév) megszerzésével.
- -x /etc/tcp.smtp.cdb: a megadott cdb-fájlban felsorolt szabályok szerint egyes kliensek számára állíts be további környezeti változókat is.
- -X: akkor is fogadd el a kapcsolatokat, ha a megadott cdb-fájl nem létezik.
- 0: a 0.0.0.0-ás IP-n (vagyis a gép összes interface-ének összes IP-jén) nyújtsd a szolgáltatást.
- smtp: az "smtp" nevű szolgáltatás portján figyelj (általában a /etc/services fájlban vannak a szolgáltatásnév-portszám-párosok).
- rblsmtpd: ez egy minimális smtp-szerver, ami megnézi, hogy a kliens (TCPREMOTEIP) szerepel-e a megadott RBL-ekben, és ha igen, mond neki egy 451-et; ha nem, elindítja a megadott programot, ami itt a qmail-smtpd, és átadja neki a klienst.
- qmail-smtpd: végül elindul maga a qmail-smtpd és lebonyolítja az SMTP-tranzakciót.
A qmail-smtpd működését az alábbi környezeti változók befolyásolják (ezeknek egy része a SPAMCONTROL nevű patch-csel jön):
- DATABYTES: legfeljebb mekkora levelet küldhet a kliens.
- HELODNSCHECK: ellenőrizze-e, hogy a HELO-ban átadott névnek van-e MX vagy A rekordja (noha elvileg csak A kéne hogy legyen, az MX irreleváns); ha nincs, 451-es kódot mond.
- RELAYCLIENT: ha be van állítva, a kliens bárhova küldhet levelet (olyat is, ami nem a mi gépünknek szól).
- MAXRECIPIENTS: legfeljebb hány címzettje lehet a levélnek.
- MFDNSCHECK: ha be van állítva, visszautasítja a levelet (451), ha a MAIL FROM-ban szereplő domainnek sem MX, sem A rekordja nincs.
- stb.
Látható, hogy ezeknek az értéke kliensfüggő kéne, hogy legyen. Az egyes kliensekre vonatkozó szabályokat a tcp.smtp.cdb fájlban adhatjuk meg.
A tcp.smtp.cdb egy szövegfájlból készül, amelyben ilyesmik vannak (a formátum neve amúgy tcprules, az után a program után, ami cdb-vé fordítja):
127.0.0.1:allow,RELAYCLIENT="",RBLSMTPD="",MAXRECIPIENTS="100" 1.2.3.:allow,HELODNSCHECK="",MFDNSCHECK="",MAXRECIPIENTS="100" 1.2.3.4:deny 1.2.5-15.:allow,RBLSMTPD=/-mail blocked. Keep your spam./ :allow,HELODNSCHECK="",MFDNSCHECK="",MAXRECIPIENTS="10"
(Ez valószínűleg részben átkerül majd az ucspi-tcp ill. a qmail szócikkbe, ha elkészülnek.)
4.2 axfr-get
Az axfr-get egy egyszerű AXFR-kliens, amivel egy domain zónafájlját tudjuk letölteni egy szerverről.
Futtatása:
tcpclient -R -v a.root-servers.net 53 axfr-get . rootzone rootzone.tmp