# PBR Radio System

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

<table id="bkmrk-systemmototrbo-r7-%2F-"><tbody><tr><td>**System**</td><td>MOTOTRBO R7 / SCEPman / Aruba ClearPass</td></tr><tr><td>**CA**</td><td>PBR-ROOT-CA\_V1 (SCEPman, Azure App Service)</td></tr><tr><td>**Radio SCEP hostname**</td><td>pki-internal.pbr.org.au → Traefik proxy (10.1.8.55)</td></tr><tr><td>**Main PKI / OCSP hostname**</td><td>pki.pbr.org.au → Azure direct (untouched by proxy)</td></tr><tr><td>**Radio VLAN**</td><td>VLAN 40</td></tr><tr><td>**Status**</td><td>Working / verified end-to-end</td></tr></tbody></table>

---

## 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.au` continues 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. Enrolment is done **at the Kilvington Drive site**, which is the only site that broadcasts the staging SSID. The radio uses the `mototrbo` staging WLAN (WPA2-Personal, password in 1Password) to reach `pki-internal.pbr.org.au` and enrol on boot, then operates on the production `pbrb_radio` WLAN (WPA3-Enterprise, EAP-TLS) which broadcasts at all sites.

Set the following under **General → Wi-Fi Network → Wi-Fi Enterprise Certificates** (both the Common Certificate and Device Certificate entries):

<table id="bkmrk-scep-server-urlhttps"><tbody><tr><td>**SCEP Server URL**</td><td>`https://pki-internal.pbr.org.au/static`</td></tr><tr><td>**CA Identifier**</td><td>**Optional — leave blank.** Confirmed not required on enrolment (SCEPman is single-CA). May be set to `PBR-ROOT-CA_V1` but is not needed.</td></tr><tr><td>**Fingerprint (MD5)**</td><td>`3AF1978B9E4CC55B81C37B372AB2D3BA` (no separators)</td></tr><tr><td>**Common Name**</td><td>Per the CN convention below</td></tr><tr><td>**Challenge Password**</td><td>From 1Password (SCEPman static challenge) — not stored here</td></tr><tr><td>**Signature / Key**</td><td>SHA-256, RSA 2048</td></tr></tbody></table>

**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:

