Skip to main content
The Pion ICE library provides flexible configuration through the AgentOption pattern. This guide covers how to configure your ICE agent with STUN/TURN servers, network types, candidate types, timeouts, and other essential settings.

Creating an Agent

There are two ways to create an ICE agent:
agent, err := ice.NewAgentWithOptions(
    ice.WithUrls(stunURLs),
    ice.WithPortRange(10000, 20000),
    ice.WithNetworkTypes([]ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6}),
)
The AgentConfig approach is deprecated. Use NewAgentWithOptions with functional options instead.

STUN/TURN Server Configuration

Configure STUN and TURN servers to enable server reflexive and relay candidates:
import "github.com/pion/stun/v3"

stunURLs := []*stun.URI{
    {Scheme: stun.SchemeTypeSTUN, Host: "stun.l.google.com", Port: 19302},
    {Scheme: stun.SchemeTypeTURN, Host: "turn.example.com", Port: 3478, 
     Username: "user", Password: "pass"},
}

agent, err := ice.NewAgentWithOptions(
    ice.WithUrls(stunURLs),
)

TURN Protocols

TURN supports multiple transport protocols:
  • UDP: turn://turn.example.com:3478
  • TCP: turn://turn.example.com:3478?transport=tcp
  • TLS: turns://turn.example.com:5349?transport=tcp
  • DTLS: turns://turn.example.com:5349?transport=udp
turnURLs := []*stun.URI{
    // TURN over UDP
    {Scheme: stun.SchemeTypeTURN, Proto: stun.ProtoTypeUDP,
     Host: "turn.example.com", Port: 3478, Username: "user", Password: "pass"},
    // TURN over TLS
    {Scheme: stun.SchemeTypeTURNS, Proto: stun.ProtoTypeTCP,
     Host: "turn.example.com", Port: 5349, Username: "user", Password: "pass"},
}

Network Types

Control which network types are used for candidate gathering:
// Enable only IPv4 UDP
agent, err := ice.NewAgentWithOptions(
    ice.WithNetworkTypes([]ice.NetworkType{ice.NetworkTypeUDP4}),
)

// Enable IPv4 and IPv6 UDP
agent, err := ice.NewAgentWithOptions(
    ice.WithNetworkTypes([]ice.NetworkType{
        ice.NetworkTypeUDP4,
        ice.NetworkTypeUDP6,
    }),
)

// Enable UDP and TCP
agent, err := ice.NewAgentWithOptions(
    ice.WithNetworkTypes([]ice.NetworkType{
        ice.NetworkTypeUDP4,
        ice.NetworkTypeTCP4,
    }),
)

Available Network Types

  • NetworkTypeUDP4 - UDP over IPv4
  • NetworkTypeUDP6 - UDP over IPv6
  • NetworkTypeTCP4 - TCP over IPv4 (requires TCPMux)
  • NetworkTypeTCP6 - TCP over IPv6 (requires TCPMux)

Candidate Types

Specify which candidate types to gather:
// Gather all candidate types (default)
agent, err := ice.NewAgentWithOptions(
    ice.WithCandidateTypes([]ice.CandidateType{
        ice.CandidateTypeHost,
        ice.CandidateTypeServerReflexive,
        ice.CandidateTypeRelay,
    }),
)

// Only gather host candidates
agent, err := ice.NewAgentWithOptions(
    ice.WithCandidateTypes([]ice.CandidateType{
        ice.CandidateTypeHost,
    }),
)

// Only gather relay candidates (force TURN)
agent, err := ice.NewAgentWithOptions(
    ice.WithCandidateTypes([]ice.CandidateType{
        ice.CandidateTypeRelay,
    }),
)

Port Range Configuration

Restrict the UDP port range for host candidates:
agent, err := ice.NewAgentWithOptions(
    ice.WithPortRange(10000, 20000),
)
Port range configuration is ignored when using UDPMux, as the mux manages a single port.

Timeout Configuration

Configure various timeouts for connectivity and gathering:

Connectivity Timeouts

import "time"

agent, err := ice.NewAgentWithOptions(
    // Time before transitioning to disconnected state (default: 5s)
    ice.WithDisconnectedTimeout(5 * time.Second),
    
    // Time before transitioning to failed after disconnected (default: 25s)
    ice.WithFailedTimeout(25 * time.Second),
    
    // Keepalive interval for selected pair (default: 2s)
    ice.WithKeepaliveInterval(2 * time.Second),
    
    // Connectivity check interval during connecting state (default: 200ms)
    ice.WithCheckInterval(200 * time.Millisecond),
)

Gathering Timeout

agent, err := ice.NewAgentWithOptions(
    // Timeout for STUN server responses (default: 5s)
    ice.WithSTUNGatherTimeout(5 * time.Second),
)

Candidate Selection Timeouts

