Dështimi i client-connect në OpenVPN: a është i garantuar pastrimi në disconnect?
Një klient i refuzuar nuk e zhbën një rregull firewall-i ose një regjistrim të shkruar. Krahasoni kontratën e callback-ut me kthimin mbrapsht që duhet të bëjë vetë hook-u juaj.
Kur një skript client-connect del me një kod jo zero, OpenVPN e refuzon klientin, dhe operatorët zakonisht supozojnë se skripti përkatës client-disconnect do t’i rregullojë gjërat. Shpesh ai nuk ekzekutohet kurrë, sepse përpunimi i disconnect varet nga ajo që faza connect arriti të përfundojë. Trajtimi i refuzimit dhe i kthimit mbrapsht si një mekanizëm i vetëm është ajo që e shndërron një hyrje të dështuar në një rregull firewall-i të rrjedhur ose në një regjistrim jetim. Janë dy detyrime të ndara, dhe vetëm njëri prej tyre është automatik. Lexoni rrugën e daljes të vetë hook-ut përpara se të fajësoni serverin për gjendjen e lënë pas.
Një dalje jo zero e refuzon klientin; nuk e zhbën punën tuaj
Statusi i daljes së client-connect është një vendim pranimi. Zero do të thotë prano, çdo gjë tjetër do të thotë shemb instancën përpara se të vendoset plotësisht. Asgjë në atë kontratë nuk shqyrton atë që skripti ka bërë tashmë në botën e jashtme. Nëse skripti shtoi një rregull iptables, shkroi një rresht ose rriti një numërues, ato ndryshime i mbijetojnë refuzimit.
E njëjta asimetri vlen për shtojcat, ku disa funksione connect mund të ekzekutohen për një instancë të vetme. Një dështim i mëvonshëm nuk anulon në mënyrë retroaktive një sukses të mëparshëm, dhe funksioni i mëparshëm nuk ka asnjë mënyrë të mësojë se një funksion motër ka dështuar.
Refuzimi është automatik, pastrimi nuk është
Manuali i OpenVPN 2.6 e lidh përpunimin e client-disconnect me suksesin e përpunimit connect të mëparshëm. Një përjashtim i dokumentuar mbulon zinxhirët kaskadë: nëse një hap connect ka kthyer tashmë sukses, hapat përkatës disconnect përsëri ekzekutohen kur instanca shembet, edhe pse një hap connect i mëvonshëm dështoi. Ai përjashtim është i ngushtë dhe varet nga numri i callback-ve të konfiguruar, prandaj testimi i një skripti të vetëm shell nuk ju thotë asgjë për një zinxhir.
Hartoni konfigurimin aktual përpara se të projektoni rreth tij: cili skript, cila shtojcë dhe në çfarë rendi ekzekutohen. Tabela më poshtë rendit atë që lë pas një konfigurim gjysmë i përfunduar.
| What the hook did before failing | What the client sees | What stays behind |
|---|---|---|
| Created a firewall entry | A rejection, with no tunnel | A rule matching an address nobody owns |
| Wrote a state row | A rejection, with no tunnel | A record of a session that never started |
| Allocated a tunnel address | A rejection, with no tunnel | An address marked busy until something releases it |
Çdo rresht përfundon njësoj për klientin dhe ndryshe për hostin. Klienti nuk mund të dijë cila prej tyre ndodhi, kështu që hook-u duhet të zhbëjë atë që bëri përpara se të kthejë statusin e dështimit.
Kompensoni brenda skriptit që dështoi
Vërtetoni gjithçka që mundeni përpara se të prekni gjendjen e përbashkët: fushat e certifikatës, disponueshmërinë e adresës, grupin të cilin klienti i përket. Refuzimi më i lirë është ai që ndodh përpara çdo caktimi. Pasi konfigurimi përfshin disa operacione të jashtme, mbani shënim se cilat përfunduan dhe kthejini mbrapsht në rend të kundërt përpara se të ktheni statusin e dështimit.
Një rast konkret: skripti krijon një zë firewall-i për çdo klient, pastaj dështon të shkruajë rreshtin e gjendjes që e përshkruan atë. Dega që dështon duhet të heqë zërin e sapokrijuar dhe më pas të dalë me një kod jo zero. Pritja e një ngjarjeje disconnect që mund të mos planifikohet kurrë është mënyra se si një rregull i mbijeton sesionit për të cilin ishte menduar.
Bëjeni kompensimin idempotent dhe me pronar
Pastrimi duhet të jetë i sigurt për t’u ekzekutuar dy herë dhe i saktë për atë që mund të fshijë. Një ngjarje e vonë nga një përpjekje e mëparshme nuk duhet të heqë caktimin e një sesioni më të ri vetëm sepse të dy ndajnë një emër të përbashkët ose një adresë tuneli të ricikluar. Regjistroni dorezën ose ID-në e operacionit specifik bashkë me burimin, dhe fshini sipas atij çelësi, jo sipas emrit. Transaksionet e bazës së të dhënave ndihmojnë vetëm me ndryshimet e vetë bazës; një rregull firewall-i jashtë atij kufiri kërkon një hap të qartë kompensimi.
Supozoni se procesi mund të vdesë midis ndryshimit dhe pastrimit, dhe shtoni një pajtues që sipas një plani krahason gjendjen e jashtme me listën e klientëve të pranuar.
Testoni tre rrugët që vërtet ndryshojnë
Ushtroni tre raste: një refuzim përpara se të caktohet gjë, një pas një caktimi të pjesshëm, dhe një sesion normal i pranuar që përfundon më vonë. Ato të tre prodhojnë rreshta regjistri të ndryshëm dhe mbetje të ndryshme. Verifikoni gjendjen e jashtme pas secilit, jo vetëm mesazhin e dështimit të klientit, sepse dështimi i klientit është rezultati i pritur në dy nga tre.
Regjistroni fazën e hook-ut, statusin e daljes dhe çfarë u caktua ose u lirua, pa kredencialet. Një regjistër hook-u që emërton burimin e krijuar është ai që e bën një rregull të rrjedhur të gjendeshëm gjashtë muaj më vonë.