108 lines
6.3 KiB
Markdown
108 lines
6.3 KiB
Markdown
# checker-stun-turn
|
|
|
|
happyDomain checker that probes **STUN** and **TURN** servers end-to-end:
|
|
DNS / SRV discovery, TCP/UDP reachability, TLS / DTLS handshake, STUN binding,
|
|
open-relay check, authenticated TURN Allocate (long-term creds *or*
|
|
REST API shared secret), relay address sanity, and a `CreatePermission + Send`
|
|
round-trip through the relay.
|
|
|
|
Backed by [`github.com/pion/stun`](https://github.com/pion/stun) +
|
|
[`github.com/pion/turn`](https://github.com/pion/turn).
|
|
|
|
## Tests performed per endpoint
|
|
|
|
| Test | What it proves |
|
|
|-----------------------------|----------------|
|
|
| `dial:<transport>` | DNS resolves, port is reachable, TLS/DTLS handshake succeeds. |
|
|
| `tls` / `dtls` | Records TLS version + cipher + peer cert CN. |
|
|
| `stun_binding` | Server answers RFC 5389 Binding Request; measures RTT. |
|
|
| `stun_reflexive_public` | Server returned a *public* XOR-MAPPED address (not RFC1918). |
|
|
| `turn_open_relay_check` | Unauthenticated Allocate is rejected with 401 + REALM/NONCE. |
|
|
| `turn_allocate_auth` | Authenticated Allocate succeeds; relay address returned. |
|
|
| `turn_relay_public` | Relay address is publicly routable. |
|
|
| `turn_relay_echo` | CreatePermission + Send to the probe peer succeed. |
|
|
| `turn_channel_bind` | (optional) ChannelBind exercised via the relay conn. |
|
|
|
|
## Most common failures surfaced with a fix
|
|
|
|
Each failing sub-test carries a `Fix` field that is rendered prominently in the
|
|
HTML report (yellow callout at the top of the card *and* inline with each row).
|
|
Mapping:
|
|
|
|
- UDP/TCP dial timeouts → firewall/NAT guidance
|
|
- TLS handshake errors → certificate reissue guidance (coturn `cert=`/`pkey=`)
|
|
- STUN binding returns RFC1918 → `external-ip=` for coturn
|
|
- Unauthenticated Allocate accepted → enable `lt-cred-mech`, close the open relay
|
|
- Allocate 401 loop → check NTP (TURN nonces are time-sensitive)
|
|
- Allocate 441 → wrong username/password or wrong REST shared secret
|
|
- Allocate 442 → try different transport or enable it server-side
|
|
- Allocate 486/508 → quota / port-range issues on the server
|
|
- Relay address is private → set `relay-ip=` to a public IP
|
|
- Relay echo fails → `min-port`/`max-port` range not publicly reachable
|
|
|
|
## Rules
|
|
|
|
| Code | Description | Severity |
|
|
|-------------------------------|---------------------------------------------------------------------------------------------------|---------------------|
|
|
| `stun_turn.discovery` | Verifies that at least one STUN/TURN endpoint could be discovered (explicit URI or SRV lookup). | CRITICAL |
|
|
| `stun_turn.srv_stun` | Verifies that at least one STUN endpoint is reachable via SRV (_stun/_stuns) or an explicit URI. | WARNING |
|
|
| `stun_turn.srv_turn` | Verifies that at least one TURN endpoint is reachable via SRV (_turn/_turns) or an explicit URI. | CRITICAL |
|
|
| `stun_turn.dial` | Verifies that every discovered endpoint accepts a connection (TCP/TLS handshake or UDP socket). | CRITICAL |
|
|
| `stun_turn.tls_transport` | Verifies that at least one TLS/DTLS transport (stuns/turns) succeeds when present. | CRITICAL |
|
|
| `stun_turn.ipv6_coverage` | Verifies at least one STUN/TURN hostname resolves to an IPv6 address. | WARNING |
|
|
| `stun_turn.stun_binding` | Verifies that the STUN Binding request receives a XOR-MAPPED-ADDRESS reply. | CRITICAL |
|
|
| `stun_turn.reflexive_public` | Flags endpoints that return a private/loopback reflexive address (server unaware of its public IP). | CRITICAL |
|
|
| `stun_turn.stun_latency` | Compares the STUN Binding RTT against the configured warning/critical thresholds. | CRITICAL |
|
|
| `stun_turn.turn_open_relay` | Verifies the TURN server requires authentication (challenges unauthenticated Allocate with 401). | CRITICAL |
|
|
| `stun_turn.turn_auth` | Verifies the supplied TURN credentials (or REST shared secret) yield a successful Allocate. | CRITICAL |
|
|
| `stun_turn.relay_public` | Flags TURN servers whose allocated relay address is private/loopback (missing public relay-ip). | CRITICAL |
|
|
| `stun_turn.relay_echo` | Verifies the TURN relay path can carry traffic to the configured probe peer (CreatePermission + Send). | WARNING |
|
|
|
|
## Usage
|
|
|
|
Build and run:
|
|
|
|
```
|
|
make # standalone binary
|
|
make plugin # .so plugin for happyDomain
|
|
./checker-stun-turn -listen :8080
|
|
```
|
|
|
|
Trigger a check:
|
|
|
|
```
|
|
curl -sX POST localhost:8080/collect -H 'content-type: application/json' -d '{
|
|
"options": {
|
|
"zone": "example.com",
|
|
"serverURI": "turns:turn.example.com:5349?transport=tcp",
|
|
"mode": "turn",
|
|
"username": "alice",
|
|
"credential": "s3cret",
|
|
"transports": "udp,tcp,tls",
|
|
"probePeer": "1.1.1.1:53",
|
|
"timeout": 5
|
|
}
|
|
}' | jq .
|
|
```
|
|
|
|
## Options
|
|
|
|
| Scope | Option | Type | Default | Notes |
|
|
|---------|-------------------|--------|---------------|-------|
|
|
| run | `zone` | string | (auto-filled) | used for `_stun._udp` / `_turn._udp` / `_turns._tcp` SRV discovery |
|
|
| run | `serverURI` | string | | explicit URI, RFC 7064/7065 |
|
|
| run | `mode` | choice | `auto` | `stun`, `turn`, `auto` |
|
|
| user | `username` | string | | long-term credentials |
|
|
| user | `credential` | secret | | long-term credentials |
|
|
| user | `sharedSecret` | secret | | REST-API auth (draft-uberti), takes precedence |
|
|
| user | `realm` | string | | optional explicit realm |
|
|
| user | `transports` | string | `udp,tcp,tls` | comma-separated among `udp,tcp,tls,dtls` |
|
|
| user | `probePeer` | string | `1.1.1.1:53` | target for the relay echo test |
|
|
| user | `testChannelBind` | bool | `false` | |
|
|
| user | `warningRTT` | uint | `200` ms | |
|
|
| user | `criticalRTT` | uint | `1000` ms | |
|
|
| user | `timeout` | uint | `5` s | per-probe |
|
|
|
|
## License
|
|
|
|
MIT (see LICENSE).
|