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

Erlang SSL sni_fun回调证书适配问题求助

嘿,我之前也碰到过Erlang SSL模块SNI回调相关的坑,咱们一步步来拆解你的问题:

问题1:初始的server_has_no_suitable_certificates错误

你提到回调函数返回[{cacerts, [Cert]}]但触发了certificate_chain(undefined, _, _) -> {error, no_cert}分支,核心原因是你返回的选项不完整——SNI回调需要返回服务器用于握手的完整SSL配置选项,其中必须包含服务器自身的证书(cert)和对应私钥(key),而你只返回了CA证书(cacerts)。

OTP的certificate_chain函数会检查回调返回的选项中是否存在cert字段,如果找不到,就会认为没有可用的服务器证书,直接返回no_cert错误。

正确的回调返回格式应该包含服务器证书、私钥(如果需要证书链的话再加cacerts),示例如下:

YourSniCallback(Hostname, _HelloMsg) ->
    % 根据SNI主机名加载对应的证书和私钥
    {ok, ServerCertDer} = file:read("/path/to/your/server-cert.der"),
    {ok, ServerKeyDer} = file:read("/path/to/your/server-key.der"),
    {ok, CaCertDer} = file:read("/path/to/your/ca-cert.der"),
    % 返回完整的SSL选项列表
    {ok, [
        {cert, ServerCertDer},
        {key, ServerKeyDer},
        {cacerts, [CaCertDer]}
    ]}.
问题2:OTP 20.3下的malformed_handshake_data错误及排查方法

这个错误是OTP在TLS握手的try-catch块中捕获到未预期的异常后,转换为的通用握手失败告警。要拿到具体的异常信息,你可以用这几个方法:

  • 开启SSL调试日志:
    在应用启动时设置SSL的调试级别为all,这样会输出详细的握手流程和异常栈信息:

    % 启动前设置
    application:set_env(ssl, debug, all),
    % 或者运行时动态调整
    ssl:set_debug(all).
    

    日志里会包含具体的异常类型、原因和调用栈,能直接定位问题。

  • 在SNI回调中主动捕获异常:
    给你的回调函数加上try-catch包裹,打印内部异常,确认是不是回调逻辑本身抛出了错误:

    YourSniCallback(Hostname, HelloMsg) ->
        try
            % 你的原有证书加载逻辑
            {ok, ServerCertDer} = file:read("/path/to/your/server-cert.der"),
            {ok, ServerKeyDer} = file:read("/path/to/your/server-key.der"),
            {ok, CaCertDer} = file:read("/path/to/your/ca-cert.der"),
            {ok, [{cert, ServerCertDer}, {key, ServerKeyDer}, {cacerts, [CaCertDer]}]}
        catch
            Type:Reason:Stacktrace ->
                % 打印异常到日志
                error_logger:error_msg(
                    "SNI callback failed for hostname ~p: ~p:~p~nStacktrace: ~p~n",
                    [Hostname, Type, Reason, Stacktrace]
                ),
                % 返回合法错误值,避免触发更严重的异常
                {error, no_cert}
        end.
    
  • 验证证书与私钥的匹配性:
    虽然你说证书正常,但还是要确认服务器证书和私钥是配对的,用OpenSSL命令验证:

    # 提取证书的模数并计算MD5
    openssl x509 -noout -modulus -in server-cert.pem | openssl md5
    # 提取私钥的模数并计算MD5
    openssl rsa -noout -modulus -in server-key.pem | openssl md5
    

    两个命令的输出MD5值必须完全一致,否则证书和私钥不匹配,会导致握手失败。


内容的提问来源于stack exchange,提问作者Cuong Truong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:57:18