创建简单的NTP服务器以响应服务器的系统时间时出现问题

时间:2019-02-22 12:02:47

标签: ntp

我正在尝试构建一个非常简单的NTP(v3)服务器,该服务器从LAN上的IP摄像机接收NTP请求以进行时间同步。摄像机已断开与Internet的连接,因此其想法是将本地PC服务器用作摄像机的NTP服务器。

我尝试了两种不同的方法。

  1. 将简单的UDP转发写入已知的NTP服务器(例如time.windows.com)。运行良好。
  2. 编写一个简单的UDP服务器,在端口123上侦听传入的NTP请求,该请求仅返回服务器的系统时间。对于简单,不需要的NTP客户端(例如,物理网络路由器),这也可以很好地工作,但是对于本地HIKVISION摄像机,它仍然会失败。

方法:接收一个48字节的缓冲区。确保偏移量为0的字节为0x1B。将偏移量为0的字节变为0x1C,并将当前UTC时间写到最后8个字节作为NTP时间戳。对于大多数NTP客户端而言,这非常有效,但对HIKVISION而言则不是。

相机发送此请求:

1B-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
00-00-00-00-00-00-00-00-61-8C-DE-CA-C3-73-89-DC

最后8个字节不为零。如果我尝试修改UDP转发解决方案[1],以便在转发前将最后8个字节清零,则相机会报告错误。因此,这些位很重要,并且可能具有一定的密码学意义。

我正在研究RFC,试图了解这一点,但找不到解释。我可以找到的任何示例代码都完全忽略了这一点,并且走了简单的路线。

所以问题是...如何解释NTP请求的尾随字节以及如何返回正确的NTP响应?欢迎使用一些示例代码或指向资源的指针。

1 个答案:

答案 0 :(得分:1)

请参阅https://www.ietf.org/rfc/rfc1305.pdf第50页开始的附录A,以获取有关NTP数据包格式的说明。该最后8个字节应该带有服务器的响应时间戳-这正是为什么在构建最小响应包时将时间戳记入这些字节的原因。

但是,基于该客户端将值放入最后8个字节这一事实,它似乎希望使用https://www.ietf.org/rfc/rfc2030.txt SNTP使用SNTP(简单NTP)协议第5节中描述的机制与NTP相同的数据包格式,但使用字段的方式略有不同。在SNTP中,客户端放入字节40至47的值是客户端当前的时间观念。 (在这种情况下,AFAICT认为时间戳大约在1951年左右。)

如果这是此客户端正在尝试执行的操作,则它希望服务器将这8个字节复制到字节24-31(“原始时间戳记”字段)中,然后将服务器的当前时间写入字节32-39(接收时间戳记)中)放入字节40-47(发送时间戳),并将其作为响应发送。当然,还应继续将响应中的第一个字节更改为0x1C,以指示此数据包来自服务器。您还应该将字节1中的Stratum值设置为合理的非零值,例如3或4。

鉴于客户端的时钟已关闭很长时间,它可能需要几轮请求/响应才能同步。因此,不要指望它的时钟立即跳到与服务器时钟匹配的时间。 (它可能会这样做,但我不会指望它。)

我认为您不需要通过特殊对待此客户端来使逻辑复杂化。您可以将完全相同的逻辑应用于来自客户端的数据包,这些数据包将零放入最后8个字节。这只是意味着您在构建对这些客户端的响应时将零复制到“原始时间戳记”字段中。

相关问题