使用Elixir与Erlang :ssl模块获取SSL证书时连接报错如何解决
问题原因
你遇到的报错是因为tls_certificate_check.options(host)返回的配置列表中包含了socket_options嵌套字段,而Erlang的:ssl.connect/4的第三个参数仅接受平层的TLS专属配置,不识别嵌套的socket_options这类底层TCP socket配置,因此抛出了选项格式错误。
修复方案
你需要先拆分tls_certificate_check返回的配置,把socket_options下的内容提取到平层,再传入:ssl.connect即可。修正后的代码如下:
defmodule ElixirSslCheck do def check do host = "www.lawlorbagcal.org" all_opts = :tls_certificate_check.options(host) # 拆分socket配置和TLS配置 socket_opts = Keyword.get(all_opts, :socket_options, []) tls_opts = Keyword.delete(all_opts, :socket_options) # 拼接为平层配置传入连接方法 :ssl.connect(host, 443, socket_opts ++ tls_opts, 5000) end # 补充:连接成功后获取证书到期时间的实现 def get_cert_expiry do case check() do {:ok, socket} -> # 获取对端证书 {:ok, der_cert} = :ssl.peercert(socket) # 解码DER格式证书为OTP结构化数据 {:OTPCertificate, tbs_cert, _, _} = :public_key.pkix_decode_cert(der_cert, :OTPCertificate) # 提取有效期字段 {:Validity, _not_before, not_after} = elem(tbs_cert, 1) |> elem(4) # 转换ASN.1时间格式为可读字符串 expiry_str = not_after |> elem(1) |> List.to_string() :ssl.close(socket) {:ok, expiry_str} error -> error end end end
额外调试建议
- 先确认你的Erlang/OTP版本和
tls_certificate_check版本兼容,OTP 25及以上版本建议使用tls_certificate_check1.20.0以上版本,避免版本不兼容导致的选项错误。 - 如果连接依然失败,可以临时在
tls_opts中添加verify: :verify_none测试网络连通性,确认是否是证书验证逻辑导致的问题,该配置仅用于调试,生产环境必须删除。
内容的提问来源于stack exchange,提问作者wgwz
相关产品推荐
相关产品推荐

