AlexxIT/go2rtc · error

webrtc: can't get public IP

Error message

webrtc: can't get public IP

What it means

pkg/webrtc GetCachedPublicIP returns the public IP used for WebRTC candidates, resolving it via external STUN-like lookups and caching the result for ~5 minutes. If none of the lookups succeed and nothing valid is cached, it returns this error — the machine effectively has no discoverable public IP, which breaks NAT traversal.

Solutions

  1. Enable outbound network access so public-IP lookup endpoints are reachable
  2. Configure the server's own IP with a static/NAT1-to-1 public IP in the config (webrtcIPsFromInterfaces / webrtcAdditionalHosts) and skip auto-lookup
  3. Check DNS resolution and firewall rules on the host
  4. Retry later — the cache may be repopulated once connectivity is restored

Example fix

// mediamtx.yml
// before (auto-detect fails on isolated host)
// after
webrtcAdditionalHosts: [203.0.113.10]  # explicit public IP instead of lookup
Defensive patterns

Strategy: fallback

Try / catch

ip, err := webrtc.GetCachedPublicIP()
if err != nil {
    // fall back to configured static public IP or disable WebRTC
    ip = configuredPublicIP
}

Prevention

When it happens

Trigger: Calling GetCachedPublicIP (directly or through Host / LookupIP) when all public-IP queries fail — no outbound internet access, DNS failure, all lookup endpoints unreachable, or a machine with only private addresses behind strict NAT.

Common situations: Running the server in an isolated Docker network or air-gapped environment; firewall blocking outbound UDP/HTTP to IP-lookup services; cloud instance with no egress yet; wrong DNS setup.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/ea7a05b1cd0298cc. Report an issue: GitHub.

Appendix: source

Thrown at pkg/webrtc/helpers.go:239

	return xorAddr.IP, nil
}

var cachedIP net.IP
var cachedTS time.Time

func GetCachedPublicIP(stuns ...string) (net.IP, error) {
	if now := time.Now(); now.After(cachedTS) {
		for _, addr := range stuns {
			if ip, _ := GetPublicIP(addr); ip != nil {
				cachedIP = ip
				cachedTS = now.Add(time.Minute * 5)
				return ip, nil
			}
		}
	}
	if cachedIP == nil {
		return nil, errors.New("webrtc: can't get public IP")
	}
	return cachedIP, nil
}

func IsIP(host string) bool {
	for _, i := range host {
		if i >= 'A' {
			return false
		}
	}
	return true
}

func MimeType(codec *core.Codec) string {
	switch codec.Name {
	case core.CodecH264:
		return webrtc.MimeTypeH264
	case core.CodecH265:

View on GitHub (pinned to c245815e75)