Skip to content

fix(webrtc): 修复异常 ICE 会话导致的端口资源泄漏 - #4782

Open
taotaobujue2008 wants to merge 2 commits into
ZLMediaKit:masterfrom
taotaobujue2008:fix/release-idle-ice-turn-resources
Open

fix(webrtc): 修复异常 ICE 会话导致的端口资源泄漏#4782
taotaobujue2008 wants to merge 2 commits into
ZLMediaKit:masterfrom
taotaobujue2008:fix/release-idle-ice-turn-resources

Conversation

@taotaobujue2008

Copy link
Copy Markdown
Contributor

公网部署时,ICE 端口可能遭受恶意请求或扫描。异常会话长期不退出,
导致 UDP 会话、TURN relay 端口及关联资源无法及时释放,最终可能耗尽
可用端口。

  • 增加 UDP ICE 会话空闲超时配置,自动关闭长期无数据的会话
  • 完善 TURN Allocation 的创建、刷新、超时和主动释放流程
  • 会话异常退出或销毁时清理 relay 端口、Permission 和 ChannelBind
  • 为 relay 会话注册表增加并发保护,避免残留或竞态访问
  • 使用弱引用解除会话对象之间的循环引用
  • 修正 Allocation Mismatch 错误码为 437
  • 补充 iceSessionTimeoutSec 配置及使用说明

Plan-Item: ICEBUGFIX

Add configurable ICE UDP session expiry, complete TURN allocation lifecycle cleanup, synchronize the relay registry, correct Allocation Mismatch to 437, and document the timeout setting.

Plan-Item: ICEBUGFIX

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90ec32207a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread webrtc/IceTransport.cpp Outdated
@xia-chu

xia-chu commented Jul 23, 2026

Copy link
Copy Markdown
Member

PR 概述

修复公网部署时异常 ICE 会话导致的 UDP 端口和资源泄漏问题。涉及 TURN allocation 生命周期管理、ICE 会话超时清理、循环引用修复等。

变更分析

改动 评价
ICE UDP 会话空闲超时 (iceSessionTimeoutSec) 正确。通过 onManager() 定期检查,TCP 会话跳过,TURN allocation 存在时保活
TURN Allocation 生命周期 (创建/刷新/超时/主动释放) 正确。原来 handleRefreshRequest 是空函数,现在实现了完整流程
_session_pairPair::Ptr 改为 weak_ptr 正确。打破 IceSession → IceServer → Pair → IceSession 的循环引用
relayForwordingData lambda 捕获 weak_ptr 正确。原来按值捕获 this,如果 IceServer 先析构,回调访问野指针
_relayed_sessions_relayed_session_mutex 正确。该全局变量被 relay socket 回调跨线程访问,需要互斥保护
allocateRelayed 去重 + getSinglePort() 空检查 正确。原代码 *port 在端口耗尽时解引用 null shared_ptr 会崩溃
AllocationMismatch 从 438 改为 437 正确。RFC 5766 定义为 437
析构函数调用 releaseSessionResources() 正确。确保异常销毁时资源不泄漏

发现的问题

1. removeRelayedSessions() 中不必要的 strong_session 存活时间(低风险)

IceServer::Ptr strong_session;
{
    std::lock_guard<std::mutex> lck(s_relayed_session_mutex);
    auto it = _relayed_session.find(relayed_pair.first);
    ...
    strong_session = it->second.lock();
    if (!strong_session || strong_session.get() == this) {
        _relayed_session.erase(it);
    }
}
// strong_session 在这里还活着,延长了 IceServer 生命周期

strong_session 在 mutex scope 外析构,如果是另一个 IceServer 实例,会不必要地延长其生命周期。建议在 if 判断后立即 reset 或移入 scope 内。不过实际影响很小。

2. handleRefreshRequest 没有验证请求来自 allocation 创建者(低风险)

if (_relayed_pairs.empty()) {
    sendErrorResponse(packet, pair, StunAttrErrorCode::Code::AllocationMismatch);
    return;
}

