NTP 时间偏差多大会出问题:HTTPS 证书、Kerberos、JWT 的时间敏感性

· 约 4 分钟 公共 NTP 时间源

服务器时间偏差是基础设施里最容易被忽视、出问题后最难排查的故障来源之一。HTTPS 握手失败、Kerberos 认证拒绝、JWT 提前过期——这些表面上看起来毫无关联的问题,根源可能都是一台时钟偏了几分钟的服务器。

时间敏感型协议速览

协议 / 组件时间容忍阈值超出后果
Kerberos±5 分钟(300秒)Clock skew too great,认证完全失败
TLS/HTTPS取决于证书有效期证书报”尚未生效”或”已过期”
JWTexp 字段决定Token expired,需重新登录
TOTP(动态验证码)±30 秒(一个时间窗口)验证码不匹配,登录失败
AWS/阿里云签名±5 或 ±15 分钟RequestTimeTooSkewed,API 调用被拒
日志时序无硬性限制多机日志时序乱,排查困难

国内公共 NTP 服务器

提供商服务器地址
阿里云ntp.aliyun.com(推荐)
腾讯云time1.cloud.tencent.com
中国授时中心ntp.ntsc.ac.cn
国家授时中心cn.ntp.org.cn
国家标准时间time.windows.com(Windows 默认)

配置时建议至少用 3 个服务器,NTP 协议用多数原则剔除异常节点。

chrony 配置(推荐)

/etc/chrony.conf

# 至少配 3 个 NTP 服务器
server ntp.aliyun.com iburst
server time1.cloud.tencent.com iburst
server ntp.ntsc.ac.cn iburst

# 允许本地时钟作为最后备选(离线时不至于完全失效)
local stratum 10

# 记录时钟漂移
driftfile /var/lib/chrony/drift

# 允许的最大偏差(超过则拒绝同步,防止时间跳变)
maxdistance 1.0

常用命令:

# 查看同步状态
chronyc tracking

# 输出示例:
# Reference ID    : 203.107.6.88 (ntp.aliyun.com)
# Stratum         : 3
# System time     : 0.000123456 seconds fast of NTP time  ← 偏差
# Last offset     : +0.000012345 seconds
# RMS offset      : 0.000034567 seconds
# Frequency       : 12.345 ppm fast

# 强制立即同步
chronyc makestep

# 查看 NTP 源列表和状态
chronyc sources -v

ntpd 配置(传统系统)

/etc/ntp.conf

server ntp.aliyun.com iburst
server time1.cloud.tencent.com iburst
server ntp.ntsc.ac.cn iburst

driftfile /var/lib/ntp/drift
# 查看同步状态
ntpq -p

# 输出示例(* 表示当前主同步源):
#      remote      refid    st  t  when poll reach  delay  offset  jitter
# *ntp.aliyun.com 10.137.38.86  2  u   45  64  377  12.345  0.012  0.045

# 手动同步一次(ntpd 停止状态下)
ntpdate ntp.aliyun.com

Kerberos 时间同步实践

Active Directory 环境(Linux 机器加域):

# 确认 DC 时间
net time -S 域控服务器地址

# 同步到 DC(临时)
ntpdate 域控服务器地址

# 永久配置:把 AD DC 作为 NTP 源
# /etc/chrony.conf 加入:
server dc.yourdomain.com iburst

Kerberos 排查

# 查看当前 ticket
klist

# 报错 Clock skew too great 时,先检查时间差
date && curl -s --head http://time.windows.com | grep Date

# 超过 5 分钟就需要同步
chronyc makestep

JWT 时钟偏差处理

签发方和验证方可能在不同服务器,各自时钟偏差叠加:

签发方快 2 分钟 + 验证方慢 2 分钟 = 有效期实际缩短 4 分钟

代码侧应对方案(以 Python python-jose 为例):

# 验证时允许 ±30 秒误差
claims = jwt.decode(token, key, algorithms=["HS256"],
                    options={"leeway": 30})

不要把 leeway 设太大(>5 分钟),否则失去 exp 的意义。根本解法是让所有服务器时间精确同步。

TOTP(动态验证码)时间窗口

Google Authenticator 等 TOTP 应用每 30 秒生成一个新码,服务端默认接受当前码和前后各一个码(±30 秒窗口)。

如果用户手机时间偏了超过 30 秒,验证码会持续失败。常见于:

  • 手机长时间飞行模式后恢复
  • Android 关闭了”自动时间同步”

