【问题标题】:Custom DNS answers自定义 DNS 答案
【发布时间】:2015-08-04 22:31:55
【问题描述】:

我目前正在为我的暑期实习做一个项目,我必须制作一个不经意的 DNS 翻译服务器。我不是在这里详细谈论​​被遗忘的部分,但我会解释我的程序的架构。

有一个服务器端接收混淆的请求,并返回一个它自己不理解的答案。

在客户端有一个将请求转换为模糊请求的代理。为此,我使用 iptables 规则将所有 DNS 请求发送到 NFQUEUE,然后使用 libnetfilter_queue 处理数据包。 之后,我收到了来自服务器的答案,我使用我获得的所有信息(来自 DNS 请求和来自服务器)制作了一个 DNS 答案,并使用 libnet 发送它。

现在让我们谈谈我的问题:使用代理时,我使用 Wireshark 检查流量,似乎我的代理发送了有效的答案,但如果我尝试使用 Firefox 浏览 Internet,它就不起作用。 你可以在这里找到我的代码:https://github.com/AurelienCasimir/PrivateDNS

我构建 DNS 数据包的方式有问题吗?

这里是 DNS 发件人:

int send_answer(char *dst_ip_array, char *src_ip_array, int dport, int sport, int dns_id, char *query, char *req_ip, int logfd)
{
char c;
u_long src_ip = arrayToLong(src_ip_array), dst_ip = arrayToLong(dst_ip_array), requested_ip_long=dotToLong(req_ip);
char requested_ip[4];
u_short type = LIBNET_UDP_DNSV4_H;
libnet_t *l;

libnet_ptag_t ip;
libnet_ptag_t ptag4; /* TCP or UDP ptag */
libnet_ptag_t dns;

char errbuf[LIBNET_ERRBUF_SIZE];
char payload[1024];
u_short payload_s;
char log_buffer[500];
int length = 0;

/*
 *  Initialize the library.  Root priviledges are required.
 */
l = libnet_init(
        LIBNET_RAW4,                            /* injection type */
        NULL,                                   /* network interface */
        errbuf);                                /* error buffer */

if (!l)
{
    length += sprintf(log_buffer + length, "\tlibnet_init: %s", errbuf);
    exit(EXIT_FAILURE);
}

/* 
 * build dns payload 
 */
requested_ip[0]=requested_ip_long/(256*256*256);
requested_ip_long=requested_ip_long%(256*256*256);
requested_ip[1]=requested_ip_long/(256*256);
requested_ip_long=requested_ip_long%(256*256);
requested_ip[2]=requested_ip_long/256;
requested_ip_long=requested_ip_long%256;
requested_ip[3]=requested_ip_long;

payload_s = snprintf(payload, sizeof payload, "%c%s%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", 
         (char)(strlen(query)&0xff), query, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0d, 0xe0, 0x00, 0x04, requested_ip[0], requested_ip[1], requested_ip[2], requested_ip[3]);

/* 
 * build packet
 */
dns = libnet_build_dnsv4(
type,          /* TCP or UDP */
dns_id,        /* id */
0x8100,        /* request */
1,             /* num_q */
1,             /* num_anws_rr */
0,             /* num_auth_rr */
0,             /* num_addi_rr */
payload,
payload_s,
l,
0
);

if (dns == -1)
{
    length += sprintf(log_buffer + length, "\tCan't build  DNS packet: %s\n", libnet_geterror(l));
    goto bad;
}

ptag4 = libnet_build_udp(
    sport,                                /* source port */
    dport,                                    /* destination port */
    LIBNET_UDP_H + LIBNET_UDP_DNSV4_H + payload_s, /* packet length */
    0,                                      /* checksum */
    NULL,                                   /* payload */
    0,                                      /* payload size */
    l,                                      /* libnet handle */
    0);                                     /* libnet id */

if (ptag4 == -1)
{
    length += sprintf(log_buffer + length, "\tCan't build UDP header: %s\n", libnet_geterror(l));
    goto bad;
}


ip = libnet_build_ipv4(
    LIBNET_IPV4_H + LIBNET_UDP_H + type + payload_s,/* length */
    0,                                          /* TOS */
    242,                                        /* IP ID */
    0,                                          /* IP Frag */
    64,                                         /* TTL */
    IPPROTO_UDP,                                /* protocol */
    0,                                          /* checksum */
    src_ip,                                     /* source IP */
    dst_ip,                                     /* destination IP */
    NULL,                                       /* payload */
    0,                                          /* payload size */
    l,                                          /* libnet handle */
    0);                                         /* libnet id */

if (ip == -1)
{
    length += sprintf(log_buffer + length, "\tCan't build IP header: %s\n", libnet_geterror(l));
    exit(EXIT_FAILURE);
}


/*
 * write to the wire
 */
c = libnet_write(l);
if (c == -1)
{
    length += sprintf(log_buffer + length, "\tWrite error: %s\n", libnet_geterror(l));
    goto bad;
}
else
{
    length += sprintf(log_buffer + length, "\tWrote %d byte DNS packet; check the wire.\n", c);
}
length = strlen(log_buffer);
write(logfd, log_buffer, length); // Write to the log.
libnet_destroy(l);
return (EXIT_SUCCESS);
bad:
length = strlen(log_buffer);
write(logfd, log_buffer, length); // Write to the log.
libnet_destroy(l);
return (EXIT_FAILURE);
}

