前言
項目需求:
使能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內部被調用,封裝好報文后發送