Last week a user could sign in to the VPN and still land on a network where nothing resolved. The client said connected, the gateway log said Access-Accept, and the identity team said the account was fine. The login had worked; the authorization behind it had not. When a VPN sign-in fails, I walk the path the request actually takes — client, gateway, RADIUS server, identity provider — and stop at the first hop whose answer disagrees with the next one.

The client never speaks RADIUS

Whatever the app on the laptop shows, its first hop is the VPN protocol: IKEv2, OpenVPN, WireGuard, or a TLS-based client. RADIUS does not appear in that exchange. The client authenticates to the gateway with a certificate, a username and password, or an EAP method carried inside the tunnel setup.

That matters when you read logs, because the generic authentication error the user sees is produced by the gateway after it has already talked to something else. If the client never reaches the gateway, no RADIUS request exists to debug, and an hour spent on the RADIUS server is wasted. Confirm the tunnel came up at all before you touch the backend.

The gateway is the RADIUS client

Once tunnel setup reaches the point where credentials must be checked, the gateway becomes a network access server. It builds an Access-Request: User-Name, a password or EAP payload, NAS-IP-Address or NAS-Identifier, and a Message-Authenticator when the method calls for one. The request goes to UDP 1812 by default, and accounting to 1813. Older deployments still use 1645 and 1646, so a firewall rule written for one pair explains a lot of silent failures.

Both sides share a secret, and it is not a user credential. It signs the exchange, and every reply is verified against it. Configure the secret differently on the two sides and the server does not answer with bad secret — it drops the request or the reply fails verification, so the gateway reports a timeout. A wrong secret and a dead server look identical from the gateway, which is why I test the hop with a client tool before blaming the directory.

The protocol is small and old — RFC 2865 defines the authentication exchange — but the attributes it carries are what most VPN policy is built on.

# 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'

The RADIUS server may only front the identity provider

People say RADIUS and identity provider as if they were the same box. Often they are not. The RADIUS server receives the Access-Request and then asks something else — Active Directory over LDAP or Kerberos, a local user file, or an external service — before it answers. FreeRADIUS with the LDAP or krb5 module, Windows NPS, and Cisco ISE all sit in this position.

The distinction decides where you look. A rejected password is an identity-provider answer relayed by RADIUS. A timeout is usually the RADIUS-to-directory leg: an expired bind account, an unreachable directory, or a request routed to the wrong backend. If the user name carries a domain suffix, the server may route on it, and the same account sent as CORP\alice and [email protected] can land in different places. On Windows NPS, the Security log records 6272 for a grant and 6273 for a denial, which tells you whether the decision came from NPS at all.

Read the failure at the hop that produced it

One cannot-connect message covers four different failures. Before changing anything, match the symptom to the hop that produced it.

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

The last row is the one that sends people to the wrong team. Access-Accept means the credentials were accepted; it does not mean the gateway has placed the user on the right pool or pushed routes. Group attributes matter only if gateway policy reads them. I have seen a correct login land in a guest pool because the group mapping was configured on the RADIUS side for a different attribute than the one the gateway inspects.

Follow one login end to end

Pick a single test account and one gateway, then watch the same attempt at all four points. Start a debug run on the RADIUS side — freeradius -X prints the request and every module it touches — tail the gateway auth log, and run tcpdump for the UDP exchange. Connect once and read the four traces in order.

What you want to see is agreement: the gateway asked about the user you expected, the RADIUS server chose the backend you expected, that backend returned a decision, and the attributes in the reply match the policy the gateway applies. The first place the traces disagree is your fault line. If the reply carries no group attribute, the problem is on the RADIUS side, not in the VPN profile; if the attribute is there and the gateway ignores it, the gateway policy is the problem.

One security note while you are in there. The shared secret protects the exchange, but it does not encrypt most attributes. If the gateway and the RADIUS server sit on different segments, put that hop on RADIUS over TLS or a private path. An encrypted user tunnel says nothing about the backend link.

Before you close the ticket, confirm four things. The gateway can reach the RADIUS server on the port it is actually configured for. The shared secret matches on both sides. The RADIUS server resolves the exact user-name form the gateway sends. The accept carries the attributes the gateway policy needs. When all four hold, a login that still fails is a gateway policy problem, not an authentication one.

Nuŋlɔɖi siwo ku ɖe eŋu