在 Erlang/OTP 27 下如何启用“tlsv1.3”并禁用旧版本?
解读
面试官抛出这道题,并不是想听你背文档,而是考察三件事:
- 你是否真的在生产环境给 CouchDB 升过级、配过 TLS,而不是纸上谈兵;
- 对 Erlang/OTP 27 的 ssl 应用默认行为变化 是否敏感(OTP 27 默认把 tlsv1 与 tlsv1.1 彻底踢出默认列表,但 tlsv1.2 仍保留,必须显式禁用 才能“纯 1.3”);
- 能否把 OTP 层面的参数与 CouchDB 的 ini 风格配置 无缝衔接,并兼顾国内常见“国密合规、等保 2.0、移动弱网”场景。
一句话:既要让 Erlang 的 ssl 只谈 1.3,又要让 CouchDB 的所有 HTTP 监听端口(5984/6984/4369 等)统一生效,且重启无感。
知识点
- Erlang/OTP 27 的 ssl 应用把
supported与available彻底拆分;只有出现在versions列表里的才能被协商。 - CouchDB 2.3+ 以后,所有 TLS 参数透传至
ssl:listen/2,因此直接在local.ini里写[ssl]段即可,无需改源码。 - 国内机房常见陷阱:
- 老版本 HAProxy/ELB 仍发 TLS 1.0 ClientHello,会导致握手失败,需提前升级;
- 国密双证书场景下,如果启用
tlsv1.3,目前只有 GM/T 0024 的实验分支支持,生产仍需回退到 1.2,回答时要指出边界。
- 禁用 1.2 的副作用:Chrome 95-97 及部分安卓 10 机型默认不启 1.3,需评估用户占比。
答案
分三步落地,全部在运维侧完成,不改 CouchDB 源码,灰度重启即可。
第一步:确认 Erlang/OTP 27 已编译进系统
couchdb@node1> erl -eval 'io:format("~s~n",[erlang:system_info(otp_release)]),halt().'
27
若输出不是 27,切勿硬升,否则 ssl 应用行为对不上。
第二步:在 local.ini 末尾追加 [ssl] 段,只留 tlsv1.3
[ssl]
port = 6984
certfile = /etc/couchdb/cert/rsa_crt.pem
keyfile = /etc/couchdb/cert/rsa_key.pem
; 关键行
tls_versions = ['tlsv1.3']
; 彻底关掉 1.2 以下
ciphers = ["TLS_AES_256_GCM_SHA384","TLS_CHACHA20_POLY1305_SHA256","TLS_AES_128_GCM_SHA256"]
; 国内等保要求前向保密,把 DH 文件也配上
dhfile = /etc/couchdb/cert/dhparam.pem
; 关闭客户端重协商,防 DOS
secure_renegotiate = true
client_renegotiation = false
保存后执行 热加载(CouchDB 2.3+ 支持):
curl -X POST http://127.0.0.1:5986/_node/_local/_config/_reload
观察 ssl:listen 返回,确认 无 tlsv1.2 出现在 negotiated 列表。
第三步:集群滚动重启,验证外部端口
nmap --script ssl-enum-ciphers -p 6984 couchdb.xxx.com
输出里 只能看到 TLSv1.3 三条 AES 套件,出现任何 TLSv1.2 套件即回滚。
若使用 HAProxy 四层代理,一定在 bind 行追加 ssl-min-ver TLSv1.3,否则前端转发会握手失败。
拓展思考
- 如果未来 CouchDB 4.x 把 erlang-ssl 改成 quic-transport,今天这套
tls_versions写法会整体失效,需要把配置迁移到quic_tls_config段,如何设计平滑迁移脚本? - 国内金融云要求 双证书(RSA+SM2)共存,但 SM2 仅在 TLSv1.2 扩展,如何在同一端口做版本分流?(提示:可借助 Erlang 的
customize_hostname_check回调,在ClientHello阶段根据supported_groups决定证书链,实现 1.3 走 RSA,1.2 走 SM2)。 - 移动端离线同步场景,PouchDB 在 React-Native 里默认禁掉 TLSv1.3(因底层 OkHttp 版本),你是否愿意为了兼容而保留 1.2?还是强制用户升级?请给出数据驱动的决策模型(DAU 损失 ≤ 1% 则强升,否则降级)。