```bash
curl -s "https://pki-internal.pbr.org.au/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 `mototrbo` staging SSID at Kilvington. Confirm success: a `50`-prefixed issuance appears in SCEPman, and the radio operates on `pbrb_radio` (WPA3-Enterprise).

---

## WLAN / Wi-Fi site scoping

Two WLANs are involved, managed in Aruba Central:

<table id="bkmrk-ssidsecuritypurposeb"><thead><tr><th>SSID</th><th>Security</th><th>Purpose</th><th>Broadcast scope</th></tr></thead><tbody><tr><td>`pbrb_radio`</td><td>WPA3-Enterprise (EAP-TLS)</td><td>Production radio Wi-Fi</td><td>**All sites** (no zone)</td></tr><tr><td>`mototrbo`</td><td>WPA2-Personal (PSK)</td><td>Staging / SCEP enrolment only</td><td>**Kilvington Drive only** — Aruba Central zone `IT`. Password in 1Password.</td></tr></tbody></table>

**Aruba Central zone behaviour:** an SSID with no zone broadcasts on all APs in the group; an SSID with a zone broadcasts only on APs that carry the same zone; an AP with no zone broadcasts only the no-zone SSIDs. The `mototrbo` staging SSID is bound to zone `IT`, and only the Kilvington Drive APs carry that zone — so staging is confined to Kilvington while `pbrb_radio` (no zone) remains fleet-wide. *Note: zone `IT` currently means "the Kilvington Drive APs".*

---

## Certificate Common Name (CN) convention

The device certificate CN identifies the radio and, critically, marks it as a **radio device** so ClearPass can authorise it onto the radio VLAN without letting other PBR-CA certificates (DCs, servers, user certs) onto the same network.

Format:

```
<owner-or-role>-<radio-id>.radio.pbr.org.au
```

Example: `IT_Manager-1900.radio.pbr.org.au`

<table id="bkmrk-segmentexamplemeanin"><thead><tr><th>Segment</th><th>Example</th><th>Meaning</th></tr></thead><tbody><tr><td>`<owner-or-role>`</td><td>`IT_Manager`</td><td>The assigned owner or role for the radio.</td></tr><tr><td>`<radio-id>`</td><td>`1900`</td><td>The radio's **Radio ID** (the Radio ID column in Radio Management). Uniquely identifies the radio.</td></tr><tr><td>`.radio.pbr.org.au`</td><td>`.radio.pbr.org.au`</td><td>**The discriminator.** All radio certs carry this suffix; it is what ClearPass matches on to scope access to VLAN 40.</td></tr></tbody></table>

**Why it matters:** SCEPman issues certificates from the same CA (`PBR-ROOT-CA_V1`) for many device types. "Valid cert from our CA" alone is therefore *not* sufficient to authorise onto the radio network — a DC or server cert would also pass. ClearPass authorisation matches the `.radio.pbr.org.au` suffix in the CN so that only radios land on VLAN 40.

**Rule:** every radio device cert CN must end in `.radio.pbr.org.au`. The owner/role and device-id segments should be unique per radio for identification and traceability.

---

## Traefik configuration

Dynamic config on the Docker host (`pbr-docker-kl1`), file provider. Rule file location: `/docker/appdata/traefik3/rules/app-pki.yml`. **TCP passthrough** — Traefik routes on SNI and forwards raw TLS to Azure, never terminating.

```yaml
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.net` name (resolved dynamically) — do **not** hardcode the Azure IP (`13.70.72.33`); it can change.
- The Docker host resolves `app-scepman-cbys7lti43ukq.azurewebsites.net` publicly; `pki-internal.pbr.org.au` resolves (internally) to the proxy — no loop.
- A YAML parse error in the rules file does **not** take the router down — Traefik keeps the last valid config and only logs the error. Always validate the file and check the log for `did not find expected key` after editing.

---

## 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_V1` into 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 with `unknown_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 suffix `.radio.pbr.org.au` (see CN convention above) 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 `pki.pbr.org.au` / `azurewebsites.net` endpoint), 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

<table id="bkmrk-symptommeaning-%2F-fix"><thead><tr><th>Symptom</th><th>Meaning / Fix</th></tr></thead><tbody><tr><td>Radio resolves SCEP host, no SYN to it (Palo log)</td><td>R7 won't connect to a public IP — must use the internal passthrough proxy (private IP).</td></tr><tr><td>Connects to private IP but not public</td><td>Confirms the public-IP limitation; the proxy is the fix.</td></tr><tr><td>"enrol failed" / "invalid cert" after GetCACert succeeds</td><td>Fingerprint mismatch. Re-derive MD5 from the live GetCACert response (not a cert store) and re-push.</td></tr><tr><td>`tls: no renegotiation` (Traefik upstream)</td><td>Caused by L7 termination + Azure client-cert mode "Optional Interactive User". Use TCP passthrough (canonical config) — it avoids the problem entirely.</td></tr><tr><td>Traefik 500, `0ms`, `unsupported protocol scheme ""`</td><td>Config didn't load — YAML parse error keeps the *previous* config. Check logs for `did not find expected key`; validate YAML; check provider-namespace refs (`@docker`/`@file`).</td></tr><tr><td>EAP-TLS `fatal alert by client - unknown_ca`</td><td>Radio rejects ClearPass's RADIUS cert. Issue the ClearPass EAP server cert from PBR-ROOT-CA\_V1.</td></tr><tr><td>EAP-TLS `parse_http_line1 ... OCSP` / no OCSP response</td><td>ClearPass OCSP hitting the passthrough proxy (or Azure host-header issue). Point ClearPass OCSP override directly at Azure on `pki.pbr.org.au`.</td></tr><tr><td>OCSP `Certificate Status revoked, Reason superseded`</td><td>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.)</td></tr></tbody></table>

**Useful SCEPman log query** (Log Analytics) — static SCEP issuances, filtering out OCSP noise:

```kql
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.
- **CN convention:** every radio device cert CN must end in `.radio.pbr.org.au` or ClearPass will not authorise it onto VLAN 40.
- **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.au` direct-to-Azure (PKI + OCSP) and `pki-internal.pbr.org.au` → proxy (radio SCEP). Do not point `pki.pbr.org.au` at the proxy — it breaks OCSP.

# RM Programming — Over-Wi-Fi Across Sites/Subnets

## Overview

Programming MOTOTRBO R7 radios and repeaters over Wi-Fi with Radio Management (RM), across sites and subnets. RM Server / Device Programmer runs on **pbr-radio-kl1 (10.8.40.10)**, RM version 2.157.149.0.

Out of the box, RM Wi-Fi programming only works when the radio and the Device Programmer are on the same subnet, because discovery uses mDNS multicast (224.0.0.251:5353) which doesn't route. Four changes were needed to make it work across sites — all four are required.

---

## The Four Fixes

### 1. Disable Windows mDNS on the RM server (registry — most important)

Windows' Dnscache service binds UDP 5353 and silently consumes the radios' incoming discovery announcements — the Motorola Device Programmer never receives them. Radios show *Waiting For Device* forever with no error.

```powershell
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters" `
  -Name EnableMDNS -Value 0 -PropertyType DWord -Force
