RPC 安全需 TLS 证书校验与 Token 鉴权双重保障:服务端须用 tls.Listen 配置有效证书链,客户端必须用含 RootCAs 的 tls.Config 拨号;Token 应嵌入 Args 并在方法内用 HMAC-SHA256+时间戳校验。

RPC连接建立前必须校验 TLS 证书有效性
Go 的 net/rpc 本身不提供加密或认证能力,所有安全机制都依赖底层传输层。若用 http.Serve 或自定义 net.Listener 暴露 RPC 服务,必须强制使用 TLS,并在客户端严格验证服务端证书。跳过 tls.Config.InsecureSkipVerify = true 是最常见也最危险的错误——它会让中间人攻击完全失效。
- 服务端启动时需传入
tls.Listen("tcp", addr, tlsConfig),其中tlsConfig.Certificates至少包含一个有效证书链 - 客户端必须用
tls.Dial("tcp", addr, &tls.Config{RootCAs: caPool}),不能用空&tls.Config{} - 若用自签名证书,务必把 CA 证书加载进
x509.CertPool,而非直接调用AppendCertsFromPEM后忽略返回值
如何在 RPC 方法调用前插入 Token 鉴权逻辑
Go 标准库的 net/rpc 不支持拦截器(middleware),无法像 HTTP 那样挂载鉴权中间件。可行方案是将认证逻辑下沉到每个 func(*Args, *Reply) error 方法内部,或封装一层代理结构体。
- 推荐在
Args结构体中嵌入Token string字段,服务端方法开头统一校验:if !isValidToken(args.Token) { return errors.New("invalid token") } - 避免在
Server.Register后动态修改方法行为——net/rpc的注册是静态的,没有钩子可插 - Token 验证建议用 HMAC-SHA256 + 时间戳防重放,不要仅比对固定字符串
为什么不用 JSON-RPC over HTTPS 而坚持用 gob+TLS
虽然 JSON-RPC 更易调试,但在 Go 生态中混用会引入额外风险点:编码兼容性、类型丢失、HTTP 头注入、以及更复杂的错误传播路径。而 gob 编码 + TLS 是 Go 原生最可控的组合。
-
gob支持私有字段导出控制,且默认拒绝未导出字段序列化,天然减少敏感数据误传 - HTTP 层的
Content-Type、Authorization等头可能被反向代理篡改或忽略;TLS 直连则绕过所有中间 HTTP 组件 - 若必须用 JSON-RPC,应禁用
http.DefaultServeMux,改用独立http.Serve并关闭所有非POST方法
package main
import (
"crypto/tls"
"net/rpc"
"net/rpc/jsonrpc"
)
func main() {
// 客户端示例:强制校验证书
config := &tls.Config{
RootCAs: caPool, // 必须非 nil
}
conn, _ := tls.Dial("tcp", "api.example.com:8443", config)
client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
}
证书校验和 Token 解析这两步缺一不可。前者保传输,后者保身份——哪怕 TLS 握手成功,Token 过期或伪造仍会导致越权调用。










