服务端必须使用TLS监听而非明文监听,客户端需显式加载RootCAs并禁用InsecureSkipVerify,自签名证书须含SAN,mTLS需双向配置ClientAuth与ClientCAs。

服务端必须用 http.ListenAndServeTLS 或 tls.Listen 启动,不能只加加密逻辑
明文监听器(如 http.ListenAndServe 或 net.Listen("tcp", ":8080"))无论 handler 里怎么 AES 加密 body,都绕过了 TLS 的密钥协商、证书校验和完整性保护。协议层就是裸奔。
-
http.ListenAndServeTLS(":443", "server.crt", "server.key", handler)最简方式,但要求server.crt必须含服务器证书 + 中间 CA(如 Let’s Encrypt 的 fullchain.pem),不能只放域名证书 - 若需自定义超时或中间件,改用
http.Server实例,设置TLSConfig字段后调用srv.ListenAndServeTLS("", ""),空字符串表示复用文件路径 - TCP/自定义协议场景用
tls.Listen("tcp", ":8443", &tls.Config{Certificates: []tls.Certificate{cert}}),其中cert来自tls.LoadX509KeyPair("server.crt", "server.key") - 私钥文件权限必须 ≤
0600(chmod 0600 server.key),否则crypto/tls会静默拒绝加载
客户端必须显式加载 RootCAs,InsecureSkipVerify: true 是裸奔开关
Go 不自动信任系统根证书池,也不会读取当前目录下的 ca.crt。漏掉 RootCAs 是最常见错误,直接导致 x509: certificate signed by unknown authority。
- 先读取 CA 文件:
caCert, _ := os.ReadFile("ca.crt") - 构建证书池:
caPool := x509.NewCertPool(),再调用caPool.AppendCertsFromPEM(caCert) - HTTP 客户端:
&http.Transport{TLSClientConfig: &tls.Config{RootCAs: caPool}} - TCP/gRPC 客户端:
tls.Dial("tcp", "host:8443", &tls.Config{RootCAs: caPool})或grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{RootCAs: caPool})) -
InsecureSkipVerify: true仅限本地调试,CI/CD 应扫描拦截该字段——它会让 SNI、ALPN 全部失效,等同于 HTTP 明文
自签名证书必须带 subjectAltName(SAN),否则 gRPC/HTTP2 握手直接失败
gRPC 基于 HTTP/2,Go 的 crypto/tls 自 1.19 起强制校验 SAN。OpenSSL 默认生成的证书不含 SAN,客户端会报 x509: cannot validate certificate for localhost because it doesn't contain any IP SANs。
- 生成前准备
openssl.conf,在[req_ext]下写subjectAltName = @alt_names,再新增[alt_names]段,例如:DNS.1 = localhost、IP.1 = 127.0.0.1 - 命令中必须显式引用配置:
openssl req -x509 -config openssl.conf -days 3650 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -subj "/CN=localhost" - Kubernetes 环境还需加 Service DNS 名:
DNS.2 = mysvc.default.svc.cluster.local - 证书内容必须是 PEM 格式,且
RootCAs只接受-----BEGIN CERTIFICATE-----块,不能塞私钥或中间证书
mTLS 双向认证要配对生效:ClientAuth 和 ClientCAs 缺一不可
mTLS 不是“双方都带证书”就行。服务端不校验,客户端白交;客户端不提供,服务端无从校验。错配会导致单向或静默放行。
立即学习“go语言免费学习笔记(深入)”;
- 服务端
tls.Config必须设:ClientAuth: tls.RequireAndVerifyClientCert,且ClientCAs: caPool(此处caPool是用于验证客户端证书的 CA 根) - 客户端发起连接时,必须在
tls.Config中提供自己的证书+私钥:Certificates: []tls.Certificate{clientCert},其中clientCert来自tls.LoadX509KeyPair("client.crt", "client.key") - gRPC 服务端用
credentials.NewServerTLSFromCert(serverCert),客户端用credentials.NewClientTLSFromCert(pool, "server-name") - 若服务端只设
ClientAuth: tls.RequireAnyClientCert但没配ClientCAs,实际效果等同于不校验


















