Skip to content

SIP Contact built from endpoint.get_addrs() can pick ephemeral outbound TLS ports — breaks mid-dialog BYE #247

Description

@autopeasant

Summary

default_contact_uri() / transport-aware Contact helpers that pick an address from endpoint.get_addrs() can select an ephemeral local port belonging to an outbound client TLS connection (e.g. trunk REGISTER or outbound INVITE), not the configured TLS/UDP listener.

Observed Contact on outbound INVITE to a TLS UA:

Contact: <sips:…@192.168.10.252:43218;transport=TLS>

Expected (listener):

Contact: <sips:…@192.168.10.252:5061;transport=TLS>

Nothing listens on :43218, so the callee’s mid-dialog BYE never reaches the B2BUA. Hangup becomes one-way: hanging up the callee leaves the caller (e.g. UDP ATA) stuck; the reverse direction still works because the ATA BYEs to the real UDP listener :5060.

Affected version

restsend/rustpbx around commit 5cbcd39419c34a3ba8b1d08305a6504ec08549b9 (and any Contact path that uses endpoint.get_addrs() without filtering to listener sockets).

Environment

  • LAN bind 192.168.x.x, TLS listener :5061, UDP :5060
  • Outbound TLS activity (trunk REGISTER / external INVITE) creates additional transports
  • Internal B2BUA call: UDP ATA → TLS softphone

Minimal reproduction

  1. Configure UDP + TLS listeners on fixed ports; set proxy.addr to the bind IP.
  2. Enable an outbound TLS trunk REGISTER so the endpoint holds outbound TLS sockets.
  3. Place a call that originates a client INVITE to a TLS-registered UA.
  4. Inspect Contact on that INVITE: host/port may be bind IP with a high ephemeral port.
  5. Answer, then hang up from the TLS UA → BYE targets Contact → no listener → caller leg stays up.

Expected

Contact host/port must be the configured listener for that transport (udp_port / tls_port on proxy.addr), optionally with external_ip for non-LAN destinations when NAT port-forwards exist. Ephemeral outbound sockets in get_addrs() must not be used for dialog Contact.

Suggested direction

Build Contact from ProxyConfig (addr + udp_port/tls_port/…) rather than endpoint.get_addrs(), or filter get_addrs() to sockets that match configured listener ports only. For internet-facing legs, prefer rtp_config.external_ip (or a dedicated SIP external host) + listener port when the destination is not RFC1918.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions