NATS 安全 TLS 配置

FreeGuideOnline 最新 2026-07-13

NATS 安全通信:TLS 配置完整指南

在分布式系统中,通过公网或不受信任的网络传输消息时,保护数据传输的机密性和完整性至关重要。NATS 提供了内置的 TLS(传输层安全)支持,可以轻松加密客户端与服务器之间、路由链路以及叶节点链路的所有通信。本教程面向初学者,将带你从零开始完成 NATS 的 TLS 配置,涵盖证书生成、服务端设置、客户端连接以及常见问题排查。

什么是 NATS 中的 TLS?

TLS 在 NATS 中主要用于以下三种场景:

  1. 客户端到服务器(Client-to-Server):加密客户端与 NATS 服务器之间的 TCP 连接。
  2. 服务器到服务器(Route):加密集群中服务器之间的路由连接。
  3. 叶节点(Leaf Node):加密叶节点与上级集群之间的连接。

本教程以最常见的客户端到服务器加密为例,使用的配置思路同样适用于其他场景。

第一步:准备 TLS 证书

你需要一个数字证书和对应的私钥。在生产环境中,建议使用受信任的 CA(证书颁发机构)签发的证书。在开发或测试环境中,我们可以用 opensslcert-manager 等工具生成自签名证书。

1. 使用 OpenSSL 生成自签名证书

安装 OpenSSL(通常系统自带,否则使用包管理器安装)后,执行以下命令。

# 1. 生成 CA 私钥及自签名根证书(可选,便于签发服务端/客户端证书)
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=MyNatsCA"

# 2. 生成 NATS 服务器私钥
openssl genrsa -out server.key 2048

# 3. 生成证书签名请求(CSR),注意 CN 要设置为服务器域名或 IP
openssl req -new -key server.key -out server.csr -subj "/CN=nats.example.com"

# 4. 使用 CA 签名生成服务器证书
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt

将生成的 ca.crtserver.crtserver.key 存放到一个安全目录,例如 /etc/nats/certs/。文件权限应严格控制,私钥仅 root 可读(chmod 600 server.key)。

如果你只是快速测试,也可以一步生成自签名证书:

openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=localhost"

此时不使用 CA,证书既是服务端证书也是自签名的根。

2. 证书要求与最佳实践

  • CN 或 SAN:证书的 Common NameSubject Alternative Name 必须与 NATS 服务器的域名或 IP 地址一致。例如客户端连接地址为 tls://nats.example.com:4222,则证书应包含 nats.example.com
  • 密钥长度:推荐 RSA 2048 位以上或 ECDSA。
  • 有效期:设置合理的过期时间,避免频繁更换但也不要过长。
  • 信任链:在双向 TLS(mTLS)场景中,还需签发客户端证书并由同一 CA 签名。

第二步:配置 NATS 服务器启用 TLS

NATS 服务器的配置文件(通常为 nats-server.conf)通过 tls 块来启用加密。

基本 TLS 配置(服务器认证)

port: 4222

tls {
  cert_file: "/etc/nats/certs/server.crt"
  key_file:  "/etc/nats/certs/server.key"
  # 可选的根 CA 证书,用于验证客户端证书(mTLS 时需要)
  # ca_file: "/etc/nats/certs/ca.crt"

  # 强制客户端使用 TLS 连接(禁用非 TLS 端口),若保留普通端口则设为 false
  # 这里直接将主端口设为 TLS,不再暴露非加密端口
}

# 如果希望同时支持 TLS 和非 TLS,可以使用单独的端口:
# port: 4222       # 非加密
# tls {
#   port: 4223     # 仅 TLS 端口
#   cert_file: ...
#   key_file: ...
# }

保存配置后启动(或重启)NATS 服务器:

nats-server -c /etc/nats/nats-server.conf

检查日志输出,应能看到类似 Listening for client connections on 0.0.0.0:4222,且无证书相关报错。

