需显式将自签名证书(cert.pem)加载为rootcas信任根,并确保含subjectaltname扩展、pem格式规范、私钥未加密,否则tls校验失败。

用 crypto/tls 加载自签名证书时提示 “x509: certificate signed by unknown authority”
这不是证书生成错了,而是客户端默认不信任自签名证书。Go 的 http.Client 和 tls.Dial 都会校验服务端证书链,而自签名证书没有上级 CA,必须显式告诉 TLS 客户端“这个根证书我信”。
- 服务端不需要额外配置,只要提供
cert.pem和key.pem即可启动 HTTPS - 客户端必须用
tls.Config{RootCAs: ...}加载自签名证书的公钥(即cert.pem)作为信任根 - 别把私钥当 CA 加进去——
RootCAs只接受*x509.CertPool,内容是 PEM 编码的证书(不是密钥) - 常见错误:直接读
cert.pem后没调用AppendCertsFromPEM(),导致RootCAs为空
用 openssl 生成兼容 Go 的自签名证书(非 x509v3 扩展失败)
Go 的 crypto/tls 对证书要求比浏览器更严格:必须包含 subjectAltName(哪怕只是 localhost),否则握手会因 SNI 不匹配失败,尤其在 macOS 或新版 Go 中更明显。
- 不要用
openssl req -new -x509简单命令,它默认不写 SAN - 必须加配置文件或命令行参数注入
subjectAltName = DNS:localhost,IP:127.0.0.1 - 密钥长度建议 2048 位以上;Go 1.19+ 已弃用 SHA-1,签名算法必须用
sha256WithRSAEncryption(OpenSSL 默认已满足) - 示例关键命令:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3650 -nodes -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
Go 代码里用 tls.X509KeyPair 加载失败:“tls: failed to find any PEM data in certificate input”
错误几乎全是 PEM 格式问题:Go 的 tls.X509KeyPair 要求证书和私钥都必须是标准 PEM 块,且不能有多余空行、BOM、注释或 Windows 换行符(\r\n)。
- 检查
cert.pem是否以-----BEGIN CERTIFICATE-----开头,以-----END CERTIFICATE-----结尾,中间只有 Base64 字符和换行 - 私钥文件同理,但必须是
-----BEGIN PRIVATE KEY-----(PKCS#8)或-----BEGIN RSA PRIVATE KEY-----(传统 PKCS#1);Go 不支持加密私钥(带 passphrase 的) - 用
file, _ := os.ReadFile("cert.pem"); fmt.Printf("%q", file[:20])看开头是不是"-----BEGIN ",避免隐藏字符 - Windows 上用记事本保存容易出 BOM,推荐用 VS Code 或
dos2unix cert.pem key.pem
想让本地开发服务同时支持 HTTP 和 HTTPS,但 http.Server 启动两个端口太啰嗦
没必要硬写两个 http.Server 实例。更轻量的做法是用 HTTP 重定向 + 单 TLS Server,或者用反向代理中转。但要注意:Go 标准库不支持一个 http.Server 同时监听 HTTP 和 HTTPS。
- 最简方案:启动一个 HTTPS server(如 :8443),再启动一个 HTTP server(如 :8080)只做 301 跳转到 HTTPS 地址
- 跳转代码里别写死域名,用
r.Host和r.URL.Path构造目标 URL,避免跨域或路径丢失 - 如果用
net/http/httputil.NewSingleHostReverseProxy做代理,注意设置Director修改URL.Scheme为https,否则后端收到的是 http 请求 - 开发时别关掉 HTTP 端口就直接上 HTTPS——浏览器缓存 HSTS 头后可能再也打不开 HTTP 版本
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











