SIP Proxy Core

June 25, 2026 · View on GitHub

The [proxy] section controls the core SIP signaling engine.

Listeners & Transport

Configure which ports and protocols to enable.

[proxy]
addr = "0.0.0.0"

# Standard SIP ports
udp_port = 5060
# Multiple UDP ports (e.g., for multi-tenant or port range binding)
# udp_ports = [5060, 5062, 5064]
tcp_port = 5060

# Encrypted SIP (SIPS)
tls_port = 5061
# Uses proxy-level ssl_* configs (if not set, falls back to top-level ssl_*)
ssl_certificate = "./certs/fullchain.pem"
ssl_private_key = "./certs/privkey.pem"

# WebRTC (SIP over WebSocket)
ws_port = 8089
ws_handler = "/ws"

# RWI (RustPBX WebSocket Interface) — real-time call control WebSocket path
rwi_path = "/rwi/v1"

# AMI (Asterisk Manager Interface) HTTP path (default: "/ami/v1")
# ami_path = "/ami/v1"

SIP Identity & Behavior

[proxy]
# SIP User-Agent header
useragent = "RustPBX/1.2.0"
# Appended to Call-ID (e.g., id@rustpbx.com)
callid_suffix = "rustpbx.com"
# Allowed domains (realms). Empty = allows all matching IP/Host.
realms = ["example.com", "sip.process-one.net"]

The Role of Realms

Realms are used to partition the SIP namespace and provide context for authentication.

  • Security: Challenges are issued against a specific realm. Users must provide credentials valid for that realm.
  • Domain Routing: When multiple domains are hosted on the same IP, realms allow the proxy to distinguish which settings or user database to use.
  • Identity: Often used as the domain part of a SIP URI (e.g., user@realm).

You can manage Realms in the Web Console under Settings > Proxy Settings. Changes require a service restart to take full effect.

Concurrency & Protection

[proxy]
# Max simultaneous transactions handled
max_concurrency = 5000

# Reject matching User-Agents
ua_black_list = ["friendly-scanner", "pplsip"]
# Only allow specific User-Agents (if set, others are rejected)
ua_white_list = []

# If true, silently ignore requests to unknown users (anti-scanning)
ensure_user = true

# Frequency limiter (optional format: "100/60s" for 100 requests per 60 seconds)
frequency_limiter = "100/60s"

# SIP Session Timers (RFC 4028)
session_timer = true
# Keep refreshing session timer even if peer does not negotiate it
# session_timer_always = false
session_expires = 1800  # 30 minutes

# RTP timeout — if no audio packets are received on either direction for
# this many seconds, the call is automatically terminated (default: 30)
rtp_timeout = 30

# SIP Transaction Timers (RFC 3261) - optional overrides
t1_timer = 500      # T1 timer in milliseconds (default: 500)
t1x64_timer = 32000 # T1x64 timer in milliseconds (default: 32000)

Modules

Controls the loading of internal logic pipelines.

[proxy]
# Default stack
modules = ["acl", "auth", "registrar", "call"]

# Enable additional Addons
addons = ["wholesale", "monitor"]

Media & Codecs

[proxy]
# Media proxy mode: auto, all, none, nat, bypass
#   auto:    Bridge RTP only when necessary (e.g., WebRTC ↔ UDP, or NAT detected)
#   all:     Always bridge RTP (B2BUA style)
#   nat:     Bridge only if private IP is detected
#   none:    Direct media (signaling only)
#   bypass:  Rewrite SDP but let RTP flow directly between endpoints
media_proxy = "auto"

# Preferred audio codec order for SDP negotiation
audio_codecs = ["opus", "pcmu", "pcma", "g729"]

# Video codec allowlist for re-INVITEs sent to RTP/PSTN/IMS trunks.
# WebRTC-only codecs (VP8, VP9, AV1, …) and all rtcp-fb feedback attributes
# are stripped automatically. Defaults to ["H264"] when not set.
# video_codecs = ["H264"]

# Codec selection strategy for WebRTC endpoints.
# "performance" (default): avoid transcoding, keep only caller-offered codecs.
# "quality": prefer Opus > G729 > G722 > G711 (may require transcoding).
codec_strategy = "performance"

# Enable NAT media latching (helps with RTP behind NAT, default: true)
enable_latching = true

# Maximum RTP packets to observe during latching probation before committing
# to a candidate source address. Higher values improve stability on flaky
# networks at the cost of slower latch convergence. (default: 6, only used
# when enable_latching = true)
latching_probation_max_packets = 6

# Enable NAT fix for SIP signaling
nat_fix = true

File Loading & Paths

[proxy]
# Directory for auto-generated configs (managed by UI/API)
generated_dir = "./config"