测试 TLS 连接

使用 NATS 提供的 CLI 工具 natsnatscli 快速验证。

# 若使用自签名证书,需要指定 CA 证书路径,否则会报证书不受信任
nats server check --server tls://localhost:4222 --tlsca /etc/nats/certs/ca.crt

如果你的证书是由公共 CA 签发且域名匹配,则无需 --tlsca

第三步:配置客户端连接 TLS

不同的 NATS 客户端库配置方式类似,核心是提供服务器 URL 的 TLS 前缀以及必要的证书。

1. 使用 nats://tls:// 协议前缀

  • nats://localhost:4222 —— 非 TLS 连接。
  • tls://localhost:4222 —— TLS 加密连接,若服务端仅配置了 TLS 端口,则必须用此前缀。

2. Go 客户端示例

import "github.com/nats-io/nats.go"

nc, err := nats.Connect("tls://nats.example.com:4222",
    nats.RootCAs("path/to/ca.crt"),    // 信任的 CA 证书(自签时必须)
    // 如果服务端要求客户端证书(mTLS)
    // nats.ClientCert("client.crt", "client.key"),
)
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

3. Python 客户端示例(nats.py)

import asyncio
import ssl
from nats.aio.client import Client as NATS

async def run():
    nc = NATS()
    # 创建 ssl 上下文
    ssl_ctx = ssl.create_default_context(cafile="ca.crt")
    # 如需客户端证书:
    # ssl_ctx.load_cert_chain(certfile="client.crt", keyfile="client.key")
    await nc.connect("tls://nats.example.com:4222", tls=ssl_ctx)
    # 业务逻辑...
    await nc.close()

asyncio.run(run())

4. 使用 nats CLI 工具

nats sub --server tls://localhost:4222 --tlsca ca.crt "test.>" 

第四步:进阶 - 双向 TLS(mTLS)

双向 TLS 要求客户端也必须提供证书以验证身份,通常用于增强安全性。配置方法如下:

  1. 使用 CA 签发客户端证书(参考第一步)。
  2. 在服务器配置中指定 ca_file 并设置 verifytrue
tls {
  cert_file: "/etc/nats/certs/server.crt"
  key_file:  "/etc/nats/certs/server.key"
  ca_file:   "/etc/nats/certs/ca.crt"
  verify:    true   # 强制客户端证书验证
}
  1. 客户端连接时需提供自己的证书和私钥。

常见问题排查

1. 证书不受信任或域名不匹配

现象:客户端报 x509: certificate signed by unknown authoritycertificate is valid for X, not Y解决:确保客户端导入了正确的 CA 证书;检查证书的 SAN 或 CN 是否匹配连接使用的地址。

2. 私钥权限过于开放

NATS 服务器启动时可能会拒绝权限为 644 或 777 的私钥文件。 解决chmod 600 server.key 并确保文件属主为运行 NATS 的 Linux 用户。

3. 未指定 TLS 前缀

客户端使用 nats:// 但服务器只启用了 TLS,连接受阻。 解决:改用 tls://

4. 证书过期

现象:连接突然中断,日志显示 certificate has expired解决:使用 openssl x509 -in server.crt -noout -dates 查看有效期,提前更换证书并重启服务。

5. 性能考量

TLS 握手会消耗少量 CPU,NATS 基于 Go 语言的高效 TLS 实现通常不会成为瓶颈。如果遇到性能问题,可考虑使用会话复用、ECDSA 证书或优化硬件。

总结

通过以上步骤,你已成功为 NATS 配置了 TLS 加密通信。核心点包括:生成可靠证书、在服务器配置中指定证书和密钥、客户端使用 tls:// 并信任 CA。对于生产环境,建议结合 Let’s Encrypt 等自动证书管理工具,并定期轮换证书。掌握了基础 TLS 后,你还能轻松扩展至集群路由加密和叶节点安全,为整个消息基础设施构建坚实的安全防线。