ProtectHome versus een TOTP-seed: waarom de VPN-login mislukt
Een juiste code helpt een PAM-module die de seed niet kan openen niet. Kies tussen een drop-in en een schrijfbaar toestandspad en controleer dan de unit.
De authenticator toont een nieuwe zescijferige code, de VPN weigert die, en dezelfde code verifieert prima wanneer je hem vanuit je eigen shell test. Dat gat is het hele verhaal. Een PAM-module die het inschrijvingsgeheim niet kan openen, geeft een fout terug die er identiek uitziet als een verkeerde code, en de dienstomgeving die thuismappen verbergt is daar een veelvoorkomende oorzaak van. Beslis, voordat je enige toestemming versoepelt, in welke van drie situaties je zit.
Welke van de drie fouten is dit?
De eerste is een geheim dat de module helemaal niet kan lezen. De tweede is een geheim dat hij kan lezen maar niet kan bijwerken. De derde is een code die echt fout is, meestal door klokdrift of een hergebruikte waarde.
Scheid ze door het dienstjournaal en het systeemauthenticatielog voor één mislukte poging te lezen, en bevestig dan welke PAM-dienst de plug-in laadt en welke moduleregel die dienst gebruikt. Een algemene authenticatiefoutmelding onderscheidt ze niet, en een geslaagde handmatige test ook niet, omdat jouw shell niet de omgeving van de dienst is.
De bestandssysteemweergave van de unit is de gebruikelijke schuldige wanneer alleen de dienst faalt.
systemctl show -p ProtectHome -p ProtectSystem -p ReadWritePaths [email protected]
ls -l /var/lib/vpn-otp/*/.google_authenticator 2>/dev/null | head -n 20Optie A: haal het geheim uit de thuismap
Wanneer de dienst /home verbergt en je die bescherming liever houdt, sla het geheim dan op waar hij het kan zien. De module accepteert een secret=-pad en een user=-account dat de bestandsbewerkingen uitvoert, waardoor een centrale opslag veel identiteiten kan bedienen.
Dit is de nette optie, en het is degene die de meeste zorg vraagt, omdat een gedeelde opslag één map de beveiligingsgrens voor elk account maakt.
auth required pam_google_authenticator.so secret=/var/lib/vpn-otp/${USER}/.google_authenticator user=vpn-otpControleer drie dingen voordat je erop vertrouwt: het account bestaat, het werkproces van de module kan ernaar overschakelen, en de bestanden zijn van hem met beperkende modi. Gebruik geen ~ of een pad met thuisvariabele samen met user=, en schakel de eigendomscontroles van de module niet uit om een pad te laten werken. Houd de wachtwoordfase en de rest van de stack intact.
Optie B: laat het bestand staan en open een pad
Als het geheim in de thuismap van de gebruiker moet blijven, heeft de unit een weergave nodig die die ene map bevat zonder elke thuismap op de host bloot te leggen. Een drop-in kan een nauw begrensde bind-mount onder een gesandboxte thuismap toevoegen.
Dit houdt eigendom per gebruiker als model, ten koste van een unitwijziging die moet worden herzien telkens wanneer de sandbox verandert.
Twee grenzen worden gemakkelijk gemist. Een alleen-lezen pad dat onder een map wordt toegevoegd die de sandbox verbergt, legt die niet bloot, omdat de ouder er simpelweg niet is. En de mount moet schrijfbaar zijn als de module de status moet bijwerken, wat de volgende optie in het spel brengt. Schrijf de drop-in als een apart bestand in plaats van de verpakte unit onder /usr/lib te bewerken, zodat een pakketupgrade hem niet stilzwijgend ongedaan maakt.
Optie C: houd de sandbox en repareer statusschrijfacties
Het geheim lezen is maar de helft van authenticatie. De module kan tijdsafwijkingsinformatie, replaybescherming of een teller herschrijven, en een bestand dat de leescontrole doorstaat kan alsnog falen bij het schrijven.
Die fout ziet er bij de volgende poging als een slechte code uit en niet bij deze, waardoor hij met klokdrift wordt verward.
Geef hem een eigen schrijfbare map en wijs het geheim daarheen, in plaats van de hele thuismap schrijfbaar te maken. Bevestig de eigenaar van de map, de vrije ruimte van het bestandssysteem en of de unit schrijfacties elders beperkt. Test dan twee opeenvolgende logins, want de tweede bewijst het schrijfpad en de eerste alleen het lezen.
Verifieer als de dienst, niet als jezelf
Elke controle die ertoe doet, moet binnen de sandbox van de unit met de identiteit van de unit draaien.
Een commando dat als root slaagt, vertelt je dat het bestand bestaat en niets anders. Een login via de echte dienst vertelt je of de module het geheim kan lezen, gebruiken en terugschrijven wat hij nodig heeft.
Houd ten slotte de eis intact. Een null-wachtwoordoptie toevoegen, alleen-lezenfouten accepteren of de sandbox verwijderen zouden allemaal het symptoom laten verdwijnen door het beleid te wijzigen. Een gebruiker die een code moet voorleggen, moet nog steeds worden geweigerd wanneer het geheim onbereikbaar is.