RPC 安全需 TLS 证书校验与 Token 鉴权双重保障:服务端须用 tls.Listen 配置有效证书链,客户端必须用含 RootCAs 的 tls.Config 拨号;Token 应嵌入 Args 并在方法内用 HMAC-SHA256+时间戳校验。
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{}
x509.CertPool,而非直接调用 AppendCertsFromPEM 后忽略返回值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 的注册是静态的,没有钩子可插虽然 JSON-RPC 更易调试,但在 Go 生态中混用会引入额外风险点:编码兼容性、类型丢失、HTTP 头注入、以及更复杂的错误传播路径。而 gob 编码 + TLS 是 Go 原生最可控的组合。
gob 支持私有字段导出控制,且默认拒绝未导出字段序列化,天然减少敏感数据误传Content-Type、Authorization 等头可能被反向代理篡改或忽略;TLS 直连则绕过所有中间 HTTP 组件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 过期或伪造仍会导致越权调用。