Skip to content

fix: wrap IPv6 addresses in brackets in UDP TURN URLs (RFC 3986)#4476

Merged
boks1971 merged 1 commit into
livekit:masterfrom
fstehle:fix/ipv6-turn-url-rfc3986
Apr 24, 2026
Merged

fix: wrap IPv6 addresses in brackets in UDP TURN URLs (RFC 3986)#4476
boks1971 merged 1 commit into
livekit:masterfrom
fstehle:fix/ipv6-turn-url-rfc3986

Conversation

@fstehle
Copy link
Copy Markdown
Contributor

@fstehle fstehle commented Apr 24, 2026

iceServersForParticipant builds UDP TURN URLs by interpolating the node IP directly into a format string:

fmt.Sprintf("turn:%s:%d?transport=udp", ip, port)

When NodeIP.V6 is set, ToStringSlice() includes the bare IPv6 address, producing URLs like:

turn:2a05:d014:ee4:1201:7039:38c:f652:a252:443?transport=udp

RFC 3986 §3.2.2 requires IPv6 addresses in URIs to be enclosed in square brackets. Without them the port is ambiguous and WebRTC clients (e.g. libdatachannel) reject the URL with "Invalid ICE server port".

Use net.JoinHostPort which handles bracketing for IPv6 and is a no-op for IPv4, producing well-formed URLs:

turn:[2a05:d014:ee4:1201:7039:38c:f652:a252]:443?transport=udp
turn:1.2.3.4:443?transport=udp

`iceServersForParticipant` builds UDP TURN URLs by interpolating the
node IP directly into a format string:

    fmt.Sprintf("turn:%s:%d?transport=udp", ip, port)

When `NodeIP.V6` is set, `ToStringSlice()` includes the bare IPv6
address, producing URLs like:

    turn:2a05:d014:ee4:1201:7039:38c:f652:a252:443?transport=udp

RFC 3986 §3.2.2 requires IPv6 addresses in URIs to be enclosed in
square brackets. Without them the port is ambiguous and WebRTC clients
(e.g. libdatachannel) reject the URL with "Invalid ICE server port".

Use `net.JoinHostPort` which handles bracketing for IPv6 and is a
no-op for IPv4, producing well-formed URLs:

    turn:[2a05:d014:ee4:1201:7039:38c:f652:a252]:443?transport=udp
    turn:1.2.3.4:443?transport=udp
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 24, 2026

CLA assistant check
All committers have signed the CLA.

@fstehle fstehle marked this pull request as ready for review April 24, 2026 08:23
@boks1971
Copy link
Copy Markdown
Contributor

Thank you for the submission.

