如果有一百万个大大小小的设备通过 TCP/IP 进行通信,如何确保时间本身不会说谎? 毕竟,他们每个人都有一个时钟,而且每个人的时间都必须是正确的。 没有ntp就无法规避这个问题。
让我们想象一下,在工业 IT 基础设施的一个部分中,随着时间的推移同步服务存在困难。 企业软件的集群堆栈立即开始出现故障,域解体,主节点和备用节点无法成功地恢复现状。
攻击者也有可能故意尝试通过 MiTM 或 DDOS 攻击来破坏时间。 在这种情况下,任何事情都可能发生:
- 用户账户密码将过期;
- X.509证书将过期;
- TOTP 二因素身份验证将停止工作;
- 备份将变得过时,系统将删除它们;
- DNSSec 将被破坏。
显然,每个IT部门都对时间同步服务的可靠运行很感兴趣,如果它们在工业运行中可靠、安全就好了。
25 分钟内破解 NTP
网络协议——千禧一代有一个特点,他们一直 它们不再有任何用处,但即使积累了足够多的爱好者和资金,更换它们也不是那么容易。
对经典 NTP 的主要抱怨是缺乏可靠的机制来防止入侵者的攻击。 为了解决这个问题已经进行了各种尝试。 为了实现这一目标,我们首先实现了用于交换对称密钥的预共享密钥(PSK)机制。
不幸的是,这种方法没有得到回报,原因很简单——它的扩展性不好。 根据服务器的情况,需要在客户端进行手动配置。 这意味着您根本无法像这样添加另一个客户端。 如果 NTP 服务器发生更改,则必须重新配置所有客户端。
然后他们想出了AutoKey,但他们立即发现了算法本身设计中的一些严重漏洞,他们不得不放弃它。 问题是种子仅包含 32 位,它太小并且不包含足够的计算复杂性来进行正面攻击。
- 密钥 ID - 对称 32 位密钥;
- MAC(消息验证码)——NTP数据包校验和;
自动键计算如下。
Autokey=H(Sender-IP||Receiver-IP||KeyID||Cookie)其中 H() 是加密哈希函数。
相同的函数用于计算数据包的校验和。
MAC=H(Autokey||NTP packet)事实证明,整个包裹检查的完整性取决于 cookie 的真实性。 获得它们后,您可以恢复自动密钥,然后欺骗 MAC。 但是,NTP 服务器在生成它们时使用种子。 这就是问题所在。
Cookie=MSB_32(H(Client IP||Server IP||0||Server Seed))MSB_32函数从md5哈希计算结果中截去32个最高有效位。 只要服务器参数保持不变,客户端cookie就不会改变。 那么攻击者只能恢复初始数量并能够独立生成cookie。
首先,您需要作为客户端连接到 NTP 服务器并接收 cookie。 此后,攻击者使用暴力方法,按照简单的算法恢复初始数字。
使用暴力方法攻击初始数计算的算法。
for i=0:2^32 − 1 do
Ci=H(Server-IP||Client-IP||0||i)
if Ci=Cookie then
return i
end if
end forIP 地址是已知的,因此剩下的就是创建 2^32 哈希值,直到创建的 cookie 与从 NTP 服务器接收到的 cookie 相匹配。 在配备 Intel Core i5 的常规家庭工作站上,这将需要 25 分钟。
NTS - 新的自动键
Autokey 中存在这样的安全漏洞是无法忍受的,2012 年它出现了 协议。 为了损害名称,他们决定重新命名,因此 Autokey v.2 被称为网络时间安全。
NTS协议是NTP安全性的扩展,目前仅支持单播模式。 它提供强大的加密保护,防止数据包操纵,防止窥探,可扩展性良好,能够抵御网络数据包丢失,并在连接安全期间将精度损失降至最低。
NTS 连接由使用较低层协议的两个阶段组成。 在 第一个 在此阶段,客户端和服务器就各种连接参数达成一致,并交换包含密钥的 cookie 和所有随附的数据集。 在 第二 在此阶段,实际受保护的 NTS 会话发生在客户端和 NTP 服务器之间。