以下是我的代理发送的 DNS 应答示例: http://imgur.com/9c5RgLj

【问题讨论】:

  • 使用 Firefox 时会发生什么?它是将 UDP 请求发送到您的代理还是直接将其发送到另一个 DNS 服务器?
  • 它将它发送到一个 dns 服务器,我在 nfqueue 中捕获它并在获得所需信息后将其丢弃。
  • 你能显示DNS响应到达浏览器吗?
  • 我现在没有电脑,但明天我会用一些 dns 回复来编辑我的问题。
  • 我添加了 DNS 答案的屏幕截图。

标签: c proxy dns network-programming


【解决方案1】:

似乎 DNS 响应是正确的。我会看:

  1. 如果需要可用的标志递归 (0x8180)
  2. 检查返回的IP地址是否正常。我无法访问您在图片中显示的 IP 地址 (https://db-ip.com/26.193.206.130)
  3. UDP 校验和是否正确?
  4. 事务 ID 是否与 DNS 查询的事务 ID 对应?
  5. 我确定这没问题,但只需检查服务器是否请求地址的类型和类别

【讨论】:

  • 1.试过了,还是不行。 2.我的数据库中的所有IP地址都是从真实DNS服务器的答案中获取的。 3. 在 libnet_build_udp 中使用 0 作为校验和,这应该让内核自己计算校验和。 4. 这是我从 NFQUEU 中的数据包中获取的信息之一。 5. 这可能是棘手的部分,因为目前我的项目不处理 CNAME 条目。 (之后的下一部分评论)
  • 我认为这应该不是问题,因为请求不知道它是 CNAME 还是主机地址,所以不是用 CNAME + 主机名回答它只是回答带有主机名(另一个区别是它只回答 1 个 IP 地址而不是多个 IP 地址)
  • @Kromoz0hm,我认为它也与 CNAME 无关,这是 DNS 服务器内部的。您可以尝试直接在浏览器中使用该 IP 地址吗?在 hosts 文件中添加域名和 IP 地址,并在 Firefox 中添加该域名(没有您的解决方案)。这是澄清任何可能的疑问的方法。在第 4 点中,您可以通过捕获查询和响应来阐明这一点
  • 哦,你在这里发现了一个非常愚蠢的错误……我忘了按网络顺序写地址,所以它应该是 130.206.193.26。但即使改变了这个,它仍然不起作用。我已经检查过了,没问题。但我又测试了一遍,还是可以的。
  • @Kromoz0hm 网络订单是一个典型的错误,请检查您在其他字段中没有同样的错误:59 分钟的生存时间听起来很奇怪。您可能在事务 ID 中遇到同样的问题。您是否检查了新地址对应于该域?顺便说一句,如果此回复有用,您可以将其标记为有用
猜你喜欢
  • 1970-01-01
  • 2016-05-24
  • 2020-05-12
  • 2020-07-10
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
相关资源
最近更新 更多