The UDM RADIUS rejects the pod CIDR as an unknown client; it accepts
10.2.11.0/24. FreeRADIUS pods get net1 on VLAN 11 "(11) RADIUS" and the
udm home server moves to 10.2.11.1.
- Talos k8s-{1,2,3}: VLANConfig radius0 (VLAN 11 on uplink), no
addresses, IPv6 disabled on the host link.
- Cilium bpf.vlanBypass gains 11: radius0 is address-less like ens19, so
its tagged frames meet the VLAN filter on uplink (#592).
- NAD freeradius-udm: macvlan on radius0, DHCP IPAM requesting only
subnet-mask (skipDefault), so the lease has no router and net1 holds
only the connected /24. No sbr: it moves that route into a source
table, and the unbound proxy socket would then reach the UDM via eth0
from the pod IP. tuning disables IPv6 on net1 (VLAN 11 sends RAs).
- NAS listeners bound to eth0, so nothing listens on net1.
- CNP freeradius-udm-egress removed: net1 traffic bypasses Cilium.
- Harness: FreeRADIUS interfaces named eth0/net1 explicitly; Docker
attaches networks in no fixed order, and the eth0 bind exposed it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FreeRADIUS functional test
tests/radius/run.sh
Runs the production FreeRADIUS config from
kubernetes/apps/authentik/freeradius-config.yaml (rendered through the
projected volume in freeradius.yaml, same image, args and secret env names)
in Docker against a mock authentik outpost and a mock UDM RADIUS, and drives
it with eapol_test (EAP-TTLS, inner PAP) as a NAS in the test client ranges
10.2.50.0/24 and fd02:50::/64. The v6 cases (v6-*) hit the IPv6
listeners and client test6. Cases use outer identity anonymous unless
noted.
| Case | Expected |
|---|---|
vlan-tunnel (outpost sends Tunnel-* and Cisco-AV-Pair) |
SUCCESS, Tunnel-* VLAN 50, no Cisco-AV-Pair |
vlan-avpair (outpost sends only Cisco-AV-Pair = "dot1x-vlan=50") |
SUCCESS, Tunnel-* VLAN 50, no Cisco-AV-Pair |
novlan (Accept without VLAN) |
FAILURE (Access-Reject) |
| wrong password / unknown user (Reject without Message-Authenticator) | FAILURE (Access-Reject) within 1 s |
| Accounting-Request | answered locally, nothing sent to the outpost or the UDM |
anon-realm (outer identity Anonymous@Example.Org) |
local TTLS, as vlan-tunnel |
udm-accept, v6-udm-accept (outer identity = account name) |
both EAP rounds reach the mock UDM (second with its State); its Access-Accept reaches the NAS with Tunnel-* VLAN 200 and MS-MPPE keys unchanged |
udm-reject |
the mock UDM's Access-Reject reaches the NAS within 1 s |
all anonymous cases |
never reach the mock UDM |
recovery |
outpost stalls until marked dead, then returns: login succeeds within 20 s |
Pieces:
mock_outpost.py: stand-in outpost on UDP 1812, reachable under the outpost Service FQDN through a Docker network alias.mock_udm.py: stand-in UDM RADIUS at theudmhome server address fromproxy.conf(10.2.11.1), on a second internal bridgeradtest-udm(that address's /24, no host address). FreeRADIUS gets a second interface there, asnet1in the pod: only the connected /24, no default route, and the proxy socket picks it by route lookup. The macvlan/DHCP attachment itself is not tested. Answers round 1 with Challenge +State+ EAP-TTLS Start (or Reject forendpoint-reject), round 2 with Accept + EAP-Success; terminates no EAP.eapol.Dockerfile:eapol_testfrom Debianeapoltest.- Docker network
radtest: internal bridge on10.2.50.0/24andfd02:50::/64with no host address (inhibit_ipv4,gateway_mode_ipv6=isolated), so the workstation LAN routes are untouched.
Requires Docker, openssl and yq (the jq wrapper). Secrets, password and
certificates are generated dummies. RADTEST_DEBUG=1 runs radiusd with -xx
and prints all logs. Containers, network and temp files are removed on exit.
live.sh logs in against the deployed FreeRADIUS instead; usage in
docs/radius/dot1x.md ("Live login check").