NTS 由两个低层协议组成:网络时间安全密钥交换 (NTS-KE)(通过 TLS 发起安全连接)和 NTPv4(NTP 协议的最新版本)。 下面对此进行更多介绍。
第一阶段-NTS KE
在此阶段,NTP 客户端通过与 NTS KE 服务器的单独 TCP 连接发起 TLS 1.2/1.3 会话。 在此会话期间会发生以下情况。
- 双方确定参数 第二阶段的算法。
- 双方定义了第二个低层协议,但目前仅支持 NTPv4。
- 双方确定 NTP 服务器的 IP 地址和端口。
- NTS KE 服务器在 NTPv4 下发出 cookie。
- 双方从 cookie 材料中提取一对对称密钥(C2S 和 S2C)。
这种方法有一个很大的优点,即传输有关连接参数的秘密信息的全部负担都落在经过验证且可靠的 TLS 协议上。 这样就无需重新发明轮子来实现安全的 NTP 握手。
第二阶段-NTS保护下的NTP
第二步,客户端与 NTP 服务器安全同步时间。 为此,它在 NTPv4 数据包结构中传输四个特殊扩展(扩展字段)。
- 唯一标识符扩展包含一个随机随机数以防止重放攻击。
- NTS Cookie 扩展包含客户端可用的 NTP cookie 之一。 由于只有客户端拥有对称 AAED C2S 和 S2C 密钥,因此 NTP 服务器必须从 cookie 材料中提取它们。
- NTS Cookie 占位符扩展是客户端向服务器请求附加 cookie 的一种方式。 此扩展对于确保 NTP 服务器响应不会比请求长很多是必要的。 这有助于防止放大攻击。
- NTS 验证器和加密扩展字段扩展包含 AAED 密码以及 C2S 密钥、NTP 标头、时间戳和上述 EF 作为随附数据。 如果没有此扩展,则可能会欺骗时间戳。

服务器收到客户端的请求后,验证NTP数据包的真实性。 为此,他必须解密 cookie、提取 AAED 算法和密钥。 成功检查 NTP 数据包的有效性后,服务器以以下格式响应客户端。
- 唯一标识符扩展是客户端请求的镜像副本,是防止重放攻击的一种措施。
- NTS Cookie 扩展 更多 cookie 以继续会话。
- NTS 验证器和加密扩展字段扩展包含带有 S2C 密钥的 AEAD 密码。
第二次握手可以重复多次,绕过第一步,因为每个请求和响应都会为客户端提供额外的 cookie。 这样做的好处是,计算和传输 PKI 数据的相对资源密集型 TLS 操作可以除以重复请求的次数。 这对于专用 FPGA 计时器来说尤其方便,因为所有主要功能都可以打包成对称加密领域的多个功能,从而将整个 TLS 堆栈传输到另一个设备。
NTP安全
NTP 有什么特别之处? 尽管该项目的作者 Dave Mills 试图尽可能地记录他的代码,但能够理解 35 岁的时间同步算法的复杂性的程序员却很少见。 有些代码是在 POSIX 时代之前编写的,当时的 Unix API 与今天使用的有很大不同。 此外,需要统计知识来清除噪声线路上的信号干扰。
NTS 并不是修复 NTP 的第一次尝试。 一旦攻击者学会利用 NTP 漏洞来放大 DDoS 攻击,很明显需要进行彻底的改变。 在 NTS 草案正在准备和最终确定的同时,美国国家科学基金会于 2014 年底紧急拨款用于 NTP 的现代化。
该工作组的领导者不是任何人,而是 - 开源社区的创始人和支柱之一以及本书的作者 。 Eric 和他的朋友尝试做的第一件事就是将 NTP 代码从 BitKeeper 平台移至 git,但并没有成功。 项目负责人 Harlan Stenn 反对这一决定,谈判陷入僵局。 然后决定分叉项目代码,NTPSec 诞生了。
丰富的经验,包括在 GPSD 方面的工作、数学背景和阅读古代代码的神奇技能 - Eric Raymond 正是能够完成这样一个项目的黑客。 团队找到了代码迁移专家,并在短短 10 周内完成了 NTP 在 GitLab 上。 工作正如火如荼地进行着。
埃里克·雷蒙德的团队承担了这项任务,就像奥古斯特·罗丹处理一块石头一样。 通过删除 175 KLOC 旧代码,他们能够通过修复许多安全漏洞来显着减少攻击面。
以下是该发行版中包含的不完整列表:
- 无证、过时、过时或损坏的参考时钟。
- 未使用的 ICS 库。
- libopts/autogen。
- Windows 的旧代码。
- ntpdc。
- 自动键。
- ntpq C 代码已用 Python 重写。
- sntp/ntpdig C 代码已用 Python 重写。
除了清理代码之外,该项目还有其他任务。 以下是部分成就列表:
- 针对缓冲区溢出的代码保护已得到显着改进。 为了防止缓冲区溢出,所有不安全的字符串函数 (strcpy/strcat/strtok/sprintf/vsprintf/gets) 已替换为实现缓冲区大小限制的安全版本。
- 添加了 NTS 支持。
- 通过链接物理硬件,时间步精度提高了十倍。 这是因为现代计算机时钟已经比 NTP 诞生时的时钟准确得多。 最大的受益者是 GPSDO 和专用时间无线电。
- 编程语言的数量已减少到两种。 现在不再是 Perl、awk 甚至 S 脚本,而是全部是 Python。 因此,代码重用的机会更多。
- 该项目开始使用软件构建系统,而不是大量的自动工具脚本 .
- 更新并重新组织了项目文档。 他们从相互矛盾、有时甚至过时的文档集合中创建了相当过得去的文档。 现在,每个命令行开关和每个配置实体都有一个单一版本的事实。 此外,手册页和 Web 文档现在是从相同的核心文件创建的。
NTPSec 可用于许多 Linux 发行版。 目前最新的稳定版本是1.1.8,对于Gentoo Linux 来说它是倒数第二个。
(1:696)$ sudo emerge -av ntpsec
These are the packages that would be merged, in order:
Calculating dependencies... done!
[ebuild R ] net-misc/ntpsec-1.1.7-r1::gentoo USE="samba seccomp -debug -doc -early -gdb -heat -libbsd -nist -ntpviz -rclock_arbiter -rclock_generic -rclock_gpsd -rclock_hpgps -rclock_jjy -rclock_local -rclock_modem -rclock_neoclock -rclock_nmea -rclock_oncore -rclock_pps -rclock_shm -rclock_spectracom -rclock_trimble -rclock_truetime -rclock_zyfer -smear -tests" PYTHON_TARGETS="python3_6" 0 KiB
Total: 1 package (1 reinstall), Size of downloads: 0 KiB
Would you like to merge these packages? [Yes/No]
计时码表
还有一次尝试用更安全的替代方案来取代旧的 NTP。 与 NTPSec 不同,Chrony 是从头开始编写的,旨在在各种条件下可靠运行,包括不稳定的网络连接、部分网络可用性或拥塞以及温度变化。 此外,chrony还有其他优点:
- chrony可以更快、更准确地同步系统时钟;
- chrony 更小,消耗更少的内存,并且仅在需要时才访问 CPU。 这对于节约资源和能源来说是一大利好;
- chrony 在 Linux 上支持硬件时间戳,允许在本地网络上极其精确的同步。
然而,chrony 缺少旧 NTP 的一些功能,例如广播和多播客户端/服务器。 此外,经典NTP支持更多的操作系统和平台。
要禁用服务器的功能以及对 chronyd 进程的 NTP 请求,只需在 chrony.conf 文件中写入端口 0 即可。 这是在不需要为 NTP 客户端或对等方维护时间的情况下执行的。 从版本 2.0 开始,仅当允许指令或适当的命令允许访问、配置 NTP 对等体或使用广播指令时,NTP 服务器端口才会打开。
该程序由两个模块组成。
- chronyd 是一项在后台运行的服务。 它接收有关系统时钟和外部时间服务器之间的差异的信息并调整本地时间。 它还实现了 NTP 协议,可以充当客户端或服务器。
- chronyc 是一个用于程序监视和控制的命令行实用程序。 用于微调各种服务参数,例如允许您在 chronyd 继续运行时添加或删除 NTP 服务器。
从 RedHat Linux 版本 7 开始 chrony 作为时间同步服务。 该软件包也适用于其他 Linux 发行版。 最新稳定版本为3.5,为v4.0的发布做准备。
(1:712)$ sudo emerge -av chrony
These are the packages that would be merged, in order:
Calculating dependencies... done!
[binary N ] net-misc/chrony-3.5-r2::gentoo USE="adns caps cmdmon ipv6 ntp phc readline refclock rtc seccomp (-html) -libedit -pps (-selinux)" 246 KiB
Total: 1 package (1 new, 1 binary), Size of downloads: 246 KiB
Would you like to merge these packages? [Yes/No]
如何在 Internet 上设置您自己的远程计时服务器以同步办公网络上的时间。 以下是设置 VPS 的示例。
在 VPS 上的 RHEL / CentOS 上设置 Chrony 的示例
现在让我们练习一下,在 VPS 上设置我们自己的 NTP 服务器。 很简单,只需在RuVDS网站上选择合适的资费,获取现成的服务器并输入十几个简单的命令即可。 就我们的目的而言,这个选项非常合适。