@boks1971 boks1971 merged commit f3b80b2 into livekit:master Apr 24, 2026
2 of 3 checks passed
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 16, 2026
….0 → v1.12.0) (#511)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [docker.io/livekit/livekit-server](https://github.com/livekit/livekit) | minor | `v1.11.0` → `v1.12.0` |

---

### Release Notes

<details>
<summary>livekit/livekit (docker.io/livekit/livekit-server)</summary>

### [`v1.12.0`](https://github.com/livekit/livekit/releases/tag/v1.12.0)

[Compare Source](livekit/livekit@v1.11.0...v1.12.0)

##### ATTENTION: This releases introduces important changes to how TURN authentication and permissions are handled. These changes make the system more secure. This release maintains backwards compatibility. However, backwards compatibility will be removed in the next release. So, please plan accordingly.

##### TURN permission handling changes

By default, TURN will not relay traffic to private IPs. If you need to relay traffic to private IPs, please use `allow_restricted_peer_cidrs` which is explained in config-sample.yaml and replicated below.

```

#   # list of restricted peer CIDRs (loopback, link-local (unicast, multicast), multicast, private, unspecified) to allow access to.
#   # By default (i. e. empty list), all restricted peer CIDRs are denied access.

#   # When not empty, only the specified CIDRs are allowed access.
#   # Note that this check is applied to restricted peer CIDRs only.

#   allow_restricted_peer_cidrs:
#     - 10.0.0.0/8

#     - 192.168.0.0/16
```

That list can be paired with a deny list which takes precedence if there is an overlap.

```

#   # list of peer CIDRs to deny access to.
#   # This applies to all peer CIDRs, including restricted ones.

#   # Deny list takes precedence over allow list.
#   deny_peer_cidrs:

#     - 10.0.0.0/8
#     - 192.168.0.0/16
```

Relevant PRs: [#&#8203;4505](livekit/livekit#4505)

##### TURN authentication handling changes

TURN credentials now have a TTL (Time-To-Live) beyond which they are not valid to join a room. We recommend rotating your TURN authentication secrets to ensure older credentials are rendered stale and not usable.

```

#   # TTL of the TURN credentials in seconds - defaults to 300
#   ttl_seconds: 300
```

Please note that the TTL is always used in constructing the credentials. So, a value of 0 will create credentials that expire immediately.

Relevant PRs: [#&#8203;4505](livekit/livekit#4505), [#&#8203;4515](livekit/livekit#4515), [#&#8203;4524](livekit/livekit#4524), [#&#8203;4526](livekit/livekit#4526)

##### Added

- add support for client capabilities ([#&#8203;4461](livekit/livekit#4461))
- Additional data tracks logging ([#&#8203;4489](livekit/livekit#4489))
- Add CloseWithReason to agent SignalConn interface ([#&#8203;4492](livekit/livekit#4492))
- add agent environment ([#&#8203;4498](livekit/livekit#4498))
- add duration seconds reporting ([#&#8203;4500](livekit/livekit#4500))
- add helper to check for agent worker endpoint ([#&#8203;4503](livekit/livekit#4503))
- test: verify upstream and downstream connection stats end-to-end ([#&#8203;4508](livekit/livekit#4508))
- Add TURN permission handler. ([#&#8203;4505](livekit/livekit#4505))
- allow setting agent job assignment url ([#&#8203;4512](livekit/livekit#4512))
- Add expiry to TURN password. ([#&#8203;4505](livekit/livekit#4505), [#&#8203;4515](livekit/livekit#4515))
- add AssignmentHook to AssignJob; propagate websocket write errors ([#&#8203;4516](livekit/livekit#4516))
- Apply room tags from JWT grant room configuration ([#&#8203;4518](livekit/livekit#4518))
- feat: auto create rooms for tokens with the RoomCreate grant ([#&#8203;4320](livekit/livekit#4320))
- Add integration test for TURN auth failures ([#&#8203;4524](livekit/livekit#4524))
- Support SIP auth realm for inbound. ([#&#8203;4522](livekit/livekit#4522))
- Apply ttl check only when authenticate allocation creating ([#&#8203;4526](livekit/livekit#4526))

##### Changed

- feat(pion/ice): replace deprecated NAT1To1 with SetAddressRewriteRules ([#&#8203;4466](livekit/livekit#4466))
- do not log data track stats if not started ([#&#8203;4468](livekit/livekit#4468))
- Consolidate RTCP packets and do RTCP callback outside lock. ([#&#8203;4469](livekit/livekit#4469))
- Keep a shadow copy of tracks for use by different stream allocator state ([#&#8203;4470](livekit/livekit#4470))
- Avoid stream allocator event data cast to interface and back. ([#&#8203;4471](livekit/livekit#4471))
- Convert sort.Slice -> slices.SortFunc ([#&#8203;4472](livekit/livekit#4472))
- Turn off transceiver re-use on Safari. ([#&#8203;4474](livekit/livekit#4474))
- reduce some heap use in packet path by ([#&#8203;4478](livekit/livekit#4478))
- Close peer connection unconditionally to unblock set local/remote ([#&#8203;4485](livekit/livekit#4485))
- Misc optimisations. ([#&#8203;4490](livekit/livekit#4490))
- report all simulcast layers ([#&#8203;4491](livekit/livekit#4491))
- Use mediatransportutil/codec package, no functional change ([#&#8203;4497](livekit/livekit#4497))
- rename agent environment to deployment ([#&#8203;4506](livekit/livekit#4506))
- Update protocol to support SIP media config. ([#&#8203;4509](livekit/livekit#4509))
- update protocol for protojson ([#&#8203;4510](livekit/livekit#4510))
- Populate data track loggers with context ([#&#8203;4514](livekit/livekit#4514))
- Log large packets receive/send. ([#&#8203;4521](livekit/livekit#4521))
- Log details of RTCP packets. ([#&#8203;4525](livekit/livekit#4525))
- Create NACK tracker only once. ([#&#8203;4527](livekit/livekit#4527))

##### Fixed

- fix: wrap IPv6 addresses in brackets in UDP TURN URLs (RFC 3986) ([#&#8203;4476](livekit/livekit#4476))
- Legacy TrackInfo.Simulcast flag. ([#&#8203;4493](livekit/livekit#4493))
- Fix publish-only limitations being incorrectly applied to receivers ([#&#8203;4495](livekit/livekit#4495))
- Include reception reoprts in receiver report callback. ([#&#8203;4496](livekit/livekit#4496))
- Fix sense check in DeltaInfo gathering ([#&#8203;4507](livekit/livekit#4507))
- Fix SIP media config upgrade. ([#&#8203;4511](livekit/livekit#4511))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/511
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants