Vorige week kon een gebruiker inloggen op de VPN en belandde toch op een netwerk waar niets werd opgelost. De client zei verbonden, het gateway-log zei Access-Accept, en het identiteitsteam zei dat het account in orde was. De login had gewerkt; de autorisatie erachter niet. Wanneer een VPN-login mislukt, loop ik het pad dat het verzoek werkelijk aflegt — client, gateway, RADIUS-server, identiteitsprovider — en stop bij de eerste hop waarvan het antwoord niet overeenkomt met de volgende.

De client spreekt nooit RADIUS

Wat de app op de laptop ook toont, de eerste hop is het VPN-protocol: IKEv2, OpenVPN, WireGuard of een TLS-gebaseerde client. RADIUS komt in die uitwisseling niet voor. De client authenticeert zich bij de gateway met een certificaat, een gebruikersnaam en wachtwoord, of een EAP-methode die in de tunnelopzet wordt meegedragen.

Dat is belangrijk als je logs leest, want de algemene authenticatiefout die de gebruiker ziet, wordt door de gateway geproduceerd nadat die al met iets anders heeft gesproken. Als de client de gateway nooit bereikt, is er geen RADIUS-verzoek om te debuggen, en een uur op de RADIUS-server is verspild. Bevestig dat de tunnel überhaupt tot stand kwam voordat je de backend aanraakt.

De gateway is de RADIUS-client

Zodra de tunnelopzet het punt bereikt waar inloggegevens moeten worden gecontroleerd, wordt de gateway een netwerktoegangsserver. Hij bouwt een Access-Request: User-Name, een wachtwoord of EAP-payload, NAS-IP-Address of NAS-Identifier, en een Message-Authenticator wanneer de methode er een vereist. Het verzoek gaat standaard naar UDP 1812, en de accounting naar 1813. Oudere implementaties gebruiken nog 1645 en 1646, dus een firewallregel voor het ene paar verklaart veel stille fouten.

Beide kanten delen een geheim, en dat is geen gebruikersreferentie. Het ondertekent de uitwisseling, en elk antwoord wordt ertegen geverifieerd. Configureer het geheim aan beide kanten verschillend en de server antwoordt niet met een fout geheim — hij laat het verzoek vallen of het antwoord faalt de verificatie, dus de gateway meldt een time-out. Een verkeerd geheim en een dode server zien er vanaf de gateway identiek uit, daarom test ik de hop met een clienttool voordat ik de directory de schuld geef.

Het protocol is klein en oud — RFC 2865 definieert de authenticatie-uitwisseling — maar de attributen die het draagt, zijn de basis waarop het meeste VPN-beleid is gebouwd.

# ask the RADIUS server directly, from the gateway host
radtest alice 'test-password' 127.0.0.1 0 testing123

# watch the exchange the gateway actually sends
tcpdump -ni any -c 20 'udp port 1812'

De RADIUS-server is misschien alleen de voorkant van de identiteitsprovider

Mensen praten over RADIUS en identiteitsprovider alsof het dezelfde doos is. Vaak niet. De RADIUS-server ontvangt de Access-Request en vraagt dan iets anders — Active Directory via LDAP of Kerberos, een lokaal gebruikersbestand of een externe dienst — voordat hij antwoordt. FreeRADIUS met de LDAP- of krb5-module, Windows NPS en Cisco ISE staan allemaal op deze plek.

Het verschil bepaalt waar je kijkt. Een geweigerd wachtwoord is een antwoord van de identiteitsprovider dat RADIUS doorgeeft. Een time-out is meestal het traject RADIUS-naar-directory: een verlopen bind-account, een onbereikbare directory of een verzoek dat naar de verkeerde backend is gerouteerd. Als de gebruikersnaam een domeinsuffix heeft, kan de server daarop routeren, en hetzelfde account verzonden als CORP\alice en [email protected] kan op verschillende plekken belanden. Op Windows NPS registreert het Security-log 6272 voor een toekenning en 6273 voor een weigering, wat zegt of de beslissing überhaupt van NPS kwam.

Lees de fout bij de hop die hem produceerde

Eén kan-niet-verbinden-bericht dekt vier verschillende fouten. Voordat je iets verandert, koppel je het symptoom aan de hop die het produceerde.

What you seeWhere it comes fromFirst check
Gateway timeout, no replyShared secret mismatch, UDP 1812 blocked, unknown NAS, wrong server addresstcpdump at the gateway; radtest from the gateway host
Immediate rejectCredentials, account state, domain suffix, RADIUS policyNPS 6273 or the FreeRADIUS auth log; test the account directly
Repeated challenge or MFA loopAccess-Challenge state not returned, or a token that expired mid-flowClient prompt timing and the State attribute in debug output
Accept, then no accessAuthorization attributes unmapped, wrong pool, route or ACL policyGateway policy and the attributes in the Access-Accept

De laatste rij is degene die mensen naar het verkeerde team stuurt. Access-Accept betekent dat de inloggegevens zijn geaccepteerd; het betekent niet dat de gateway de gebruiker in de juiste pool heeft geplaatst of routes heeft geduwd. Groepsattributen tellen alleen als het gatewaybeleid ze leest. Ik heb een correcte login in een gastpool zien belanden omdat de groepsmapping aan de RADIUS-kant was geconfigureerd voor een ander attribuut dan het attribuut dat de gateway inspecteert.

Volg één login van begin tot eind

Kies één testaccount en één gateway en bekijk dan dezelfde poging op alle vier de punten. Start een debug-run aan de RADIUS-kant — freeradius -X drukt het verzoek en elke module die het raakt af — volg het authenticatielog van de gateway en draai tcpdump voor de UDP-uitwisseling. Verbind één keer en lees de vier sporen op volgorde.

Wat je wilt zien is overeenstemming: de gateway vroeg naar de gebruiker die je verwachtte, de RADIUS-server koos de backend die je verwachtte, die backend gaf een beslissing terug, en de attributen in het antwoord passen bij het beleid dat de gateway toepast. De eerste plek waar de sporen niet overeenkomen, is je foutgrens. Als het antwoord geen groepsattribuut draagt, ligt het probleem aan de RADIUS-kant, niet in het VPN-profiel; als het attribuut er is en de gateway negeert het, is het gatewaybeleid het probleem.

Eén beveiligingsopmerking terwijl je daar bent. Het gedeelde geheim beschermt de uitwisseling, maar het versleutelt de meeste attributen niet. Als de gateway en de RADIUS-server in verschillende segmenten staan, leg die hop dan op RADIUS via TLS of een privépad. Een versleutelde gebruikerstunnel zegt niets over de backend-verbinding.

Voordat je het ticket sluit, bevestig je vier dingen. De gateway bereikt de RADIUS-server op de poort waarvoor hij werkelijk is geconfigureerd. Het gedeelde geheim komt aan beide kanten overeen. De RADIUS-server lost de exacte gebruikersnaamvorm op die de gateway stuurt. De accept draagt de attributen die het gatewaybeleid nodig heeft. Als alle vier kloppen, is een login die nog steeds mislukt een gatewaybeleidsprobleem, geen authenticatieprobleem.

Gerelateerde artikelen