排查:手机设置 → 系统 → 日期和时间 → 开启”自动设置时间”。

容器和虚拟机注意事项

容器(Docker):直接用宿主机时钟,不需要在容器内配 NTP
虚拟机(VMware/KVM):宿主机配 NTP,虚拟机通过 VMware Tools / virtio-ptp 同步
跨时区部署:所有服务器统一用 UTC,应用层处理时区显示
# 查看系统时区
timedatectl

# 设置为 UTC(推荐服务器统一使用)
timedatectl set-timezone UTC

# 设置为上海时间(面向用户的前端服务器)
timedatectl set-timezone Asia/Shanghai

配套工具

❓ 常见问题

时间偏差多少会导致 HTTPS 证书报错?

取决于证书的有效期范围,不是固定阈值。TLS 握手时客户端用本地时间检查证书的 Not Before(生效时间)和 Not After(过期时间)。如果客户端时间早于 Not Before——报"证书尚未生效";如果客户端时间晚于 Not After——报"证书已过期"。两种情况都会导致握手失败。实践中:证书有效期通常 90 天(Let's Encrypt)到 1 年,时间偏差几分钟不会触发;但有些内网证书 Not Before 设为当天,新颁发的证书在时间慢的客户端上会立即报"尚未生效"。

Kerberos 为什么对时间那么敏感?

Kerberos ticket 里带时间戳,用于防重放攻击,默认允许 ±5 分钟偏差。Kerberos 的工作原理:KDC(Key Distribution Center)颁发的 ticket 包含颁发时间和有效期(默认 8-10 小时),客户端和服务端都用时间戳验证 ticket 是否在有效期内,允许 ±5 分钟(300 秒)的时钟偏差(clock_skew)。超过 5 分钟:KDC 拒绝认证请求,报 KRB5KRB_AP_ERR_SKEW(Clock skew too great)。常见场景:Linux 机器加入 Active Directory 域,如果 ntpd/chrony 没有正确同步到 DC,第二天早上就会发现无法 SSH 登录或 sudo 失败。

JWT 的时间相关字段有哪些,服务端怎么校验?

JWT 标准有三个时间 claim:(1) iat(issued at)——签发时间,Unix 时间戳;(2) exp(expiration time)——过期时间,Unix 时间戳,服务端验签时当前时间 > exp 则拒绝;(3) nbf(not before)——生效时间,当前时间 < nbf 则拒绝。服务端时钟偏差的影响:签发方时钟快了 10 分钟 → exp 比预期早 10 分钟 → token 提前 10 分钟过期;验证方时钟慢了 10 分钟 → 看到的当前时间比实际早 → 已过期的 token 被认为还有效(安全漏洞)。最佳实践:JWT 库通常有 leeway(容差)配置,允许 ±几分钟的时钟偏差,但不要设过大。

怎么检查服务器当前时间偏差?

两种方法:(1) 命令行直接查询 NTP 服务器偏差:chronyc tracking(chrony)或 ntpq -p(ntpd),看 System timeoffset 字段,单位秒;(2) 手动对比:date 看本机时间,和 curl -s --head http://worldtimeapi.org/api/ip | grep Date 对比(这个方法受网络延迟影响,参考即可)。容忍范围参考:一般服务 ±1 秒;Kerberos ±300 秒;高频交易系统 ±1 毫秒;证书签发系统 ±1 秒。超过 1 秒就该修,超过 1 分钟必须立即处理。

chrony 和 ntpd 该用哪个?

现代系统推荐 chrony,老系统用 ntpd。chrony 的优势:(1) 启动时能快速同步(ntpd 首次同步可能要几分钟);(2) 在网络不稳定的环境(虚拟机、容器、断网重连)表现更好;(3) 支持硬件时钟精度更高;(4) RHEL/CentOS 7+、Ubuntu 18.04+ 默认用 chrony。ntpd 仍然适合:需要精确到微秒级的场景(PTP 协议更好)、老旧系统的历史兼容。Docker 容器内不需要单独配 NTP——容器时间同步宿主机,宿主机用 chrony/ntpd 同步即可。

打开 公共 NTP 时间源 阿里/腾讯/华为/国家授时中心/Cloudflare(NTS)/Google(leap-smear) 10 家·一键生成 macOS/Windows/chrony/timesyncd/OpenWrt 配置