# Then REBOOT the server
```

Verify after reboot — the Motorola DP process (not svchost) must own the port:

```powershell
Get-NetUDPEndpoint -LocalPort 5353 | Select LocalAddress,OwningProcess
```

### 2. Set Device Discovery Server Name in the radio codeplug

CPS → Wi-Fi → per network profile: set **Device Discovery Server Name** to `pbr-radio-kl1` (or 10.8.40.10). This makes the radio send its discovery announcement unicast to the server (routable) instead of local multicast. Set it on **every** Wi-Fi profile the radio uses. DNS-SD port 5353, interval 90 sec.

### 3. RM Machine Authorization

RM Server Utility → Machine Authorization: the machine running the Device Programmer (including the RM server itself) must be listed with the **Programmer** permission ticked. Without it, connections fail with the generic "Failed to connect to the RM server" dialog and jobs never dispatch.

### 4. Use 10.8.40.10, not localhost

In the RM config, Job Processor and Device Monitor/DP settings, set the RM Server address to `10.8.40.10` — not localhost. With localhost, cross-site writes fail with **Error 450** ("connection could not be established with the selected connection type") while local writes still work.

---

## Quick Troubleshooting

<table id="bkmrk-symptomcheck-waiting"><thead><tr><th>Symptom</th><th>Check</th></tr></thead><tbody><tr><td>Waiting For Device forever, cross-site</td><td>Fix 1 — who owns UDP 5353? Windows updates/rebuilds can re-enable mDNS</td></tr><tr><td>Cross-site radio never discovered at all</td><td>Fix 2 — Device Discovery Server Name missing on the active Wi-Fi profile</td></tr><tr><td>"Failed to connect to RM server" dialog</td><td>Fix 3 — Machine Authorization</td></tr><tr><td>Error 450 on cross-site writes only</td><td>Fix 4 — localhost addressing</td></tr></tbody></table>

## Ports

**UDP 5353** (radio → server, discovery) · **TCP 443** (RM server/clients) · **TCP 8002-8003** (DP → radio, programming session) · **TCP 50000-50100 / UDP 20000** (IP Program, repeaters). Traffic currently rides the Palo Alto intrazone-default allow — add explicit rules if radio VLANs move to their own zone.

## Notes

- If this breaks after a Windows update or server rebuild, check the EnableMDNS registry value first.
- If the server IP changes, update it in both the radio codeplugs (Fix 2) and RM component settings (Fix 4).