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

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論