通过https实现简单安全的系统时间同步

httpsdate的Python项目详细描述


httpsdate.py

这是一个(相当)简单的python脚本,它将系统时钟设置为从一组https服务器获得的值。 这提供了一种简单、安全但不十分精确的时间同步方法。

为什么?< >

当今的一些安全技术都假设有一个正确的本地时钟。 一个例子是证书过期。

不幸的是,安全可靠的时钟同步协议的选择很少。 有关今天选项的错误状态的讨论可以在@hannob的https://blog.hboeck.de/archives/890-in-search-of-a-secure-time-source.html中找到。 作者还提出了一种简单而有效的方法,可以安全地将系统时钟与远程服务器同步。

这个方法和脚本是灵感来源于httpsdate.py。 它的编写是为了克服httpstime的简化设计所带来的一些限制:

  1. httpsdate.py以最低权限自动运行。
  2. httpsdate.py不一定依赖于单个服务器来提供正确的时间。
  3. < > >

    它是如何工作的?< >

    https date.py查询一个或多个https服务器以获取datehttp头中的时间戳。 然后将系统时钟设置为以这种方式获得的时间戳的中值。

    只要超过一半的时间戳是正确的,那么得到的系统时间就是正确的。 但是,由于非常简单的协议所施加的限制,它可能会失去几秒钟的准确性。

    httpsdate.py完成后退出。 要在较长时间内保持系统时钟同步,只需定期运行httpsdate.py,例如作为cron作业或systemd计时器。

    如何使用

    使用它的最简单方法是运行如下命令:root

    httpsdate.py www.ptb.de
    

    这将从www.ptb.de获取当前时间,并将本地系统时钟设置为与之匹配。 控制台输出如下:

    Time adjustment: 0.43 seconds
    1 remote clocks returned usable time information, 0 did not.
    

    如上所述,还可以查询多个服务器:

    httpsdate.py www.ptb.de www.metas.ch
    

    请参见[下面](流氓服务器)了解为什么要这样做。

    在解释httpsdate.py的其他选项之前,让我们先看一下帮助消息:

    usage: httpsdate.py [-h] [-n] [-u USER] [--max-adjust seconds] [-q]
                        host [host ...]
    
    Set the system clock to a date and time obtained from one or more HTTPS
    servers. Needs to be run with CAP_SYS_TIME, but drops unnecessary privileges
    when started as root.
    
    positional arguments:
      host                  get the time from the Date header of these HTTPS
                            servers
    
    optional arguments:
      -h, --help            show this help message and exit
      -n, --dry-run         do not actually set the system clock
      -u USER, --user USER  when started with high privileges, run as this user
                            instead (default: nobody)
      -t seconds, --timeout seconds
                            HTTPS network response timeout (default: 3 seconds)
      --max-adjust seconds  do not change the clock more than this many seconds
      --max-failed N        do not change the clock if more than N servers failed
                            to send a usable date and time
      -q, --quiet           do not show warnings and adjustment information
    

    如果使用root权限调用了httpsdate.py,它将自动删除除cap_sys_time之外的所有权限(设置系统时钟所需的权限),并切换到非特权用户。 使用--user指定要切换到的用户帐户。
    无需将httpsdate.py
    作为root运行。 仅用cap_sys_time运行它就足够了。 如果没有进一步的特权,它显然无法切换用户,并且会忽略--user选项(如果提供的话)。

    使用--dry run来查看会发生什么,但实际上不会更改系统时钟。

    当使用--quiet调用时,httpsdate.py将抑制非错误消息。 非错误信息是:

    • 关于不可用服务器的警告,例如由于证书验证错误
    • 最后的总结,有助于估计新系统时间的可靠性

    通常,可以相信系统时间离正确的时间不会太远。 为了反映这一点,可以使用--max adjust选项。 它指示httpsdate.py如果新时间离当前系统时间太远,则在不修改系统时钟的情况下退出。 与不经常的同步一起,这有助于防止恶意服务器故意改变系统时钟。 合理值为几分钟或几秒,具体取决于通常的时钟漂移和同步频率。

    类似地,--max failed限制了httpsdate.py的容错性。 如果超过这个数量的远程服务器无法发送可用时间,它将不会更改系统时钟。 无法获得可用时间的原因包括无效的X.509证书、TLS参数不兼容或缺少或无效的日期标题。

    为了更好地进行精确控制,可以使用--timeout更改到远程服务器的连接的https网络超时。 不在时间限制内响应的远程服务器将被跳过并计为失败。 这有助于减少从获取远程时间到实际更改系统时钟之间的延迟。

    要求

    • Linux内核3.5或更新版本
    • python 3.4.3或更新版本
    • python prctl
    • 一个适度正确的系统时间开始(几个月的休息应该没问题)

    httpsdate.py也应该在Python3.3上运行。 在3.4.3之前,python默认情况下不验证https证书,因此使https容易受到中间人攻击,除非相应的代码设置了验证。 httpsdate.py依赖于python做正确的事情,因此不应该与3.4.3之前的python版本一起使用(除非它们被修补,也就是说)。

    如果有疑问,可以运行

    httpsdate.py -n self-signed.badssl.com
    

    python3 -c 'from urllib.request import urlopen; urlopen("https://self-signed.badssl.com")'

    如果任何一个命令抛出包含certificate\u verify\u failed的错误,则一切正常,python验证证书。

    安装

    不需要安装。 下载并运行httpsdate.py

    为了方便起见,还可以使用pip安装httpsdate.py

    pip install httpsdate
    

    安全注意事项

    中间人攻击

    httpsdate.py验证远程服务器的X.509证书。 这有效地使用x.509pki系统验证了时间信息。 因此,中间人攻击者无法在不中断TLS连接的情况下故意设置错误的时间。

    但是,攻击者可以断开连接,从而阻止时间同步。

    恶意服务器

    通过将系统时钟设置为从远程服务器获取的值,可以信任远程服务器的管理员保持其时间正确(并且相当准确)。

    为了减少每个远程服务器中需要放置的信任量,httpsdate.py可以使用多个服务器。 如果提供可用时间的远程服务器的一半以上也提供了正确的时间,则使用中值可以确保所选时间受正确时间值的限制。 因此,单个恶意服务器不能影响结果系统时间(只要至少有两个其他服务器响应,即)。

    中间人和流氓服务器

    中间人攻击者同时控制(至少)一个查询的服务器,可以很容易地断开与它们不控制的服务器的连接,从而强制一个可用时间值。

    在这种情况下,使用参数--max failed可以提供一些保护,因为故障远程服务器的可接受数量(例如,由于连接断开)是有限的。 这有效地增加了需要由攻击者控制的服务器数量。 不过,超过一半的响应需要正确才能确保系统时钟设置为正确的时间。

    软件错误

    httpsdate.py取决于其他软件。 例如,是用python编写并在linux内核上运行的。 因此,python解释器和linux内核中的错误可能会影响httpsdate.py。 httpsdate.py可能有它自己的。

    因此,httpsdate.py试图遵循最小特权原则。 在Linux上设置系统时钟需要提升的权限,但不需要完全的root权限。 httpsdate.py仅在设置时钟所需的cap sys_time功能下工作良好。 如果它是以完全root权限启动的(这通常比采用细粒度功能控制更方便),那么它将删除所有不必要的权限,并使用未被授予权限的用户的用户和组ID运行。 当然,这是在连接到网络之前完成的。

    不过,还有一些安全措施httpsdate.py目前并不采用自身,比如名称空间和seccomp过滤器。 如果这些技术配置得不太严格,那么应该可以将httpsdate.py与这些技术一起使用。 要在受限制的沙箱中运行httpsdate.py,可以使用systemd、bubblewrap或firejail。

    httpsdate.py本身就是自由/开源软件,代码相当简短。 实际上它的原始行比这个自述文件少。 可以对代码进行独立审计,以增强其不表现出任何不良行为的信心。

    关于精度的考虑

    如前所述,httpsdate.py的精度不是很高。 "不是很高"是指通常应该在参考时间的几秒钟内。 这并不理想,但对于大多数目的来说都足够了。

    影响精度的因素有三个,为了获得更好的结果,可以在一定程度上加以考虑。

    分辨率

    httpsdate.py从http头中检索远程时间,该头的分辨率仅为1秒。 因此,这种方法根本无法达到亚秒精度。

    网络延迟

    远程服务器设置的时间需要一段时间才能到达httpsdate.py,然后在设置系统时钟之前需要多几个CPU周期。 httpsdate.py不会做任何聪明的事情来纠正这些延迟,甚至测量错误的数量。 这根本没有得到考虑,而且很可能永远不会得到考虑。 由于所获得的时间数据的分辨率有限,任何尝试都可能是不可行的。

    减少网络延迟的常用方法适用,例如选择响应时间快的服务器。

    远程时钟精度

    日期标题不用于传递准确的当前时间信息。 因此,https服务器的管理员可能无法保持自己的时钟非常精确。 此外,缓存(反向)代理服务器和类似的网络组件可能会导致远程服务器返回过时的date头。

    虽然可以将httpsdate.py与任何支持https的现代web服务器一起使用,但选择希望保持自身时钟尽可能准确并始终生成新标题的服务器确实是有意义的。

    许可证

    麻省理工学院< /P>

    欢迎加入QQ群-->: 979659372 Python中文网_新手群

    推荐PyPI第三方库


热门话题
java使用ContentExchange设置请求属性   java Spark/Hdfs/Hdfsclient兼容性   java springcloudstreamkafka配置:instanceCount和instanceIndex   Java中web服务序列化日期   java用动态数据替换占位符   java git gc似乎覆盖了一个packfile,留下了一个打开的文件描述符,其中包含对“oldxxx.pack”的引用   为什么Apache项目对Java版本敏感?   java Anylogic帮助如何在导入的3dobject通过输送机上的多个“站”时更改其颜色?   JavaEclipseNeonM2E可以导入一个大型项目,但似乎不能自动解决依赖关系   java@FindBy搜索具有满足条件的子元素的元素   java如何将ActionEvent e与键绑定一起使用?   java转换以集中方式从外部库抛出的异常   java中用户文件/数据文件与系统/程序文件的区别   java使用变量字符串或字符作为对象名   字体使用Java图形操纵字符串中每个字符的形状   JavaFX图表移动数据   java RandomAccessFile:将所有项设置为相同的字节数?   java Google Play inapp Billing onPurchasesUpdated()错误响应代码1   java在不知道属性名和属性数的情况下处理json对象   java是否可以一次从HazelcastInstance(映射和列表)中删除所有数据?