纯Node.js服务器启用HTTPS时遭遇ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误
纯Node.js HTTPS服务器出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误的排查与解决
我在纯Node.js(未使用Express)服务器上配置HTTPS,用OpenSSL生成ED25519密钥和证书后,浏览器访问时出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误。已经尝试将CA证书与服务器证书的Common Name设为不同值,但问题依旧。
证书生成命令
# 生成私钥 openssl genpkey -algorithm ed25519 -outform pem -out ca_pvt_key.pem openssl genpkey -algorithm ed25519 -outform pem -out server_pvt_key.pem # 生成证书 openssl req -inform pem -key ca_pvt_key.pem -days 36000 -x509 -config openssl-ca.cnf -nodes -outform pem -out ca_cert.pem openssl x509 -outform der -in ca_cert.pem -out ca_cert.crt # 创建服务器证书请求(SCR) openssl req -new -config openssl-server.cnf -key server_pvt_key.pem -nodes -outform pem -out server_certificate.csr # 创建OpenSSL CA所需文件 touch index.txt echo '01' > serial.txt # 生成签名后的最终证书 openssl ca -config openssl-ca.cnf -notext -policy signing_policy -extensions signing_req -out server_certificate.pem -infiles server_certificate.csr openssl ca -config openssl-ca.cnf -notext -policy signing_policy -extensions signing_req -out server_certificate.crt -infiles server_certificate.csr cat server_certificate.pem > cert_chain.pem cat ca_cert.pem >> cert_chain.pem
CA配置文件片段
[ ca_extensions ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer basicConstraints = critical, CA:true keyUsage = keyCertSign, cRLSign
服务器证书配置文件片段
#################################################################### [ server_req_extensions ] subjectKeyIdentifier = hash basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment subjectAltName = @alternate_names nsComment = "OpenSSL Generated Certificate" #################################################################### [ alternate_names ] DNS.1 = localhost # IPv4 localhost IP.1 = 127.0.0.1 # IPv6 localhost IP.2 = ::1
Node.js服务器代码片段
const port = 3000; const options = { host: "localhost", port: port, path: "/", rejectUnauthorized: false, requestCert: true, agent: false, key: fs.readFileSync(path.join(path.resolve(__dirname, "../../"), "/certs/server_pvt_key.pem")), cert: fs.readFileSync(path.join(path.resolve(__dirname, "../../"), "/certs/cert_chain.pem")), }; const server = https.createServer(options, (req, res) => { // 纯Node.js服务器逻辑 });
系统环境与额外操作
- 运行环境:OpenSUSE Tumbleweed的Podman容器,宿主系统为Ubuntu 22.04LTS
- 已执行操作:
- 将
ca_cert.crt添加到Ubuntu的/usr/local/share/ca-certificates目录并更新证书信任 - 将
server_certificate.crt放入/etc/ssl/certs,server_pvt_key.pem放入/etc/ssl/private
- 将
测试情况
curl可以正常获取网站HTML内容- Brave浏览器访问时触发
ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误 - 尝试将
ca_cert.pem或ca_cert.crt导入Brave的"Authorities"标签时失败
问题原因与解决方法
1. 服务器配置参数混杂错误
你的options对象混入了客户端请求参数(host、port、path、agent),而https.createServer的第一个参数仅需服务器端TLS配置,多余参数会导致初始化异常。
修正后的配置:
const options = { rejectUnauthorized: false, // 测试用,生产环境建议设为true requestCert: true, key: fs.readFileSync(path.join(path.resolve(__dirname, "../../"), "/certs/server_pvt_key.pem")), cert: fs.readFileSync(path.join(path.resolve(__dirname, "../../"), "/certs/cert_chain.pem")), }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('HTTPS Server Running'); }); server.listen(port, () => { console.log(`Server listening on port ${port}`); });
2. ED25519密钥的兼容性问题
ED25519椭圆曲线算法部分浏览器或Node.js TLS配置支持有限,易引发握手失败。
临时验证方案:改用RSA密钥重新生成证书:
# 生成RSA私钥 openssl genrsa -out ca_pvt_key.pem 2048 openssl genrsa -out server_pvt_key.pem 2048
重新执行后续证书生成步骤后测试浏览器访问。
3. 证书导入与信任问题
Brave导入失败大概率是格式问题,可将CA证书转换为PKCS#12格式后导入:
openssl pkcs12 -export -out ca_cert.p12 -in ca_cert.pem -inkey ca_pvt_key.pem
导入.p12文件到Brave"Authorities",并设置信任该CA颁发的证书。
同时验证证书链有效性:
openssl verify -CAfile ca_cert.pem server_certificate.pem
确保服务器证书能被CA证书正确验证。
4. TLS协议与密码套件配置
Node.js默认TLS配置可能禁用了部分浏览器兼容的套件,可显式指定:
const options = { // 其他配置... minVersion: 'TLSv1.2', ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384', };
内容的提问来源于stack exchange,提问作者RaxOroX
相关产品推荐
相关产品推荐

