必须用app.listentls,不能套http.listenandservetls;fiber的*fiber.app不实现http.handler接口,硬传会编译失败或panic;正确方式是app.listentls(":443", "fullchain.pem", "key.pem"),且需确保证书链完整、私钥未加密、换行符为lf、权限0600,并为自签名证书添加subjectaltname扩展。

必须用 app.ListenTLS,不能套 http.ListenAndServeTLS
Fiber 的 *fiber.App 不实现标准库 http.Handler 接口,硬传给 http.ListenAndServeTLS 会直接编译失败或 panic:cannot use app (type *fiber.App) as type http.Handler。这不是参数写错或漏导包的问题,是 Go 类型系统在拦截。唯一正确入口是 app.ListenTLS(":443", "fullchain.pem", "key.pem")。
fullchain.pem 和 key.pem 的格式要求极严
两个文件任一出错都会静默失败或 TLS 握手卡住,日志几乎不报具体原因:
-
fullchain.pem必须包含:域名证书 + 所有中间 CA 证书(如 Let’s Encrypt 的chain.pem);只放cert.pem会导致 iOS/Java 客户端报x509: certificate signed by unknown authority;合并命令:cat cert.pem chain.pem > fullchain.pem -
key.pem必须未加密(不能是openssl genrsa -aes256直接生成的),否则握手阶段无响应;解密命令:openssl rsa -in key.pem.enc -out key.pem - 两个文件换行符必须为 LF(Unix 风格),含 CRLF 会报
tls: failed to find any PEM data;修复命令:dos2unix fullchain.pem key.pem - Linux 下私钥权限建议设为
0600;Go 标准库crypto/tls会拒绝加载0644权限的私钥,Fiber 不校验但底层会静默退出
自签名证书调试时 Chrome 拒绝连接?缺 subjectAltName
Chrome 90+ 对自签名证书要求更严格,仅 CN 匹配已不够。生成时必须显式添加 SAN 扩展:
- 命令示例:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -addext "subjectAltName = DNS:localhost,IP:127.0.0.1" - 注意同时覆盖
DNS和IP,否则访问https://localhost:443或https://127.0.0.1:443都会报ERR_CERT_COMMON_NAME_INVALID - 此时
cert.pem已含完整链,可直接当fullchain.pem用,但保持文件名一致更稳妥
需要自定义 http.Server 字段(如超时)?用 app.Listener()
app.ListenTLS 封装了默认 http.Server,若需设置 ReadTimeout、WriteTimeout 或 IdleTimeout,必须手动构造:
- 调用
ln, err := app.Listener("tcp", ":443")获取监听器 - 创建自定义
http.Server,把app.Handler()传给Handler字段(注意:Fiber v3 起才提供app.Handler(),v2 不支持) - 再调
srv.ListenAndServeTLS("fullchain.pem", "key.pem") - 别试图用
app.Serve(ln, ...)—— 它不支持 TLS,只处理已建立的连接
curl -v https://localhost:443 看 TLS 握手是否完成,再查服务是否响应,别一上来就埋头改代码。











