I'm currently working on a project for my summer internship and I've got to make an oblivious DNS translation server. I'm not here to speak about the oblivious part in detail but I'll explane the architecture of my program.
There is a server side that receives obfuscated requests and sends back an answer that it doesn't understand itself.
On the client side there is a proxy that translate requests into obfuscated requests. For that I use an iptables rule to send all DNS requests to a NFQUEUE, and then I work with libnetfilter_queue to handle the packet. After that I received the answer from the server I make a DNS answer with all the information I get (from the DNS request and from the server) and send it using libnet.
Now let's talk about my problem : When using my proxy I check the traffic with Wireshark and it seems that my proxy sends valid answers but if I try to browse the Internet with Firefox it doesn't work. You can find my code here : http://ift.tt/1SZL7pX
Is there a problem in my way of building DNS packets ?
Here is the DNS sender :
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);
}
Here is an example of DNS answer sent by my proxy: http://ift.tt/1KO1GGw
via
Chebli Mohamed