mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-06-16 22:54:12 +00:00
- Add `turn_stealth_domain` to gateway config for stealth TURN support - Introduce `turn_discovery` in `sni-router` to auto-discover per-namespace routes - Add database migration to enable stealth TURN per namespace - Document ephemeral state API in `SERVERLESS.md`
98 lines
3.6 KiB
Go
98 lines
3.6 KiB
Go
package turn
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
// Config holds configuration for the TURN server
|
|
type Config struct {
|
|
// ListenAddr is the address to bind the TURN listener (e.g., "0.0.0.0:3478")
|
|
ListenAddr string `yaml:"listen_addr"`
|
|
|
|
// TURNSListenAddr is the address for TURNS (TURN over TLS on TCP, e.g., "0.0.0.0:5349")
|
|
TURNSListenAddr string `yaml:"turns_listen_addr"`
|
|
|
|
// TLSCertPath is the path to the TLS certificate PEM file (for TURNS)
|
|
TLSCertPath string `yaml:"tls_cert_path"`
|
|
|
|
// TLSKeyPath is the path to the TLS private key PEM file (for TURNS)
|
|
TLSKeyPath string `yaml:"tls_key_path"`
|
|
|
|
// PublicIP is the public IP address of this node, advertised in TURN allocations
|
|
PublicIP string `yaml:"public_ip"`
|
|
|
|
// Realm is the TURN realm (typically the base domain)
|
|
Realm string `yaml:"realm"`
|
|
|
|
// AuthSecret is the HMAC-SHA1 shared secret for credential validation
|
|
AuthSecret string `yaml:"auth_secret"`
|
|
|
|
// RelayPortStart is the beginning of the UDP relay port range
|
|
RelayPortStart int `yaml:"relay_port_start"`
|
|
|
|
// RelayPortEnd is the end of the UDP relay port range
|
|
RelayPortEnd int `yaml:"relay_port_end"`
|
|
|
|
// Namespace this TURN instance belongs to
|
|
Namespace string `yaml:"namespace"`
|
|
|
|
// StealthDomain is the neutral, CDN-bland SNI hostname this server also
|
|
// answers TURNS for (e.g. "cdn-a1b2c3d4e5f6.orama-devnet.network").
|
|
//
|
|
// The stealth endpoint is an SNI-router passthrough, NOT a separate TURN
|
|
// server: a router on :443 reads only the TLS ClientHello SNI and forwards
|
|
// the raw bytes for this hostname to this same TURNS listener. TLS is still
|
|
// terminated here, by this TURN server, which therefore presents two certs
|
|
// (the primary TURN domain and StealthDomain) selected by ClientHello SNI.
|
|
// When empty, the stealth endpoint is disabled and behavior is unchanged.
|
|
StealthDomain string `yaml:"stealth_domain,omitempty"`
|
|
|
|
// TLSStealthCertPath is the path to the TLS certificate PEM file presented
|
|
// for StealthDomain. The SNI router only forwards bytes; this TURN server
|
|
// terminates the TLS handshake, so it needs the stealth domain's cert here.
|
|
TLSStealthCertPath string `yaml:"tls_stealth_cert_path,omitempty"`
|
|
|
|
// TLSStealthKeyPath is the path to the TLS private key PEM file for the
|
|
// StealthDomain certificate (TURN terminates TLS for the router-forwarded
|
|
// stealth connections).
|
|
TLSStealthKeyPath string `yaml:"tls_stealth_key_path,omitempty"`
|
|
}
|
|
|
|
// Validate checks the TURN configuration for errors
|
|
func (c *Config) Validate() []error {
|
|
var errs []error
|
|
|
|
if c.ListenAddr == "" {
|
|
errs = append(errs, fmt.Errorf("turn.listen_addr: must not be empty"))
|
|
}
|
|
|
|
if c.PublicIP == "" {
|
|
errs = append(errs, fmt.Errorf("turn.public_ip: must not be empty"))
|
|
} else if ip := net.ParseIP(c.PublicIP); ip == nil {
|
|
errs = append(errs, fmt.Errorf("turn.public_ip: %q is not a valid IP address", c.PublicIP))
|
|
}
|
|
|
|
if c.Realm == "" {
|
|
errs = append(errs, fmt.Errorf("turn.realm: must not be empty"))
|
|
}
|
|
|
|
if c.AuthSecret == "" {
|
|
errs = append(errs, fmt.Errorf("turn.auth_secret: must not be empty"))
|
|
}
|
|
|
|
if c.RelayPortStart <= 0 || c.RelayPortEnd <= 0 {
|
|
errs = append(errs, fmt.Errorf("turn.relay_port_range: start and end must be positive"))
|
|
} else if c.RelayPortEnd <= c.RelayPortStart {
|
|
errs = append(errs, fmt.Errorf("turn.relay_port_range: end (%d) must be greater than start (%d)", c.RelayPortEnd, c.RelayPortStart))
|
|
} else if c.RelayPortEnd-c.RelayPortStart < 100 {
|
|
errs = append(errs, fmt.Errorf("turn.relay_port_range: range must be at least 100 ports (got %d)", c.RelayPortEnd-c.RelayPortStart))
|
|
}
|
|
|
|
if c.Namespace == "" {
|
|
errs = append(errs, fmt.Errorf("turn.namespace: must not be empty"))
|
|
}
|
|
|
|
return errs
|
|
}
|