




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
简介:DDNS (Dynamic DNS) 扩展了 DNS 将客户端 IP 与其域名进行静态映射的功能,它可以将同一域名实时地解析为不同的动态 IP,而不需要额外的人工干预。这在客户端 IP 地址不断发生变化的情况下,尤其是在无线网络和 DHCP 环境中,都有着极其重要的意义。本文通过分析 DDNS 的工作原理,简单演示了其在 Linux 网络协议栈的内核空间及用户空间创建 netlink 套接字、进行数据交换、并最终通过 nsupate 工具将更新消息发送给 DNS 服务器的过程。DDNS 工作原理的分析DDNS 的实现最根本的一点是当主机的 IP 地址发生变化的时候,实现 DNS 映射信息的及时更新,应用程序需要及时地获得这一信息,主要的方法可分为两大类: 一类是轮询机制,即:应用程序每隔一定的时间,去从查询主机当前的 IP 地址,并与之前的进行比较,从而判断网络地址是否发生了变化。显然,这种方法不仅效率低下,而且对每次查询 IP 地址的时间间隔很难得到一个折中的数值。 第二类方法是异步实现方式,即:每当主机的 IP 地址发生变化的时候,应用程序能够被及时地通知到。这的确是一个简单而又高效的方法,但与此同时,另一个问题又产生了,那就是:通知源又应该由谁来担当 呢?显然,这是处于用户空间的应用程序无法胜任的。于是,我们想到了让内核来充当这一消息源。这样,在内核空间和用户空间之间就需要通过消息来进行通信 了。在 Linux 下用户空间与内核空间的信息交互方式有许多种,比如:软中断、系统调用、netlink 等等。关于这些通信方式的介绍以及其各自的优缺点并不在本文的讨论范围内,您可以自行查看参考资源。在这许多种通信方式中,netlink 凭借其标准的 socket API、模块化实现、异步通信机制、多播机制等等多种优势,成为了内核与越来越多应用程序之间交互的主要方式。在 Linux 的内核中,已经为我们封装了使用 netlink 对特定网络状态变化进行消息通知的功能,这就是著名的 rtnetlink。有关 netlink 在内核空间实现的详细代码以及其 API 参数的介绍,您可以自行查看参考资源,本文在此不作过多的赘述。本文讨论的重点是针对 DDNS 这一特定的应用,演示 rtnetlink 检测到 IP 地址发生了变化、并将消息告知用户空间的应用程序的整个过程,以及应用程序利用 netlink 套接字接收消息、并告知 DNS 服务器的实现方法。DDNS 工作流程的简单介绍结合上述对 DDNS 工作原理的分析,我们可以将 DDNS 的工作流程简单地用图 1 来表示:图 1. DDNS 的工作流程图从图 1 中可以看到,DDNS 的工作流程主要有三个部分:1. 应用程序实时感知到 IP 地址发生了变化,如上介绍,利用基于 netlink 的异步通知机制可以让应用程序及时得到内核空间对这些事件的“通知”,具体可以分为如下 5 个步骤:o 1、内核空间初始化 rtnetlink 模块,创建 NETLINK_ROUTE 协议簇类型的 netlink 套接字;o 2、用户空间创建 NETLINK_ROUTE 协议簇类型的 netlink 套接字,并且绑定到 RTMGRP_IPV4_IFADDR 组播 group 中;o 3、用户空间接收从内核空间发来的消息,如果没有消息,则阻塞自身;o 4、当主机被分配了新的 IPV4 地址,内核空间通过 netlink_broadcast,将 RTM_NEWADDR 消息发送到 RTNLGRP_IPV4_IFADDR 组播 group 中 ;o 5、用户空间接收消息,进行验证、处理;2. 应用程序接收到“通知”后,把 DNS update 信息发送给 DNS 服务器,目的是将更新后的 IP 地址及时地通知 DNS 服务器,以便网络上的主机仍然能够通过原来的域名访问到自己,通用的做法是利用开源软件 nsupdate 发送 DNS update 信息给 DNS 服务器以实现 DNS 信息的动态更新。3. 最后,对应于第一部分 netlink 套接字的创建,用户空间和内核空间关闭所创建的 netlink 套接字。下文将详细阐述其中的每一环节及其实现。内核空间 rtnetlink 检测 IP 地址变化的实现与分析在我们开始利用 netlink 套接字、实现与内核通信的应用程序之前,先来分析一下内核空间的 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 来创建一个 NETLINK_ROUTE 类型的 netlink 套接字,并指定接收函数为 rtnetlink_rcv,有关 rtnetlink_rcv 的实现细节可以查阅内核 net/core/rtnetlink.c 文件。这里需要指出的是,netlink 提供了包括 NETLINK_ROUTE、NETLINK_FIREWALL、NETLINK_INET_DIAG 等在内的多种协议簇(详细列表及各协议簇的含义可以自行查看参考资源),其中 NETLINK_ROUTE 类型提供了网络地址发生变化的消息,这正是 DDNS 需要用到的。内核空间 IP 地址变化事件的通知过程引起主机 IP 地址变化的原因有很多种,如:DHCP 分配的 IP 过期、用户手动修改了 IP 等等。无论何种原因,最终都会触发内核空间对相应事件的通知机制,这里以最常用的修改 IPV4 地址的工具 ifconfig 为例。ifconfig 先是创建一个 AF_INET 的 socket,然后通过系统调用 ioctl 来完成配置的,ioctl 在内核中对应的函数是 sys_ioctl,对于 IP 地址、子网掩码、默认网关等配置的修改,其最终会调用 devinet_ioctl。devinet_ioctl 函数处理包括 get、set 在内的多种命令,与 DDNS 应用有关的是 set 类命令,图 2 给出了 SIOCSIFADDR 命令(设置网络地址)的 ifconfig 调用树:图 2. SIOCSIFADDR 命令的 ifconfig 调用树从图 2 中可以看到,当用户使用 ifconfig 对主机的 IP 地址作了修改,内核在进行了新地址的设置之后,会调用 rtmsg_ifa,传递的事件为 RTM_NEWADDR。清单 2. rtmsg_ifa 发送 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 消息后,需要根据 IP 的变化进行处理。这里使用了 handle_newaddr 函数,对 IP 的变化分为了两种情况:一种是 interface 已经存在、仅仅是 IP 发生了变化;另一种是 interface 是新添加的。无论是哪种情况,handle_newaddr 函数在进行了相应的处理之后,都需要调用 update_dns.sh 这个脚本通知 DNS 服务器。关于 update_dns.sh 的实现参见下一章。清单 8. 用户空间处理内核空间消息 void handle_newaddr(struct ifinfomsg *ifinfo, int len) struct if_info *i; for(i = if_list ; i ; i = i-next) / 遍历 in_list,找到 ip 发生变化的 interface if(i-index = ifinfo-ifi_index) break; if(i != NULL) / 找到了相应的 interface,执行 update_dns.sh system(update_dns.sh); return; / 没有找到对应的 interface,说明该 interface 是新添加的 if(i = calloc(sizeof(struct if_info), 1) = NULL)/ 分配一个 if_info 结构用于添加新的 interface exit(1); / 根据 ifinfo-ifi_index 等信息更新 if_info 结构 i,考虑到与 ddns 应用关系不大,限于篇幅,这里略过 . system(update_dns.sh); / 执行 update_dns.sh i-next = if_list; / 在 if_list 的末尾添加新发现的 interface if_list = i; 应用程序与 DNS 服务器的交互应用程序可以利用开源工具 nsupdate 来向 DNS 服务器发送 DNS update 消息。nsupdate 的详细用法及特性可以请查看参考资源,受篇幅所限,本章将会结合例子简单介绍这个工具的基本用法。nsupdate 可以从终端或文件中读取命令,每个命令一行。一个空行或一个send命令,则会将先前输入的命令发送到 DNS 服务器上,典型的使用方法如清单 9 所示。nsupdate 默认从文件 /etc/resolv.conf 中解析 DNS 服务器和域名,在实际应用中,我们可以首先解析网络参数,生成 nsupdate 的输入文件,最后调用 nsupdate。update_dns.sh 的实现流程如图 3 所示。清单 9. nsupdate 的使用例子 # nsupdate server 0 /DNS 服务器地址 0,默认端口 53 update delete A / 删除域名 的任何 A 类型记录 update add 86400 A / 添加一条 A 类型的记录, / 记录的 TTL 是 24 小时(86400 秒) send / 发送命令图 3. update_dns.sh 的实现流程netlink socket 的关闭用户空间关闭 netlink socket同标准的 socket API 一样,用户空间关闭 netlink socket 使用的也是 close 函数,而且用法完全一致。您可以参考清单 6 中 close 函数在 DDNS 应用程序中的使用。内核空间关闭 netlink socket内核空间关闭 netlink socket 使用 sock_release 函数,函数原型如下所示:清单 10. 内核空间关闭 netlink socket - sock_release /* 以下代码摘自 Linux kernel 3.4.3, net/socket.c 文件 */ void sock_release(struct socket * sock); 其中 sock 为 netlink_kernel_create 创建的 netlink 套接字。值得一提的是,在最新的 Linux kernel 中,还提供了 netlink_kernel_release 接口,函数原型如下所示:清单 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 创建的 netlink 套接字。对 DDNS 应用实现的扩展启示DDNS 利用 rtnetlink 的 NETLINK_ROUTE 协议簇套接字来监听 Linux 内核网络事件“RTM_NEWADDR”,实时更新 DNS 映射信息,从而实现 DNS 信息的动态更新。除了 NETLINK_ROUTE,netlink_family 还提供了多种协议簇来实现多种信息的报告,比如 SELinux、防火墙、Netfilter、IPV6 等。就 NETLINK_ROUTE 协议簇而言,也提供了多个组播 group 对应多种网络连接、网
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 风电叶片巡检无人机2025智能识别算法在风电运维中的经济效益报告
- 2025年UAM行业创新报告:通勤网络布局与用户接受度引领
- 考点解析-苏科版八年级物理上册《物态变化》专题测试试卷
- 2025低空经济市场分析报告:生物电飞行器能量转化技术应用案例
- 2025年住院医师规培-湖北住院医师规培(口腔修复科)历年参考题库及答案
- 2025-2030年新能源汽车智能化升级技术发展报告
- 湖北省武汉为明学校高中语文 第五单元 9 清兵卫与葫芦说课稿 新人教版《外国小说欣赏》
- 第七章认识区域:联系与差异 2023-2024八年级地理下册 大单元说课稿(单元分析+4课时规划+作业)
- 考点解析人教版八年级上册物理声现象《声音的特性》专项训练试题(详解版)
- 安徽省长丰县2024-2025学年高中政治 第四课 第一框 政府的权力:依法行使说课稿 新人教版必修2
- 耳石症教学课件
- 学生心理健康一生一策档案表
- 《淡水生态系统之谜》课件
- 王之涣《登鹳雀楼》课件2
- 北师大版小学五年级数学下册教案全册
- 中国少年先锋队成长故事征文
- 种草养鹅项目实施计划方案
- 动物遗传繁育知到智慧树章节测试课后答案2024年秋甘肃畜牧工程职业技术学院
- 无人机网络安全防护-洞察分析
- T-EERT 040.1-2024 环保设备设施安全管理 总则
- 2025工程施工包工包料承包合同
评论
0/150
提交评论