NTP配置为客户端广播监听模式
前言
项目需求:
使能ntp为客户端模式,能监服务端广播模式发出的ntp报文,计算出服务端的时间与客户端的时间偏差并上报。
开发状况:
交叉编译ntp源码,将修改后的ntpd进程部署到设备上作为客户端完成项目需求
如何操作?
首先应该知道ntp客户端广播监听模式处理逻辑
ntp客户端监听广播ntp处理逻辑:
找到如下资料:
总结一下:
ntp客户端模式下监听广播ntp,先被动接收报文,接收第一个报文后进行一次单播,算出网络延迟,后续一直处于监听状态。
也就是说,要想实现ntp广播监听,先要保证单播监听能正常使用
首先查看单播监听能否使用:
配置ntp.conf为最简单的单播客户端:
server 192.168.1.52
restrict 127.0.0.1
restrict ::1
设置ntp服务端为单播模式,将客户端ntpd进程运行至前台查看解析情况:
用tcpdump监听发现客户端能收到数据,但是解析数据时发现T1时间不一致的情况,报错如下
这就要了解一下单播原理了
单播原理:
计算原理:
wireshake上对应关系:
单播不再过多阐述了。使用tcpdump在客户端抓取ntp包,并查看分析问题到底出现在了哪里:
通过抓包发现,客户端时间戳T1在发送给服务端后被更改了,导致客户端收到包后发现T1更改后,认为这个是个无效包,将报文丢掉。
原因:
客户端发送请求时会将自己的时间搓T1封装到发送报文里,服务端接收到数据后,发送报文给客户端后,客户端会先检查原来的T1有没有被更改,若被更改,那么该包会被丢弃
上述我遇到的情况,是客户端请求的时候T1与wrieshake中抓到的T1报文不一样,导致客户端收到服务端报文的时候发现T1对不上,将包丢掉导致单播失败
原因是ntp应用层发送的时间系统为了提高精度,在OS层被改掉了,导致T1对不上,
解决方法:
更改源码#define M_ISEQU 对比宏定义,比较逻辑,秒上时间相等就通过,不再比较秒下时间了
至此单播模式便能使用了
广播模式配置:
客户端单播监听没问题就能实现广播了
客户端配置为广播模式最简单的conf配置如下:
broadcastclient
restrict 127.0.0.1
restrict ::1
服务端启动广播模式,开始查看客户端监听log日志,果然出了问题,广播模式只监听不做上述单播请求
经过对日志结合源码的分析发现:
问题出在没有配置身份验证,ntp源码receive函数对接收到的报文会先判断一下报文类型,具体在receive函数中的switch(retcode)模块下的case AM_NEWBCL语句下会检查广播报文是否有身份验证,没有验证则直接退出,我这边代码中这个身份验证默认是开启的。
解决方法:
要么配置身份验证,要么不做身份验证,我的是在init_proto函数中将sys_authenticate置0也就是不检查身份验证信息
修改好后再次启动ntpdf发现广播监听成功!
客户端被动接收服务端报文信息,接收服务端报文后进行一次单播,主要是算出网络延迟,后续一直进入广播被动接收
至此我的ntp客户端使能广播监听成功。
源码重要函数补充:
ntp_proto.c文件中:
receice(struct recvbuf*rbuf) 此函数用于接收ntp报文做一些判断,查看报文是否符合要求
process_packet() 这个函数非常重要receive函数内部校验完毕后会在内部调用一此此函数,此函数主要是根据t1 ~t4算出偏差等信息,只要报文能进入这个函数,基本就说明监听成功了transmit() 此函数用于发送报文
peer_xmit() 此函数用于封装报文,在transmit内部被调用,封装好报文后发送