Rails访问有效Let's Encrypt证书站点报SSL验证失败如何解决
修复方案
问题根源
该报错由2021年9月30日Let's Encrypt旧根证书DST Root CA X3过期导致,OpenSSL 1.0.2版本存在逻辑缺陷,无法自动跳过过期的交叉签名根证书,即便目标站点证书本身有效,也会抛出校验失败错误。
分步修复操作
第一步:移除系统内置的过期根证书
执行以下两条命令,把过期的DST Root CA X3证书从系统CA信任列表中拉黑并更新证书库:
sudo sed -i 's/^mozilla\/DST_Root_CA_X3.crt/!mozilla\/DST_Root_CA_X3.crt/g' /etc/ca-certificates.conf sudo update-ca-certificates
执行完成后可以先通过命令行验证有效性:openssl s_client -connect 你的目标站点域名:443
如果返回结果中Verify return code为0 (ok),说明系统级证书问题已经修复。
第二步:适配Ruby/Rails应用的证书配置
如果第一步完成后应用仍然报错,是因为Ruby的Net::HTTP默认没有调用系统CA证书库,需要手动指定路径:
你可以直接修改请求代码,在http.use_ssl = true后新增CA文件配置:
def get_request url uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true # 新增行:指定系统CA证书路径 http.ca_file = '/etc/ssl/certs/ca-certificates.crt' #more than 10 seconds this is too slow http.open_timeout = 10 http.read_timeout = 10 request = Net::HTTP::Get.new(uri.request_uri) response = http.request(request) if response.code.to_i == 200 return true else puts "Failed to GET #{url}: #{response.code.to_i}" return false end end
如果不想逐个修改请求代码,可以在Rails应用启动时配置全局环境变量SSL_CERT_FILE,值为/etc/ssl/certs/ca-certificates.crt,可以写入应用的启动脚本、服务配置文件或者用户profile中,生效后所有Ruby发起的SSL请求都会自动调用系统CA库。
可选长期方案
Ubuntu 16.04已经停止官方维护,OpenSSL 1.0.2也不再更新,后续还可能遇到其他加密兼容性问题,建议择机升级系统到20.04及以上长期支持版本,从底层解决兼容性缺陷。
内容的提问来源于stack exchange,提问作者Julien
相关产品推荐
相关产品推荐

