Andoroid下检测DNS错误

Andoroid下检测DNS错误

思路:首先是抓取端口53的包,然后对包进行解析:
有问题的dns回复:

可以看出Answer RRs是0 ,这个值代表dns服务器返回的域名ip应答数。
下面是正常的dns应答包:

可以看出Answer RRs为12,说明有12个ip答复。
所以可以通过Answer RRs来判断是否发生了dns错误。
/*循环抓包,在got_packet()中处理抓到的包*/
int main(int argc, char **argv)  
{  
  
    char *dev = NULL;                                       /* capture device name */  
    char errbuf[PCAP_ERRBUF_SIZE];                          /* error buffer */  
    pcap_t *handle;                                         /* packet capture handle */  
  
    char filter_exp[] = "dst 202.114.85.31 and tcp";        /* filter expression [3] */  
    printf("input filter:");
    gets(filter_exp);
//    char filter_exp[] = "(src port 53) or (dst port 53)";
    struct bpf_program fp;                                   /* compiled filter program (expression) */  
    bpf_u_int32 mask;                                        /* subnet mask */  
    bpf_u_int32 net;                                         /* ip */  
    int num_packets = 10;                                   /* number of packets to capture */  

    
	Ping ping = Ping();
	if(ping.isConnection(PING_IP, 4) && !ping.isConnection(PING_HOST, 4))
		printf("DNS ERROR\n\n");
	else
		printf("NET ACCESS\n\n");
    
    print_app_banner();

    /* check for capture device name on command-line */  
    if (argc == 2)
    {
        dev = argv[1];
    }
    else if (argc > 2)
    {
        fprintf(stderr, "error: unrecognized command-line options\n\n");  
        print_app_usage(); 
        exit(EXIT_FAILURE);  
    }
    else
    {  
        /* find a capture device if not specified on command-line */  
        dev = pcap_lookupdev(errbuf);
        if (dev == NULL)
        {  
            fprintf(stderr, "Couldn't find default device: %s\n", errbuf);  
            exit(EXIT_FAILURE);  
        }  
    }  
      
    /* get network number and mask associated with capture device */  
    if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
    {  
        fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);  
        net = 0;
        mask = 0;
    }  
  
    /* print capture info */  
    printf("Device: %s\n", dev);  
    printf("Number of packets: %d\n", num_packets);  
    printf("Filter expression: %s\n", filter_exp);  
  
    /* open capture device */  
    handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);  
    if (handle == NULL)
    {  
        fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);  
        exit(EXIT_FAILURE);
    }  
  
    /* make sure we're capturing on an Ethernet device [2] */  
    if (pcap_datalink(handle) != DLT_EN10MB) 
    {  
        fprintf(stderr, "%s is not an Ethernet\n", dev);  
        exit(EXIT_FAILURE);
    }  
  
    /* compile the filter expression */  
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
    {  
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));  
        exit(EXIT_FAILURE);  
    }  
  
    /* apply the compiled filter */  
    if (pcap_setfilter(handle, &fp) == -1)
    {  
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));  
        exit(EXIT_FAILURE);  
    }  

    udpErrorCount = 0;
    /* now we can set our callback function */  
    pcap_loop(handle, num_packets, got_packet, NULL);  
  
    /* cleanup */  
    pcap_freecode(&fp);  
    pcap_close(handle);  
  
    printf("\nCapture complete.\n");  
  
    return 0;  
}  

/*解析包*/
void  got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)  
{
    static int count = 1; 
      

    const struct sniff_ethernet *ethernet; 
    const struct sniff_ip *ip; 
  
    int size_ip;
      
    printf("\nPacket number %d:\n", count);  
    count++;  
      
    ethernet = (struct sniff_ethernet*)(packet);  
    ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);  
    size_ip = IP_HL(ip) * 4;
    if (size_ip < 20) 
    {  
        printf(" * Invalid IP header length: %u bytes\n", size_ip);  
        return;  
    }  
  
    printf(" From: %s\n", inet_ntoa(ip->ip_src));  
    printf(" To: %s\n", inet_ntoa(ip->ip_dst));  
         
    switch(ip->ip_p)
    {
        case IPPROTO_TCP:
            printf(" Protocol: TCP\n");
            DecodeTCPPacket(packet + SIZE_ETHERNET + size_ip, ntohs(ip->ip_len) - size_ip);
            break;
        case IPPROTO_UDP:
            printf(" Protocol: UDP\n");
            DecodeUDPPacket(packet + SIZE_ETHERNET + size_ip, ntohs(ip->ip_len) - size_ip);
            break;
        case IPPROTO_ICMP:
            printf(" Protocol: ICMP\n");  
            break;
        case IPPROTO_IP:
            printf(" Protocol: IP\n");  
            break;
        default:
            printf(" Protocol: unknown\n");  
            break;
    } 
}  

/*解析UDP包*/
void DecodeUDPPacket(const u_char *packet, int size_packet)
{
    const struct sniff_udp *udp;
    
    udp = (struct sniff_udp *)packet;
    
    printf("UDPPort: %d -> %d \nUDPlength: %d\n", ntohs(udp->sourcePort), ntohs(udp->destinationPort), ntohs(udp->len));
    
    ParseDNSPacket(packet + sizeof(struct sniff_udp), size_packet - sizeof(struct sniff_udp));
}
/*解析DNS包,并通过ping来判断是否发生dns错误*/
void ParseDNSPacket(const u_char *packet, int size_packet)
{
    const struct sniff_dns *dns;
    dns = (struct sniff_dns *)packet;
    if(QR(dns))
    {
        printf(" DNS type: response\n");
        if((ntohs(dns->dns_Answer) == 0) && (++udpErrorCount) >= UDP_ERROR_COUNT)
        {
            Ping ping = Ping();
            if(!ping.isConnection(PING_HOST, 4) && ping.isConnection(PING_IP, 4))
            {
                //DNS ERROR
                printf("DNS(Packet) ERROR\n");
            }
        }
        else
        {
            udpErrorCount = 0;
        }
    }
    else
    {
        printf(" DNS type:request\n");
    }
    printf(" Questions: %d\n", ntohs(dns->dns_Questions));
    printf(" Answer RRs: %d\n", ntohs(dns->dns_Answer));
    printf(" Authority RRs: %d\n", ntohs(dns->dns_Authority));
    printf(" Additional RRs: %d\n", ntohs(dns->dns_Additional));

    print_payload(packet + sizeof(struct sniff_dns), size_packet - sizeof(struct sniff_dns));
}
最终又经过ping来判断是否发生dns错误,不过未能复现错误环境所以没能实际检测。

源码地址: http://download.csdn.net/download/bgylde/9725375

最后希望可以顺便解决dns错误,但是在现在的android上通过代码方式修改dns未能成功,最后的思路是实用iptable来访问正确的dns地址,还未实际尝试,欢迎交流


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值