让我们继续设置服务并首先安装 chrony 包。
[root@server ~]$ yum install chronyRHEL 8 / CentOS 8 使用不同的包管理器。
[root@server ~]$ dnf install chrony安装chrony后,您需要启动并激活该服务。
[root@server ~]$ systemctl enable chrony --now如果需要,您可以更改 /etc/chrony.conf,将 NPT 服务器替换为最近的本地服务器以减少响应时间。
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.ru.pool.ntp.org iburst
server 1.ru.pool.ntp.org iburst
server 2.ru.pool.ntp.org iburst
server 3.ru.pool.ntp.org iburst
接下来,我们设置 NTP 服务器与指定池中的节点的同步。
[root@server ~]$ timedatectl set-ntp true
[root@server ~]$ systemctl restart chronyd.service
还需要向外部开放 NTP 端口,否则防火墙将阻止来自客户端节点的传入连接。
[root@server ~]$ firewall-cmd --add-service=ntp --permanent
[root@server ~]$ firewall-cmd --reload
在客户端,正确设置时区就足够了。
[root@client ~]$ timedatectl set-timezone Europe/Moscow/etc/chrony.conf 文件指定运行 NTP 服务器 chrony 的 VPS 服务器的 IP 或主机名。
server my.vps.server最后,在客户端上启动时间同步。
[root@client ~]$ systemctl enable --now chronyd
[root@client ~]$ timedatectl set-ntp true
下次我将告诉您在没有互联网的情况下同步时间的选项有哪些。
来源: habr.com