Control minimum wait times before nominating each candidate type:
agent, err := ice.NewAgentWithOptions(
    // Wait before selecting host candidates (default: 0ms)
    ice.WithHostAcceptanceMinWait(0 * time.Millisecond),
    
    // Wait before selecting srflx candidates (default: 500ms)
    ice.WithSrflxAcceptanceMinWait(500 * time.Millisecond),
    
    // Wait before selecting prflx candidates (default: 1000ms)
    ice.WithPrflxAcceptanceMinWait(1000 * time.Millisecond),
    
    // Wait before selecting relay candidates (default: 2000ms)
    ice.WithRelayAcceptanceMinWait(2000 * time.Millisecond),
)

Interface and IP Filtering

Filter network interfaces and IP addresses during candidate gathering:
// Only use interfaces starting with "eth"
agent, err := ice.NewAgentWithOptions(
    ice.WithInterfaceFilter(func(interfaceName string) bool {
        return len(interfaceName) >= 3 && interfaceName[:3] == "eth"
    }),
)

// Only use private IP addresses
agent, err := ice.NewAgentWithOptions(
    ice.WithIPFilter(func(ip net.IP) bool {
        return ip.IsPrivate()
    }),
)

ICE Lite Mode

Configure the agent to run in ICE Lite mode:
agent, err := ice.NewAgentWithOptions(
    ice.WithICELite(true),
)
ICE Lite agents do not perform connectivity checks and only provide host candidates. Use this mode for servers behind a known public IP.

Local Credentials

Set custom ICE username fragment and password:
agent, err := ice.NewAgentWithOptions(
    ice.WithLocalCredentials("customUfrag", "customPassword"),
)
The username fragment must have at least 24 bits of randomness (3 characters), and the password must have at least 128 bits (16 characters). If empty strings are provided, random values will be generated.

Maximum Binding Requests

Control the maximum number of binding requests before marking a pair as failed:
agent, err := ice.NewAgentWithOptions(
    ice.WithMaxBindingRequests(7), // default is 7
)

Logging

Configure logging for the ICE agent:
import "github.com/pion/logging"

loggerFactory := logging.NewDefaultLoggerFactory()
loggerFactory.DefaultLogLevel = logging.LogLevelDebug

agent, err := ice.NewAgentWithOptions(
    ice.WithLoggerFactory(loggerFactory),
)

Proxy Support

Configure a proxy dialer for TURN over TCP/TLS:
import "golang.org/x/net/proxy"

dialer, err := proxy.SOCKS5("tcp", "proxy.example.com:1080", nil, proxy.Direct)
if err != nil {
    panic(err)
}

agent, err := ice.NewAgentWithOptions(
    ice.WithProxyDialer(dialer),
)

Complete Example

Here’s a complete example combining multiple configuration options:
import (
    "time"
    "github.com/pion/ice/v4"
    "github.com/pion/logging"
    "github.com/pion/stun/v3"
)

func createAgent() (*ice.Agent, error) {
    // Configure STUN/TURN servers
    urls := []*stun.URI{
        {Scheme: stun.SchemeTypeSTUN, Host: "stun.l.google.com", Port: 19302},
        {Scheme: stun.SchemeTypeTURN, Host: "turn.example.com", Port: 3478,
         Username: "user", Password: "pass"},
    }
    
    // Configure logger
    loggerFactory := logging.NewDefaultLoggerFactory()
    loggerFactory.DefaultLogLevel = logging.LogLevelInfo
    
    // Create agent with options
    return ice.NewAgentWithOptions(
        ice.WithUrls(urls),
        ice.WithPortRange(10000, 20000),
        ice.WithNetworkTypes([]ice.NetworkType{
            ice.NetworkTypeUDP4,
            ice.NetworkTypeUDP6,
        }),
        ice.WithCandidateTypes([]ice.CandidateType{
            ice.CandidateTypeHost,
            ice.CandidateTypeServerReflexive,
            ice.CandidateTypeRelay,
        }),
        ice.WithDisconnectedTimeout(5 * time.Second),
        ice.WithFailedTimeout(25 * time.Second),
        ice.WithKeepaliveInterval(2 * time.Second),
        ice.WithLoggerFactory(loggerFactory),
    )
}

Default Values

The following table shows the default values for key configuration options:
OptionDefault ValueSource
Check Interval200msagent_config.go:18
Keepalive Interval2sagent_config.go:21
Disconnected Timeout5sagent_config.go:24
Failed Timeout25sagent_config.go:27
Host Acceptance Wait0msagent_config.go:30
Srflx Acceptance Wait500msagent_config.go:33
Prflx Acceptance Wait1000msagent_config.go:36
Relay Acceptance Wait2000msagent_config.go:39
STUN Gather Timeout5sagent_config.go:45
Max Binding Requests7agent_config.go:48
TCP Priority Offset27agent_config.go:52

Next Steps

Candidate Gathering

Learn how to gather ICE candidates

Connectivity Checks

Understand how ICE performs connectivity checks

Multiplexing

Share ports with UDPMux and TCPMux

NAT Traversal

Configure NAT traversal and address rewriting

Build docs developers (and LLMs) love