Quan un script client-connect surt amb un codi diferent de zero, l’OpenVPN rebutja el client, i els operadors solen suposar que el script client-disconnect corresponent ho ordena tot. Sovint no s’executa mai, perquè el processament de disconnect depèn del que la fase connect va aconseguir completar. Tractar el rebuig i la reversió com un sol mecanisme és el que converteix un inici de sessió fallit en una regla de tallafoc filtrada o en un registre orfe. Són dues obligacions separades, i només una és automàtica. Llegiu el camí de sortida propi del hook abans de culpar el servidor per deixar estat enrere.

Una sortida diferent de zero rebutja el client; no desfà la vostra feina

L’estat de sortida de client-connect és una decisió d’admissió. Zero vol dir admetre; qualsevol altra cosa vol dir enderrocar la instància abans que estigui plenament establerta. Res en aquest contracte no inspecciona què ha fet ja el script al món exterior. Si el script ha afegit una regla d’iptables, ha escrit una fila o ha incrementat un comptador, aquests canvis sobreviuen al rebuig.

La mateixa asimetria s’aplica als connectors, on diverses funcions connect poden executar-se per a una sola instància. Una fallada posterior no cancel·la retroactivament un èxit anterior, i la funció anterior no té manera de saber que una funció germana ha fallat.

El rebuig és automàtic, la neteja no

El manual de l’OpenVPN 2.6 lliga el processament de client-disconnect a l’èxit previ del processament de connect. Una excepció documentada cobreix les cadenes en cascada: si un pas connect ja ha retornat èxit, els passos disconnect corresponents s’executen igualment quan s’enderroca la instància, encara que un pas connect posterior hagi fallat. Aquesta excepció és estreta i depèn de quants callbacks hi ha configurats, i per això provar un sol script de shell no us diu res sobre una cadena.

Mapa la configuració real abans de dissenyar-hi al voltant: quin script, quin connector i en quin ordre s’executen. La taula següent llista què deixa enrere una configuració a mig fer.

What the hook did before failingWhat the client seesWhat stays behind
Created a firewall entryA rejection, with no tunnelA rule matching an address nobody owns
Wrote a state rowA rejection, with no tunnelA record of a session that never started
Allocated a tunnel addressA rejection, with no tunnelAn address marked busy until something releases it

Cada fila acaba igual per al client i de manera diferent per a l’amfitrió. El client no pot saber quin d’aquests casos ha passat, així que el hook ha de desfer el que ha fet abans de retornar l’estat de fallada.

Compenseu dins del script que ha fallat

Valideu tot el que pugueu abans de tocar estat compartit: camps del certificat, disponibilitat de l’adreça, el grup al qual pertany el client. El rebuig més barat és el que passa abans de qualsevol assignació. Quan la configuració abasta diverses operacions externes, porteu un registre de quines s’han completat i desfeu-les en ordre invers abans de retornar l’estat de fallada.

Un cas concret: el script crea una entrada de tallafoc per client i després no aconsegueix escriure la fila d’estat que la descriu. La branca que falla ha de treure l’entrada que acaba de crear i després sortir amb un codi diferent de zero. Esperar un esdeveniment disconnect que potser mai no es programarà és com una regla sobreviu a la sessió per a la qual estava pensada.

Feu la compensació idempotent i amb propietari

La neteja ha de ser segura d’executar dues vegades i precisa sobre què pot esborrar. Un esdeveniment tardà d’un intent anterior no ha de treure l’assignació d’una sessió més nova només perquè totes dues comparteixen un nom comú o una adreça de túnel reciclada. Registreu el manejador o l’identificador d’operació concret amb el recurs, i esborreu per aquesta clau en lloc de pel nom. Les transaccions de base de dades només ajuden amb els canvis propis de la base de dades; una regla de tallafoc fora d’aquesta frontera necessita un pas de compensació explícit.

Suposeu que el procés pot morir entre el canvi i la neteja, i afegiu un reconciliador que compari periòdicament l’estat extern amb la llista de clients admesos.

Proveu els tres camins que realment difereixen

Exerciu tres casos: un rebuig abans que s’assigni res, un després d’una assignació parcial i una sessió admesa normal que després acaba. Aquests tres produeixen línies de registre diferents i residus diferents. Verifiqueu l’estat extern després de cadascun, no només el missatge de fallada del client, perquè la fallada del client és el resultat esperat en dos dels tres.

Registreu la fase del hook, l’estat de sortida i què s’ha assignat o alliberat, sense les credencials. Un registre de hook que anomena el recurs que ha creat és el que fa que una regla filtrada sigui trobable sis mesos després.

Articles relacionats