如何自己动手去实现一个nslookup

nslookup 这个命令大家一定非常熟悉,我们常常使用这个命令查看指定域名的IP地址。那这个命令是如何实现的呢?能否自己亲自动手实现一个属于自己的nslookup呢?

准备工具

Wireshark

基本思路

向指定DNS服务器(地址:144.144.144.144,端口:53)发送指定格式的请求报文,然后接收服务器发送来的响应报文,然后从接收到的响应报文中解析出指定IP地址。

请求报文

首先我们必须知道我们要发送的请求报文中要包含哪些数据,这里我们打开浏览器输入www.baidu.com然后使用Wire shark抓取到的请求报文长这个样子:

我们点击Domain Name System(query),我们会看到有下面这几项:
在这里插入图片描述

  1. Transaction ID: 会话标识
    我们通过点击它,会发现下面的请求报文中有对应的两个方块亮起,也就是说这一项会占用两个字节,下面的其他选项的操作都是如此,我就不一一放图了。
    占用字节数:2
    推荐值: 随机正整数。
    推荐使用类型:unsigned short。
    在这里插入图片描述

  2. Flags: 标志
    占用字节数目:2
    推荐值:0x0100
    推荐使用类型: short/unsigned short
    这个推荐值有什么说法吗?有的,但是这里我们就不再过多深究了假如想要知道这个值是怎么来的可以自己百度一下或者参考这篇文章link,我们现在只需要明白,如果是想要向DNS服务器发送请求,填这个值就对了。

  3. Questions :问题数目
    占用字节数目:2
    推荐使用类型: short/unsigned short
    推荐值:1
    这个就很好理解吧,我们每次只向服务器请求一个域名的IP地址,所以只有一个问题。

  4. Answer RRs: 回答资源数目
    占用字节数目:2
    推荐使用类型: short/unsigned short
    推荐值:0
    我们作为请求的一方,自然是不知道我们请求的域名对应有几个IP地址,所以我们这里填0。

  5. Authority RRs: 授权资源记录数目
    占用字节数目:2
    推荐使用类型: short/unsigned short
    推荐值:0

  6. Additional RRs: 附加资源记录数目
    占用字节数目:2
    推荐使用类型: short/unsigned short
    推荐值:0
    我作为请求方,这个是我可以知道的吗?所以是0。

  7. Queries:查询问题区域
    这个区域下面有三个项目是我们必须要填的:

    • Name:想要查询的域名
      在请求报文中我们必须将我们想要查询的域名经过格式化服务器才能正确识别,比如我要查询的域名为:www.baidu.com那我必须将域名格式化为:3www5baidu3com\0 才行。 查询的域名不同,此项在请求报文中占用的字节数目也有所不同。比如我们上面我们经过格式化后的域名:3w5baidu3com\0在请求报文中就占用了12个字节。
    • Type: 查询类型
      占用字节数目:2
      推荐使用类型: short/unsigned short
      推荐值:1
      值为1,是向服务器表示我们此次请求的目的是获得指定域名的IP地址。当然还有很多的其他选项,可以参考这篇文章link
    • Class:查询类
      占用字节数目:2
      推荐使用类型: short/unsigned short
      推荐值:1
      一般情况下这个值都为1,它表示我们查询的是互联网地址。

请求报文的代码实现

在实现代码的时候我们需要注意的是 我们需要利用htons()函数将上面每个选项在内存中的值从主机字节序进行网络字节序的转化,也就是从小端存储转化为大端存储。什么是小端存储,什么是大端存储参考这篇文章 link。然后依照上面各个选项的次序,依次将各个选项的值(注意,这里要求的是网络字节序)放到一个字符串数组中,然后利用sendto()函数发送给我们的DNS服务器。

// QUERY : without queries
struct QUERY {
   
    unsigned short transaction_id;
    short flags;
    short count_question;
    short answer_rrs;
    short authority_rrs;
    short additional_rrs;
};
//为部分请求参数赋值
int creat_query(struct QUERY* query, char* hostname) {
   
    srand(time(0));
    query->transaction_id = rand();
    query->flags = htons(0x0100);
    query->count_question = htons(1);
    query->answer_rrs = htons(0);
    query->authority_rrs = htons(0);
    query->additional_rrs = htons(0);

    return 0;
}
//将查询域名进行格式化 example:3wwww5baidu3com
char* format_hostname(char* hostname) {
   
    if (hostname == NULL) return NULL;
    // hostnaem after conversion
    char* name = (char*)malloc(sizeof(strlen(hostname) + 2));
    if (name == NULL)
        return NULL;
    //
    char* temp_name = name;
    char* duplicaton_hostname = strdup(hostname);
    char delimition[2] = ".";
    char* segment = strtok(duplicaton_hostname, delimition);
    while (segment 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值