Codex bot 也指出了这个问题:如果不同 5-tuple 的发送者使用相同凭证到达同一个 IceServer,Refresh 请求会被接受。RFC 5766 要求 Refresh 必须来自创建 allocation 的同一 5-tuple。但对于 ZLM 的场景(单 peer 的 TURN server),实际风险很低。

3. 全局静态 mutex 的粒度(建议优化)

s_relayed_session_mutex 是全局静态的,所有 IceServer 实例共享。对于高并发 TURN 场景,可以考虑改为 per-instance 锁或放在 IceServer 成员变量中。当前实现功能正确,只是锁粒度偏大。

4. _allocation_timer 在 TURN 关闭时仍然创建(低风险)

initialize() 中先检查 enable_turn,TURN 关闭时不创建 timer,这是正确的。但 timer 回调间隔 10s + allocation 生命周期 600s,极端情况下 allocation 可能超时 10s 后才被清理。可以接受。

结论

可以合并。 这是一个高质量的安全修复 PR:

  • 修复了 allocateRelayed 在端口耗尽时的 崩溃 bug*port 解引用 null)
  • 修复了 relayForwordingDatathis 指针 use-after-free 的隐患
  • 补全了 TURN Refresh 这个 空函数 的完整实现
  • 解决了公网部署中恶意扫描导致 端口耗尽 的实际问题
  • 循环引用通过 weak_ptr 正确解除

上述发现的问题都是低风险优化项,不影响正确性。建议合并。

@xia-chu

xia-chu commented Jul 23, 2026

Copy link
Copy Markdown
Member

@taotaobujue2008 上述是千问3.7max的评论 您看下有没有改进空间?

@baigao-X baigao-X left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 感谢补充修正,上述意见您看下是否可以优化下。

Comment thread webrtc/IceSession.hpp Outdated
Use Ticker for ICE idle tracking, validate TURN allocation ownership and retransmissions, and add allocation regression coverage.

Plan-Item: ICEBUGFIX-REVIEW
@alexliyu7352
alexliyu7352 requested a review from Copilot July 28, 2026 14:40

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7833e00e4d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread webrtc/IceTransport.cpp

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the WebRTC ICE/TURN implementation against abnormal or malicious ICE sessions that can linger and leak UDP sessions and TURN relay ports, by introducing idle timeouts and more robust TURN allocation lifecycle management.

Changes:

  • Added iceSessionTimeoutSec configuration (default 60s) and enforced UDP ICE session idle shutdown to reclaim resources.
  • Improved TURN allocation handling: allocation mismatch handling (437), refresh/release logic, periodic allocation timeout cleanup, and removal of relay-session registry races via mutex protection.
  • Added a dedicated TURN allocation behavior test (test_turn_allocation) and updated test filtering when WebRTC target is unavailable.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
webrtc/WebRtcTransport.h Declares new config key kIceSessionTimeoutSec.
webrtc/WebRtcTransport.cpp Defines new config key and default value in ini initialization.
webrtc/USAGE.md Documents iceSessionTimeoutSec usage.
webrtc/StunPacket.hpp Corrects TURN Allocation Mismatch error code to 437.
webrtc/IceTransport.hpp Extends IceServer with allocation lifecycle helpers, weak refs, and timeout hooks.
webrtc/IceTransport.cpp Implements TURN allocation timeout cleanup, safer relay forwarding, and adds mutex for relay registry.
webrtc/IceSession.hpp Adds an activity ticker to track UDP session idleness.
webrtc/IceSession.cpp Resets activity ticker on receive; closes idle UDP sessions while respecting active allocations.
tests/test_turn_allocation.cpp Adds coverage for Allocate/Refresh behavior, mismatch handling, and capacity failures.
tests/CMakeLists.txt Skips the new test when WebRTC target is not built.
conf/config.ini Adds documented iceSessionTimeoutSec setting to the shipped config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_turn_allocation.cpp
@xia-chu

xia-chu commented Jul 31, 2026

Copy link
Copy Markdown
Member

@baigao-X 看起来可以合并pr了?

@taotaobujue2008

Copy link
Copy Markdown
Contributor Author

会导致 TURN relay 会在 600 秒后中断。
我再优化一版

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.

4 participants