checker-stun-turn/checker/definition.go
Pierre-Olivier Mercier 7c7706fe3f Initial commit
Adds a happyDomain checker that probes STUN/TURN servers end-to-end:
DNS/SRV discovery, UDP/TCP/TLS/DTLS dial, STUN binding + reflexive-addr
sanity, open-relay detection, authenticated TURN Allocate (long-term
creds or REST-API HMAC), public-relay check, CreatePermission + Send
round-trip through the relay, and optional ChannelBind.

Failing sub-tests carry a remediation string (`Fix`) that the HTML
report surfaces as a yellow headline callout and inline next to each
row. Mapping covers the most common coturn misconfigurations
(external-ip, relay-ip, lt-cred-mech, min-port/max-port, cert issues,
401 nonce drift, 441/442/486/508 allocation errors).

Implements sdk.EndpointDiscoverer (checker/discovery.go): every
stuns:/turns:/DTLS endpoint observed during Collect is published as a
DiscoveredEndpoint{Type: "tls"|"dtls"} so a downstream TLS checker can
verify certificates without re-parsing the observation.

Backed by pion/stun/v3 + pion/turn/v4 + pion/dtls/v3; SDK pinned to a
local replace until the EndpointDiscoverer interface ships in a tagged
release.
2026-04-26 19:55:05 +07:00

94 lines
3.1 KiB
Go

package checker
import (
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
// Version is the checker version reported in CheckerDefinition.Version.
// Defaults to "built-in"; standalone binaries override it from main().
var Version = "built-in"
// Definition returns the CheckerDefinition for the STUN/TURN checker.
func (p *stunTurnProvider) Definition() *sdk.CheckerDefinition {
return &sdk.CheckerDefinition{
ID: "stunturn",
Name: "STUN/TURN Server",
Version: Version,
HasHTMLReport: true,
ObservationKeys: []sdk.ObservationKey{ObservationKeyStunTurn},
Availability: sdk.CheckerAvailability{
ApplyToZone: true,
ApplyToService: true,
},
Options: sdk.CheckerOptionsDocumentation{
RunOpts: []sdk.CheckerOptionDocumentation{
{
Id: "zone",
Type: "string",
Label: "Zone",
Placeholder: "example.com",
AutoFill: sdk.AutoFillDomainName,
Description: "Zone used for SRV-based STUN/TURN endpoint discovery when no explicit URI is provided.",
},
{
Id: "serverURI",
Type: "string",
Label: "Server URI",
Placeholder: "turns:turn.example.com:5349?transport=tcp",
Description: "Explicit STUN/TURN URI (RFC 7064/7065). Overrides SRV-based discovery.",
},
{
Id: "mode",
Type: "string",
Label: "Mode",
Default: "auto",
Choices: []string{"auto", "stun", "turn"},
Description: "auto: probe both STUN and TURN; stun: skip TURN allocation tests; turn: require TURN allocation.",
},
},
UserOpts: []sdk.CheckerOptionDocumentation{
{Id: "username", Type: "string", Label: "TURN username"},
{Id: "credential", Type: "string", Label: "TURN password", Secret: true},
{
Id: "sharedSecret",
Type: "string",
Label: "REST API shared secret",
Secret: true,
Description: "Shared secret used to derive ephemeral credentials (draft-uberti-rtcweb-turn-rest). Takes precedence over username/password.",
},
{Id: "realm", Type: "string", Label: "Realm"},
{
Id: "transports",
Type: "string",
Label: "Transports",
Default: "udp,tcp,tls",
Description: "Comma-separated list of transports to test among: udp, tcp, tls, dtls.",
},
{
Id: "probePeer",
Type: "string",
Label: "Relay echo target",
Default: "1.1.1.1:53",
Description: "host:port used to validate the relay path (a CreatePermission + Send is issued, no payload data is exchanged).",
},
{
Id: "testChannelBind",
Type: "bool",
Label: "Also test ChannelBind",
Default: false,
},
{Id: "warningRTT", Type: "uint", Label: "RTT warning threshold (ms)", Default: 200},
{Id: "criticalRTT", Type: "uint", Label: "RTT critical threshold (ms)", Default: 1000},
{Id: "timeout", Type: "uint", Label: "Per-probe timeout (s)", Default: 5},
},
},
Rules: Rules(),
Interval: &sdk.CheckIntervalSpec{
Min: 5 * time.Minute,
Default: 30 * time.Minute,
Max: 24 * time.Hour,
},
}
}