Je wachtwoord klopt, de VPN-aanmelding mislukt toch, en de RADIUS-server heeft misschien precies gedaan wat hem is opgedragen. De gateway heeft waarschijnlijk een Access-Challenge ontvangen, niets nuttigs getoond en is daarna in een timeout gelopen of heeft dat antwoord als afwijzing behandeld. Vanaf de client ziet het eruit als verkeerde inloggegevens of een kapotte tunnel. De oorzaak zit meestal midden in een gesprek dat niemand heeft vastgelegd.

Eén aanmelding, twee RADIUS-uitwisselingen

Als de backend een tweede factor wil, antwoordt hij niet op het eerste verzoek met acceptatie of afwijzing. Hij antwoordt met code 11 en wacht op het volgende antwoord van de gebruiker, dat de gateway in een vervolgverzoek moet terugsturen. Dat vervolgverzoek hoort bij hetzelfde authenticatiegesprek, niet bij een nieuwe aanmeldpoging.

In een werkende opstelling ziet de gebruiker een tweede prompt: eerst het wachtwoord, dan een eenmalige code, of één gecombineerde prompt als de beheerder die heeft gedocumenteerd. In een kapotte opstelling verschijnt de tweede prompt nooit en mislukt de aanmelding simpelweg.

Dat is het symptoom om na te jagen, en het is eenvoudig te bevestigen vanaf alleen de client: als de VPN-client om precies één geheim vraagt en daarna een wachtwoord afwijst waarvan je weet dat het geldig is, eindigde de uitwisseling waarschijnlijk bij de challenge.

Wat de challenge werkelijk draagt

De RADIUS-specificatie beschrijft code 11 in sectie 4.4 en staat twee attributen toe die hier belangrijk zijn. Reply-Message bevat tekst voor de gebruiker, en State bevat een ondoorzichtige waarde die de server terug wil. De NAS hoort State niet te interpreteren, alleen ongewijzigd terug te geven.

Het vervolgverzoek gebruikt een nieuwe Identifier en een nieuwe Request Authenticator, en het moet dezelfde State-waarde plus het antwoord van de gebruiker dragen. De server koppelt het via die State aan de wachtende challenge, en daarom kan een gateway die het attribuut opnieuw genereert of laat vallen de ceremonie niet afmaken. Ook de response authenticator in elk antwoord moet valideren, anders hoort de NAS het pakket weg te gooien.

Sectie 4.4 voegt het detail toe dat de meeste stille fouten verklaart: een NAS die geen challenges kan ondersteunen, behandelt Access-Challenge als een afwijzing. Als de VPN-dienst van je gateway ouder is dan die ondersteuning of die weglaat, wordt het verzoek van de backend om een tweede factor een onmiddellijk «authenticatie mislukt» zonder enige prompt.

Waar het geketende verzoek verloren gaat

De eerste verdachte is het promptpad, niet de inloggegevens. Een portaal dat een OTP-veld toont voor webaanmeldingen, doet dat niet automatisch voor de VPN-dienst, en sommige gateways geven een challenge alleen door aan clients die de mogelijkheid aankondigen. Test hetzelfde account op beide ingangen; als het portaal werkt en de VPN niet, kijk je naar de overdracht, niet naar het token.

Het invoerformaat is de tweede verdachte. Wachtwoord en code aaneenplakken zonder het gedocumenteerde scheidingsteken van de leverancier, of opgeslagen inloggegevens een oude code laten herhalen, mislukt op een manier die identiek lijkt aan een verkeerd wachtwoord. Gebruik de gedocumenteerde aparte prompt of het gecombineerde formaat van de beheerder, en verzin nooit een scheidingsteken.

Versiespecifieke fouten bestaan, maar een lijst met gecorrigeerde versies van jaren geleden is geen diagnose voor de uitrol van vandaag. Lees de release notes van de software die je werkelijk draait, en houd de waargenomen uitwisselingsfase als bewijs.

Volg één poging van begin tot eind

Reproduceer het één keer met debugging aan de serverkant aan, en houd elke andere sessie buiten het opnamevenster:

$ sudo radsniff -i eth0 -x -f 'udp port 1812'
$ sudo freeradius -X
$ radtest alice 'password' 127.0.0.1 0 testing123

Zoek in de uitvoer naar de vorm van het gesprek in plaats van één regel. Een eerste Access-Request met Identifier 3, een Access-Challenge die State draagt, dan een tweede Access-Request met Identifier 4 die deze State herhaalt en het antwoord van de gebruiker bevat. Ontbreekt het tweede verzoek, dan heeft de gateway nooit gevolgd. Komt het zonder State binnen, dan kan de server het niet aan de wachtende challenge koppelen en wijst het meestal af.

Verberg inloggegevens, tokens en onnodige identiteitsgegevens wanneer je het spoor deelt, en correleer gebeurtenissen uit de ene poging in plaats van herhalingen uit meerdere browsertabbladen te mengen. Tijdstempels zijn hier je vriend; een challenge die aankomt nadat de client heeft opgegeven, ziet er voor de gebruiker uit als een afwijzing en in het log als een traag antwoord.

De eindtoestand die je wilt, is een voltooid, geautoriseerd gesprek gevolgd door de bedoelde diensttoegang. Een antwoord dat van de RADIUS-server binnenkomt, bewijst veel minder dan dat.

Gerelateerde artikelen