# Load additional config files matching these patterns
routes_files = ["config/routes/*.toml"]
trunks_files = ["config/trunks/*.toml"]
acl_files = ["config/acl/*.toml"]
queues_files = ["config/queues/*.toml"]
ivr_files = ["config/ivr/*.toml"]

# Directory for queue-specific data files
queue_dir = "./queues"

Inline ACL Rules

ACL rules can also be defined inline in rustpbx.toml alongside acl_files:

[proxy]
# Inline rules are merged with rules loaded from acl_files
acl_rules = [
    "allow all",
    "deny all",
]

Call Handling

[proxy]
# Registrar default expires time in seconds (default: 30).
# This is the fallback value when the REGISTER request does not include
# an Expires header or Contact expires parameter.
# Both settings can be changed via the Web Console under Settings > Proxy.
registrar_expires = 30

# Maximum allowed expires value in seconds (default: 50).
# Client-requested expires exceeding this limit will be capped.
# Set to a higher value if clients need longer registration lifetimes.
max_registrar_expires = 50

# Passthrough failure status codes to caller
# When true, caller receives the same SIP error code (e.g., 486, 603) from callee
# When false, a generic error code is sent
passthrough_failure = true

# Use SIP REFER for blind transfers (default: false, uses re-INVITE)
# blind_transfer_use_refer = false

# Maximum items for SIP flow storage (per dialog)
sip_flow_max_items = 1000

In-Dialog Authentication Cache

When enabled, successfully authenticated dialogs are cached along with their source address. Subsequent in-dialog requests (e.g., re-INVITE, BYE) from the same source address within the TTL window skip re-authentication, reducing latency and load.

[proxy]
# Enabled by default. Set to false to disable.
dialog_auth_cache = { enabled = true, cache_size = 10000, ttl_seconds = 3600 }
  • enabled: Whether to skip authentication for cached in-dialog requests. Default: true.
  • cache_size: Maximum number of dialogs to cache (LRU eviction). Default: 10000.
  • ttl_seconds: Time-to-live for cache entries. Default: 3600 (1 hour).

To disable explicitly:

[proxy]
dialog_auth_cache = { enabled = false }

Channel Capacity

Controls the size of internal async channels used for session and media command/event passing. Increasing these values may help under high concurrency at the cost of memory, while decreasing them can reduce backpressure latency.

[proxy]
# Session command channel capacity (default: 256)
session_cmd_channel_capacity = 256
# Session state change channel capacity (default: 256)
session_state_channel_capacity = 256
# Media engine command channel capacity (default: 512)
media_cmd_channel_capacity = 512
# Media engine event channel capacity (default: 1024)
media_event_channel_capacity = 1024
  • session_cmd_channel_capacity: Max pending commands per SIP session (e.g., hangup, transfer, play). Default: 256.
  • session_state_channel_capacity: Max pending state-change notifications per session. Default: 256.
  • media_cmd_channel_capacity: Max pending commands per media engine instance (e.g., play, stop, record). Default: 512.
  • media_event_channel_capacity: Max pending media events per engine instance (e.g., DTMF, playback complete). Default: 1024.

DoS Protection

Rate-limiting and anti-scanning controls for SIP traffic.

[proxy]
# Enable DoS protection
dos_enabled = false

# Max calls per second per source IP (default: 100)
dos_max_cps_per_ip = 100

# Max concurrent dialogs per source IP (default: 500)
dos_max_concurrent_per_ip = 500

# Number of failed probe attempts before blocking (default: 50)
dos_scan_probe_threshold = 50

# Block duration in seconds for detected scanners (default: 600)
dos_scan_block_duration_secs = 600

URI Validation

[proxy]
# Maximum URI length accepted (default: 256)
uri_max_length = 256

# Reject malformed URIs (default: false)
uri_reject_malformed = false

Emergency Numbers

Configure emergency call handling for local compliance.

[proxy]
[proxy.emergency]
enabled = true
numbers = ["110", "119", "120", "122", "911", "999"]
emergency_trunk = "pstn-trunk"

Identity & Privacy

These settings control how the PBX identifies itself in SIP signaling and SDP media attributes.

[proxy]
# Contact header username when no dialplan caller_contact is set.
# If not specified, a random 16-char hex string is generated at startup.
contact_username = "my-pbx-01"

# CNAME value used in SDP a=ssrc:<n> cname:<value> attributes.
# If not specified, a random 16-char hex string is generated at startup.
# This replaces the default "rustrtc-cname-<ssrc>" in generated SDP.
rtc_cname = "my-pbx-01"

When neither is specified, both default to the same randomly generated hex string, making the PBX instance identifiable without revealing implementation details.