我目前正在爲我的夏季實習項目工作,而且我必須做一個不經意的DNS翻譯服務器。我不是在這裏詳細講述這個無意義的部分,但我會解釋我的程序的體系結構。自定義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服務器? – rodolk
它將它發送到DNS服務器,我在nfqueue中捕獲並在獲取所需信息後將其刪除。 – Kromoz0hm
您可以顯示DNS響應,因爲它會到達瀏覽器? – rodolk