|
|
# Hotspot proxy (integrated)
|
|
|
|
|
|
**ADN DMR Peer Server** includes an **integrated hotspot proxy**: one process (`adn-server.py`) accepts Homebrew (HBP) from many hotspots on a single UDP port and **injects** traffic into a configured **MASTER** system. You do **not** need a separate **`adn-proxy`** process when this mode is enabled.
|
|
|
|
|
|
Configuration lives in **`adn-server.yaml`** under **`PROXY`** and optional **`SELF_SERVICE`** (same MySQL **`Clients`** table as **adn-monitor**).
|
|
|
|
|
|
---
|
|
|
|
|
|
## When to use it
|
|
|
|
|
|
| Deployment | What to run |
|
|
|
|------------|-------------|
|
|
|
| **Typical ADN stack** (monitor + dashboard + many Pi-Star hotspots) | **`adn-server.py`** with **`PROXY`** + **`SELF_SERVICE`**. |
|
|
|
|
|
|
The integrated proxy uses **fan-in**: hotspots only need **`PROXY.LISTEN_PORT`** (e.g. **62031**). The target **MASTER** is **inject-only** — it does **not** bind its own UDP port for that system (no per-hotspot port range on the server host).
|
|
|
|
|
|
```mermaid
|
|
|
flowchart LR
|
|
|
HS1[Hotspot A] -->|UDP HBP| LP[PROXY LISTEN_PORT]
|
|
|
HS2[Hotspot B] -->|UDP HBP| LP
|
|
|
LP -->|inject| MASTER[TARGET_SYSTEM MASTER]
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## Optional dependency (self-service)
|
|
|
|
|
|
MySQL self-service requires **`mysqlclient`**:
|
|
|
|
|
|
```bash
|
|
|
pip install -e ".[selfservice]"
|
|
|
```
|
|
|
|
|
|
If **`USE_SELFSERVICE: true`** but **`mysqlclient`** is missing, startup fails with a clear error. Set **`USE_SELFSERVICE: false`** to run the proxy without DB (no dashboard-driven **RPTO** updates).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `PROXY` keys
|
|
|
|
|
|
| Key | Role |
|
|
|
|-----|------|
|
|
|
| **LISTEN_PORT** | UDP port where **hotspots** connect (the address users configure on the hotspot). |
|
|
|
| **LISTEN_IP** | Bind address; empty = all interfaces. |
|
|
|
| **TARGET_SYSTEM** | Name of the **`SYSTEMS`** **MASTER** entry that receives injected HBP (must exist and be **ENABLED**). |
|
|
|
| **TIMEOUT** | Idle session timeout (seconds); expired sessions are torn down on the MASTER. |
|
|
|
| **DEBUG** | Verbose packet logging. |
|
|
|
| **CLIENT_INFO** | Log connect/disconnect per radio ID. |
|
|
|
| **BLACK_LIST** | Block listed radio IDs. |
|
|
|
| **IP_BLACK_LIST** | Block source IPs (with optional expiry). |
|
|
|
|
|
|
There is **no** **`MASTER`**, **`PORT`**, or **`GENERATOR`** in integrated **`PROXY`** — those belong to the legacy standalone proxy. The target MASTER uses **`MAX_PEERS`** (not a UDP port range) to cap concurrent hotspot sessions.
|
|
|
|
|
|
Example (from `adn-server.example.yaml`):
|
|
|
|
|
|
```yaml
|
|
|
PROXY:
|
|
|
LISTEN_PORT: 62031
|
|
|
LISTEN_IP: ""
|
|
|
TARGET_SYSTEM: SYSTEM
|
|
|
TIMEOUT: 30
|
|
|
DEBUG: false
|
|
|
CLIENT_INFO: true
|
|
|
BLACK_LIST: []
|
|
|
IP_BLACK_LIST: {}
|
|
|
```
|
|
|
|
|
|
### Inject-only target MASTER
|
|
|
|
|
|
When **`PROXY.TARGET_SYSTEM`** points at a system (e.g. **`SYSTEM`**), startup **removes** **`IP`** / **`PORT`** from that MASTER block. Hotspots never connect directly to the conference port; all HBP enters via **`LISTEN_PORT`**.
|
|
|
|
|
|
Set **`MAX_PEERS`** on the target MASTER to the maximum concurrent proxied hotspots (e.g. **102**). Other MASTER systems (e.g. **ECHO**, **D-APRS**) keep normal **`IP`** / **`PORT`** binds if they are not the proxy target.
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SELF_SERVICE` keys
|
|
|
|
|
|
Same semantics as **`adn-monitor.yaml`** — shared **`Clients`** table, **`modified`** flag, **RPTO** toward the MASTER.
|
|
|
|
|
|
| Key | Role |
|
|
|
|-----|------|
|
|
|
| **USE_SELFSERVICE** | Enable MySQL-backed options sync (`true` / `false`). |
|
|
|
| **PBKDF2_SALT**, **PBKDF2_ITERATIONS** | Must **match** monitor/backend for password hashing. |
|
|
|
|
|
|
MariaDB connection settings live in the top-level **`DATABASE`** block (shared with dynamic TG persistence) — see [Configuration](configuration.md#database-mariadb).
|
|
|
|
|
|
On startup the server logs **`(SELF_SERVICE) Database connection test: OK`** and **`(SELF_SERVICE) Enabled`** when the pool connects. Self-service runs **asynchronously**; voice forwarding is not blocked on DB latency.
|
|
|
|
|
|
Details of the dashboard flow: [Self-service](../../monitor/self-service.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## Multi-hotspot behaviour
|
|
|
|
|
|
- Each authenticated hotspot is a **peer** on the inject-only MASTER with its own **OPTIONS** (static TGs). **Repeat** and monitor fan-out respect **per-peer OPTIONS** — traffic for a TG is not sent to peers that did not select it.
|
|
|
- **Parrot / echo** talkgroups **9990–9999** are **point-to-point**: they bypass the OPTIONS filter and return **only** to the exact peer that originated the call (`RX_PEER` on the slot), never to other hotspots of the same user. With a single connected peer, it is delivered to that peer (legacy behaviour). See [Echo — Multi-hotspot behaviour](echo.md#multi-hotspot-behaviour-inject-only-proxy) and [Special numbers](special-numbers.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## OPTIONS line behaviour
|
|
|
|
|
|
After login (RPTL → RPTK → RPTC), the proxy starts a **10 s timer** waiting for
|
|
|
the hotspot's **RPTO** packet with its **OPTIONS** line. What the hotspot sends
|
|
|
(or does not send) determines **who is the source of truth** for the peer's
|
|
|
static talkgroups:
|
|
|
|
|
|
| Hotspot sends in the RPTO | Who defines the TGs | Behaviour |
|
|
|
|---|---|---|
|
|
|
| `OPTIONS=PASS=xxxxxx;` | **Self-service** (dashboard) | The proxy processes the `PASS=`, verifies the individual password (PBKDF2 against `Clients.psswd`), marks the peer as authenticated, cancels the 10 s timer, and pushes the DB-configured TGs to the master. The user **can** log in by password and auto-login by IP on the dashboard. |
|
|
|
| `OPTIONS=` (empty) | **Self-service** (dashboard) | The proxy reads the TGs from the DB and injects them to the master. The user can **only** use auto-login by IP on the dashboard (no password). |
|
|
|
| **No RPTO at all** (10 s timer expires) | **Self-service** (dashboard) | The proxy assumes the hotspot has no OPTIONS of its own and falls back to the DB. Same effect as `OPTIONS=` empty. |
|
|
|
| `OPTIONS=TS2=730444;SINGLE=0;` (content without `PASS=`) | **The hotspot itself** | The master takes the TGs **directly from the OPTIONS line**. The DB is ignored. The user can **only** use auto-login by IP on the dashboard (no password). |
|
|
|
|
|
|
**Key rule:** self-service is the source of truth **unless** the hotspot sends
|
|
|
explicit content (TGs, SINGLE, TIMER, etc.) in its OPTIONS line. In that case,
|
|
|
what the hotspot says **takes precedence** and self-service is ignored.
|
|
|
|
|
|
### Individual password and dashboard login
|
|
|
|
|
|
- If the hotspot **never** sends `PASS=` in its RPTO, the user **cannot** log in
|
|
|
to the dashboard with a password. They can only use **auto-login by IP**
|
|
|
(if their IP matches `Clients.host`).
|
|
|
- To enable password login on the dashboard, the hotspot must send
|
|
|
`OPTIONS=PASS=your_password;` in its configuration (Pi-Star / WPSD / MMDVM
|
|
|
`optsfile`). The password must match the PBKDF2 hash stored in `Clients.psswd`.
|
|
|
- The `PASS=` flow is what activates bidirectional sync: the proxy stores the
|
|
|
hash, notes the `modified` flag, and pushes the DB-configured TGs to the master.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Hot reload (`SIGHUP`)
|
|
|
|
|
|
**Applied without restart** (active proxy sessions stay up):
|
|
|
|
|
|
- **`PROXY`:** **TIMEOUT**, **DEBUG**, **CLIENT_INFO**, **BLACK_LIST**, **IP_BLACK_LIST**
|
|
|
- **`SELF_SERVICE`:** merged into config (credential changes take effect on new DB operations; loops are not restarted on reload)
|
|
|
|
|
|
**Requires full process restart:**
|
|
|
|
|
|
- **`PROXY.LISTEN_PORT`** / **`LISTEN_IP`** (bind change is logged and ignored at reload)
|
|
|
- **`PROXY.TARGET_SYSTEM`**
|
|
|
- Enabling or disabling **`USE_SELFSERVICE`** after startup (start/stop MySQL loops)
|
|
|
|
|
|
See [Configuration — hot reload](configuration.md#hot-reload-adn-serveryaml).
|
|
|
|
|
|
---
|
|
|
|
|
|
## See also
|
|
|
|
|
|
- [Configuration](configuration.md) — full **`adn-server.yaml`** reference.
|
|
|
- [Monitoring and reports](monitoring.md) — TCP reports, dashboard, log rotation.
|
|
|
- [Self-service](../../monitor/self-service.md) — **`Clients`**, **RPTO** timing.
|