DDNS 的工作原理及其在 Linux 上的實現(xiàn).doc_第1頁
DDNS 的工作原理及其在 Linux 上的實現(xiàn).doc_第2頁
DDNS 的工作原理及其在 Linux 上的實現(xiàn).doc_第3頁
DDNS 的工作原理及其在 Linux 上的實現(xiàn).doc_第4頁
DDNS 的工作原理及其在 Linux 上的實現(xiàn).doc_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

簡介:DDNS (Dynamic DNS) 擴展了 DNS 將客戶端 IP 與其域名進行靜態(tài)映射的功能,它可以將同一域名實時地解析為不同的動態(tài) IP,而不需要額外的人工干預。這在客戶端 IP 地址不斷發(fā)生變化的情況下,尤其是在無線網(wǎng)絡和 DHCP 環(huán)境中,都有著極其重要的意義。本文通過分析 DDNS 的工作原理,簡單演示了其在 Linux 網(wǎng)絡協(xié)議棧的內核空間及用戶空間創(chuàng)建 netlink 套接字、進行數(shù)據(jù)交換、并最終通過 nsupate 工具將更新消息發(fā)送給 DNS 服務器的過程。DDNS 工作原理的分析DDNS 的實現(xiàn)最根本的一點是當主機的 IP 地址發(fā)生變化的時候,實現(xiàn) DNS 映射信息的及時更新,應用程序需要及時地獲得這一信息,主要的方法可分為兩大類: 一類是輪詢機制,即:應用程序每隔一定的時間,去從查詢主機當前的 IP 地址,并與之前的進行比較,從而判斷網(wǎng)絡地址是否發(fā)生了變化。顯然,這種方法不僅效率低下,而且對每次查詢 IP 地址的時間間隔很難得到一個折中的數(shù)值。 第二類方法是異步實現(xiàn)方式,即:每當主機的 IP 地址發(fā)生變化的時候,應用程序能夠被及時地通知到。這的確是一個簡單而又高效的方法,但與此同時,另一個問題又產(chǎn)生了,那就是:通知源又應該由誰來擔當 呢?顯然,這是處于用戶空間的應用程序無法勝任的。于是,我們想到了讓內核來充當這一消息源。這樣,在內核空間和用戶空間之間就需要通過消息來進行通信 了。在 Linux 下用戶空間與內核空間的信息交互方式有許多種,比如:軟中斷、系統(tǒng)調用、netlink 等等。關于這些通信方式的介紹以及其各自的優(yōu)缺點并不在本文的討論范圍內,您可以自行查看參考資源。在這許多種通信方式中,netlink 憑借其標準的 socket API、模塊化實現(xiàn)、異步通信機制、多播機制等等多種優(yōu)勢,成為了內核與越來越多應用程序之間交互的主要方式。在 Linux 的內核中,已經(jīng)為我們封裝了使用 netlink 對特定網(wǎng)絡狀態(tài)變化進行消息通知的功能,這就是著名的 rtnetlink。有關 netlink 在內核空間實現(xiàn)的詳細代碼以及其 API 參數(shù)的介紹,您可以自行查看參考資源,本文在此不作過多的贅述。本文討論的重點是針對 DDNS 這一特定的應用,演示 rtnetlink 檢測到 IP 地址發(fā)生了變化、并將消息告知用戶空間的應用程序的整個過程,以及應用程序利用 netlink 套接字接收消息、并告知 DNS 服務器的實現(xiàn)方法。DDNS 工作流程的簡單介紹結合上述對 DDNS 工作原理的分析,我們可以將 DDNS 的工作流程簡單地用圖 1 來表示:圖 1. DDNS 的工作流程圖從圖 1 中可以看到,DDNS 的工作流程主要有三個部分:1. 應用程序實時感知到 IP 地址發(fā)生了變化,如上介紹,利用基于 netlink 的異步通知機制可以讓應用程序及時得到內核空間對這些事件的“通知”,具體可以分為如下 5 個步驟:o 1、內核空間初始化 rtnetlink 模塊,創(chuàng)建 NETLINK_ROUTE 協(xié)議簇類型的 netlink 套接字;o 2、用戶空間創(chuàng)建 NETLINK_ROUTE 協(xié)議簇類型的 netlink 套接字,并且綁定到 RTMGRP_IPV4_IFADDR 組播 group 中;o 3、用戶空間接收從內核空間發(fā)來的消息,如果沒有消息,則阻塞自身;o 4、當主機被分配了新的 IPV4 地址,內核空間通過 netlink_broadcast,將 RTM_NEWADDR 消息發(fā)送到 RTNLGRP_IPV4_IFADDR 組播 group 中 ;o 5、用戶空間接收消息,進行驗證、處理;2. 應用程序接收到“通知”后,把 DNS update 信息發(fā)送給 DNS 服務器,目的是將更新后的 IP 地址及時地通知 DNS 服務器,以便網(wǎng)絡上的主機仍然能夠通過原來的域名訪問到自己,通用的做法是利用開源軟件 nsupdate 發(fā)送 DNS update 信息給 DNS 服務器以實現(xiàn) DNS 信息的動態(tài)更新。3. 最后,對應于第一部分 netlink 套接字的創(chuàng)建,用戶空間和內核空間關閉所創(chuàng)建的 netlink 套接字。下文將詳細闡述其中的每一環(huán)節(jié)及其實現(xiàn)。內核空間 rtnetlink 檢測 IP 地址變化的實現(xiàn)與分析在我們開始利用 netlink 套接字、實現(xiàn)與內核通信的應用程序之前,先來分析一下內核空間的 rtnetlink 模塊是如何工作的。內核空間 rtnetlink 的初始化清單 1. rtnetlink 的初始化 /* 以下代碼摘自 Linux kernel 2.6.18, net/core/rtnetlink.c 文件,并只選擇了與本主題相關的最重要的部分,其他的都用省略號略過,之后的各清單也一樣。 */ void _init rtnetlink_init(void) . rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv, THIS_MODULE); if (rtnl = NULL) panic(rtnetlink_init: cannot initialize rtnetlinkn); . 從清單 1 中可以看到:在 rtnetlink 進行初始化的時候,首先會調用 netlink_kernel_create 來創(chuàng)建一個 NETLINK_ROUTE 類型的 netlink 套接字,并指定接收函數(shù)為 rtnetlink_rcv,有關 rtnetlink_rcv 的實現(xiàn)細節(jié)可以查閱內核 net/core/rtnetlink.c 文件。這里需要指出的是,netlink 提供了包括 NETLINK_ROUTE、NETLINK_FIREWALL、NETLINK_INET_DIAG 等在內的多種協(xié)議簇(詳細列表及各協(xié)議簇的含義可以自行查看參考資源),其中 NETLINK_ROUTE 類型提供了網(wǎng)絡地址發(fā)生變化的消息,這正是 DDNS 需要用到的。內核空間 IP 地址變化事件的通知過程引起主機 IP 地址變化的原因有很多種,如:DHCP 分配的 IP 過期、用戶手動修改了 IP 等等。無論何種原因,最終都會觸發(fā)內核空間對相應事件的通知機制,這里以最常用的修改 IPV4 地址的工具 ifconfig 為例。ifconfig 先是創(chuàng)建一個 AF_INET 的 socket,然后通過系統(tǒng)調用 ioctl 來完成配置的,ioctl 在內核中對應的函數(shù)是 sys_ioctl,對于 IP 地址、子網(wǎng)掩碼、默認網(wǎng)關等配置的修改,其最終會調用 devinet_ioctl。devinet_ioctl 函數(shù)處理包括 get、set 在內的多種命令,與 DDNS 應用有關的是 set 類命令,圖 2 給出了 SIOCSIFADDR 命令(設置網(wǎng)絡地址)的 ifconfig 調用樹:圖 2. SIOCSIFADDR 命令的 ifconfig 調用樹從圖 2 中可以看到,當用戶使用 ifconfig 對主機的 IP 地址作了修改,內核在進行了新地址的設置之后,會調用 rtmsg_ifa,傳遞的事件為 RTM_NEWADDR。清單 2. rtmsg_ifa 發(fā)送 IP 地址變化消息 /* 以下代碼摘自 Linux kernel 2.6.18, net/ipv4/devinet.c 文件 */ static void rtmsg_ifa(int event, struct in_ifaddr* ifa) int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128); struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); if (!skb) netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) 0) while(NLMSG_OK(nl, len) /NLMSG 相關的宏定義可以參考內核 include/linux/netlink.h 文件 switch(nl-nlmsg_type) case RTM_NEWADDR: / 處理 RTM_NEWADDR 的 netlink 消息類型 /ifinfomsg 結構可以參考內核 include/linux/rtnetlink.h 文件 handle_newaddr(struct ifinfomsg *)NLMSG_DATA(nl), NLMSG_PAYLOAD(nl, sizeof(struct ifinfomsg); break; . / 處理其他 netlink 消息類型,如:RTM_NEWLINK,這里略過 default: printf(Unknown netlink message type : %d, nl-nlmsg_type); nl = NLMSG_NEXT(nl, len); if( nl != NULL ) free(nl); . int receive_netlink_message(struct nlmsghdr *nl) struct iovec iov; / 使用 iovec 進行接收 struct msghdr msg = NULL, 0, &iov, 1, NULL, 0, 0; / 初始化 msghdr int length; *nl = NULL; if (*nl = (struct nlmsghdr *) malloc(MAX_MSG_SIZE) = NULL ) return 0; iov.iov_base = *nl; / 封裝 nlmsghdr iov.iov_len = MAX_MSG_SIZE; / 指定長度 length = recvmsg(nl_socket, &msg, 0); if(length 應用程序在收到了 RTM_NEWADDR 類型的 netlink 消息后,需要根據(jù) IP 的變化進行處理。這里使用了 handle_newaddr 函數(shù),對 IP 的變化分為了兩種情況:一種是 interface 已經(jīng)存在、僅僅是 IP 發(fā)生了變化;另一種是 interface 是新添加的。無論是哪種情況,handle_newaddr 函數(shù)在進行了相應的處理之后,都需要調用 update_dns.sh 這個腳本通知 DNS 服務器。關于 update_dns.sh 的實現(xiàn)參見下一章。清單 8. 用戶空間處理內核空間消息 void handle_newaddr(struct ifinfomsg *ifinfo, int len) struct if_info *i; for(i = if_list ; i ; i = i-next) / 遍歷 in_list,找到 ip 發(fā)生變化的 interface if(i-index = ifinfo-ifi_index) break; if(i != NULL) / 找到了相應的 interface,執(zhí)行 update_dns.sh system(update_dns.sh); return; / 沒有找到對應的 interface,說明該 interface 是新添加的 if(i = calloc(sizeof(struct if_info), 1) = NULL)/ 分配一個 if_info 結構用于添加新的 interface exit(1); / 根據(jù) ifinfo-ifi_index 等信息更新 if_info 結構 i,考慮到與 ddns 應用關系不大,限于篇幅,這里略過 . system(update_dns.sh); / 執(zhí)行 update_dns.sh i-next = if_list; / 在 if_list 的末尾添加新發(fā)現(xiàn)的 interface if_list = i; 應用程序與 DNS 服務器的交互應用程序可以利用開源工具 nsupdate 來向 DNS 服務器發(fā)送 DNS update 消息。nsupdate 的詳細用法及特性可以請查看參考資源,受篇幅所限,本章將會結合例子簡單介紹這個工具的基本用法。nsupdate 可以從終端或文件中讀取命令,每個命令一行。一個空行或一個send命令,則會將先前輸入的命令發(fā)送到 DNS 服務器上,典型的使用方法如清單 9 所示。nsupdate 默認從文件 /etc/resolv.conf 中解析 DNS 服務器和域名,在實際應用中,我們可以首先解析網(wǎng)絡參數(shù),生成 nsupdate 的輸入文件,最后調用 nsupdate。update_dns.sh 的實現(xiàn)流程如圖 3 所示。清單 9. nsupdate 的使用例子 # nsupdate server 0 /DNS 服務器地址 0,默認端口 53 update delete A / 刪除域名 的任何 A 類型記錄 update add 86400 A / 添加一條 A 類型的記錄, / 記錄的 TTL 是 24 小時(86400 秒) send / 發(fā)送命令圖 3. update_dns.sh 的實現(xiàn)流程netlink socket 的關閉用戶空間關閉 netlink socket同標準的 socket API 一樣,用戶空間關閉 netlink socket 使用的也是 close 函數(shù),而且用法完全一致。您可以參考清單 6 中 close 函數(shù)在 DDNS 應用程序中的使用。內核空間關閉 netlink socket內核空間關閉 netlink socket 使用 sock_release 函數(shù),函數(shù)原型如下所示:清單 10. 內核空間關閉 netlink socket - sock_release /* 以下代碼摘自 Linux kernel 3.4.3, net/socket.c 文件 */ void sock_release(struct socket * sock); 其中 sock 為 netlink_kernel_create 創(chuàng)建的 netlink 套接字。值得一提的是,在最新的 Linux kernel 中,還提供了 netlink_kernel_release 接口,函數(shù)原型如下所示:清單 11. 內核空間關閉 netlink socket netlink_kernel_release /* 以下代碼摘自 Linux kernel 3.4.3, net/netlink/af_netlink.c 文件 */ void netlink_kernel_release(struct sock *sk); 其中 sk 為 netlink_kernel_create 創(chuàng)建的 netlink 套接字。對 DDNS 應用實現(xiàn)的擴展啟示DDNS 利用 rtnetlink 的 NETLINK_ROUTE 協(xié)議簇套接字來監(jiān)聽 Linux 內核網(wǎng)絡事件“RTM_NEWADDR”,實時更新 DNS 映射信息,從而實現(xiàn) DNS 信息的動態(tài)更新。除了 NETLINK_ROUTE,netlink_family 還提供了多種協(xié)議簇來實現(xiàn)多種信息的報告,比如 SELinux、防火墻、Netfilter、IPV6 等。就 NETLINK_ROUTE 協(xié)議簇而言,也提供了多個組播 group 對應多種網(wǎng)絡連接、網(wǎng)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論