MOTOTRBO R7 — SCEPman EAP-TLS Enrolment
Overview
How Motorola MOTOTRBO R7 portable radios obtain a device certificate from SCEPman (via SCEP) and authenticate to the WPA3-Enterprise Wi-Fi using EAP-TLS, validated by Aruba ClearPass. SCEPman is Azure-hosted; the radios reach it through an internal Traefik reverse proxy because the R7 SCEP client will not connect to the public Azure endpoint directly.
| System | MOTOTRBO R7 / SCEPman / Aruba ClearPass |
| CA | PBR-ROOT-CA_V1 (SCEPman, Azure App Service) |
| Radio SCEP hostname | pki-internal.pbr.org.au → Traefik proxy (10.1.8.55) |
| Main PKI / OCSP hostname | pki.pbr.org.au → Azure direct (untouched by proxy) |
| Radio VLAN | VLAN 40 |
| Status | Working / verified end-to-end |
Why the proxy exists
The R7 SCEP client resolves the SCEP host but will not open a TCP connection to a public IP (it connects fine to private/RFC1918 addresses). It also expects a transport it trusts and cannot tolerate the TLS renegotiation Azure App Service triggers under L7 termination. The working solution is a TCP/TLS passthrough proxy on a private IP:
- The radio connects to
pki-internal.pbr.org.au(private IP, the proxy). - Traefik forwards the raw TLS stream by SNI to the Azure App Service — it does not terminate TLS, so there is no Go/Traefik renegotiation failure and no transport-cert substitution. The radio completes TLS end-to-end with Azure's real certificate (which it trusts).
- A separate hostname keeps the radio path isolated:
pki.pbr.org.aucontinues to resolve directly to Azure for normal PKI and OCSP, so nothing else is affected.
Azure App Service client-certificate mode stays "Optional Interactive User" (SCEPman's required setting). Passthrough does not have the renegotiation problem that L7 termination did, so this setting does not need changing.
Enrolment runbook (per radio)
Performed in Radio Management. The radio uses a staging WPA2-Personal SSID (with routable access to pki-internal.pbr.org.au) to enrol on boot, then cuts over to WPA3-Enterprise.
Set the following under General → Wi-Fi Network → Wi-Fi Enterprise Certificates (both the Common Certificate and Device Certificate entries):
| SCEP Server URL | https://pki-internal.pbr.org.au/static |
| CA Identifier | PBR-ROOT-CA_V1 |
| Fingerprint (MD5) | 3AF1978B9E4CC55B81C37B372AB2D3BA (no separators) |
| Challenge Password | From 1Password (SCEPman static challenge) — not stored here |
| Signature / Key | SHA-256, RSA 2048 |
Critical: the fingerprint must be the MD5 of the CA cert as returned by the live GetCACert response, not a copy from a local cert store — they can differ and a mismatch causes the radio to reject the CA ("enrol failed" / "invalid cert"). Derive it with:
curl -s "http://pki-internal.pbr.org.au:8081/static?operation=GetCACert" -o ca.bin
openssl x509 -inform DER -in ca.bin -noout -fingerprint -md5
After setting the fields, push the codeplug to the radio (confirm the push completes), then enrol over the staging SSID. Confirm success: a 50-prefixed issuance appears in SCEPman, and the radio cuts to WPA3-Enterprise.
Traefik configuration
Dynamic config on the Docker host (pbr-docker-kl1), file provider. TCP passthrough is the canonical/working config — Traefik routes on SNI and forwards raw TLS to Azure.
tcp:
routers:
pki-tcp-rtr:
rule: "HostSNI(`pki-internal.pbr.org.au`)"
entryPoints:
- websecure-internal
tls:
passthrough: true
service: pki-tcp-svc
services:
pki-tcp-svc:
loadBalancer:
servers:
- address: "app-scepman-cbys7lti43ukq.azurewebsites.net:443"
Notes:
- The radio's SNI must match the Azure-bound hostname so App Service routes correctly. The radio sends SNI = the host in its SCEP URL.
- The upstream uses the
azurewebsites.netname (resolved dynamically) — do not hardcode the Azure IP (13.70.72.33); it can change. - The Docker host resolves
app-scepman-cbys7lti43ukq.azurewebsites.netpublicly;pki-internal.pbr.org.auresolves (internally) to the proxy — no loop.
Diagnostic-only L7 / plain-HTTP variant. A plain-HTTP endpoint on :8081 was used during troubleshooting (handy for curling GetCACert and checking the SCEP exchange in the clear). It requires Azure client-cert mode = "Optional" to avoid the renegotiation failure, so it is not used in production. Kept here for reference only:
http:
routers:
pki-http-rtr:
rule: "Host(`pki-internal.pbr.org.au`) && PathPrefix(`/static`)"
entryPoints:
- scep-http # plain :8081 entrypoint, no HTTP->HTTPS redirect
service: pki-svc
services:
pki-svc:
loadBalancer:
passHostHeader: false
servers:
- url: "https://app-scepman-cbys7lti43ukq.azurewebsites.net"
serversTransport: scep-azure
serversTransports:
scep-azure:
serverName: "app-scepman-cbys7lti43ukq.azurewebsites.net"
ClearPass EAP-TLS
EAP-TLS is mutual — both certificates must chain to a CA the other side trusts.
- Trust the CA: import
PBR-ROOT-CA_V1into ClearPass (Administration → Certificates → Trust List), enabled for EAP. This validates the radio device certs. - RADIUS / EAP server cert: must be issued from
PBR-ROOT-CA_V1(via SCEPman Certificate Master, CSR signed) so the radio trusts ClearPass back. A server cert from any other CA causes the radio to reject the handshake withunknown_ca. Generate the CSR on ClearPass, sign in Certificate Master as a serverAuth cert, install with the full chain. - Authorisation: match the radio device-cert CN pattern (contains
radio.pbr.org.au) so only radios — not other PBR-CA certs (DCs, servers) — land on the radio VLAN. - Enforcement: radio role → return RADIUS tunnel attributes for VLAN 40.
- OCSP: revocation checking enforced. ClearPass OCSP override URL points directly at Azure (the
azurewebsites.net/pki.pbr.org.auendpoint), bypassing the proxy. Do not route OCSP through the passthrough proxy — passthrough has no HTTP path handling, and ClearPass's OCSP requests would be intercepted and dropped.
Troubleshooting reference
| Symptom | Meaning / Fix |
|---|---|
| Radio resolves SCEP host, no SYN to it (Palo log) | R7 won't connect to a public IP — must use the internal passthrough proxy (private IP). |
| Connects to private IP but not public | Confirms the public-IP limitation; the proxy is the fix. |
| "enrol failed" / "invalid cert" after GetCACert succeeds | Fingerprint mismatch. Re-derive MD5 from the live GetCACert response (not a cert store) and re-push. |
tls: no renegotiation (Traefik upstream) | L7 termination + Azure client-cert mode "Optional Interactive User". Use TCP passthrough instead (canonical config). |
Traefik 500, 0ms, unsupported protocol scheme "" | Config didn't load — YAML parse error keeps the previous config. Check logs for did not find expected key; validate YAML; provider-namespace refs (@docker/@file). |
EAP-TLS fatal alert by client - unknown_ca | Radio rejects ClearPass's RADIUS cert. Issue the ClearPass EAP server cert from PBR-ROOT-CA_V1. |
EAP-TLS parse_http_line1 ... OCSP / no OCSP response | ClearPass OCSP hitting the passthrough proxy (or Azure host-header issue). Point ClearPass OCSP override directly at Azure on pki.pbr.org.au. |
OCSP Certificate Status revoked, Reason superseded | Radio is using an old cert that a re-enrolment superseded. Re-enrol cleanly so it holds the current cert. (Also confirms OCSP enforcement works.) |
Useful SCEPman log query (Log Analytics) — static SCEP issuances, filtering out OCSP noise:
SCEPman_CL
| where TimeGenerated > ago(30d)
| where RequestUrl has "/static"
| order by TimeGenerated desc
Maintenance notes
- Cert renewal: radios have Renew Strategy = Renew. Verify renewal works through the passthrough path before the first certs expire.
- Fingerprint: if the SCEPman Root CA is ever rotated, re-derive the MD5 from GetCACert and update every radio codeplug.
- Azure IP: the proxy upstream uses the azurewebsites hostname, so an Azure front-end IP change is handled automatically. Do not pin the IP anywhere.
- Hostname separation: keep
pki.pbr.org.audirect-to-Azure (PKI + OCSP) andpki-internal.pbr.org.au→ proxy (radio SCEP). Do not pointpki.pbr.org.auat the proxy — it breaks OCSP.