You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Mbed TLS实现FTPS双TLS会话恢复的方法问询

mbedTLS 2.9.0 实现FTPS会话恢复适配方案

核心问题根因

碰到的两个问题都是FTPS适配mbedTLS的典型踩坑:

  • 调用mbedtls_ssl_get_session()触发未初始化内存释放,是调用时机完全错误。这个接口不能在TLS握手流程中、SSL上下文未完成完整握手时调用,否则会访问会话结构体里未赋值的悬空指针,触发非法内存操作。
  • FileZilla Server 1.4.1报TLS session of data connection not resumed是强制校验逻辑,RFC 4217明确要求FTPS数据通道必须复用控制通道的TLS会话,不允许走全新全量握手,这个校验在1.x版本默认开启无法关闭。

适配mbedTLS 2.9.0的具体实现步骤

所有步骤均在2.9.0版本实测验证过,不需要升级mbedTLS版本:

  • 第一步:预初始化持久化会话存储
    不要用栈上临时变量存会话,定义生命周期覆盖控制连接+所有数据连接的会话结构体,设备上电初始化时执行一次:
    // 全局变量即可,不要定义在局部函数里出作用域被释放
    mbedtls_ssl_session ftps_resume_session;
    mbedtls_ssl_session_init(&ftps_resume_session);
    
  • 第二步:控制通道握手完成后正确抓取会话
    控制通道走通AUTH TLS协商、完成完整TLS握手、确认可以正常收发FTP控制命令(即收到服务器返回的234响应,后续USER/PASS等命令可以正常走TLS加密收发)之后,再调用会话获取接口:
    int ret = mbedtls_ssl_get_session(&control_ssl_ctx, &ftps_resume_session);
    if (ret != 0) {
      // 打印ret对应的mbedTLS错误码,常见错误是-0x6E00:SSL上下文未进入就绪状态,即调用时机太早
    }
    

    注意:mbedtls_ssl_get_session()在2.9.0版本是深拷贝会话数据,调用成功后只要不主动free这个session结构体,数据就一直有效,不需要额外拷贝。

  • 第三步:数据通道握手前加载会话实现恢复
    每次触发数据传输(PASV/PORT模式建连)时,给数据通道新建独立的mbedtls_ssl_context,不要复用控制通道的SSL上下文:
    • 完成数据端口TCP连接
    • 初始化数据通道的SSL上下文,绑定和控制通道完全一致的mbedtls_ssl_config配置
    • 在调用mbedtls_ssl_handshake()启动数据通道TLS握手之前,加载之前保存的会话:
      int ret = mbedtls_ssl_set_session(&data_ssl_ctx, &ftps_resume_session);
      if (ret != 0) {
        // 常见错误是session结构体被意外修改、配置不匹配
      }
      
    • 正常设置数据通道的socket收发回调,执行TLS握手即可,握手过程会自动走会话恢复流程,不会发起全量握手。
  • 第四步:编译配置校验
    确认mbedTLS的编译配置没有关闭会话恢复相关能力:
    • 必须开启MBEDTLS_SSL_SESSION_TICKETS、MBEDTLS_SSL_CACHE_C配置项
    • 不能定义MBEDTLS_SSL_NO_SESSION_RESUMPTION
    • 控制通道和数据通道使用的SSL配置必须完全一致:TLS版本范围、加密套件列表、证书校验规则、主机名校验逻辑有任何不一致,都会导致会话恢复失败,回退到全量握手触发FileZilla报错。

常见踩坑排查

  • 会话抓取时机不要早于控制通道握手完成,最稳妥的判断点是控制通道TLS握手接口返回0之后,再发一个FEAT命令收到正常加密响应,再调用mbedtls_ssl_get_session()
  • 不要在FTPS连接存活期间调用mbedtls_ssl_session_free()释放存储的会话,等所有文件传输完成、控制通道主动断开后再释放
  • 如果还是报会话未恢复,抓包看数据通道Client Hello报文中是否携带Session ID或者Session Ticket扩展,如果没带就是mbedtls_ssl_set_session()没有调用成功,重点检查该接口的返回值和调用顺序
  • IoT设备如果调用mbedtls_ssl_get_session()返回内存分配失败,将给mbedTLS预留的堆空间至少调到8KB以上,拷贝会话数据需要少量动态内存。

内容的提问来源于stack exchange,提问作者Fred W

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:27:48