[tor-bugs] #2602 [Tor Relay]: DNS Relay

Tor Bug Tracker & Wiki torproject-admin at torproject.org
Tue Feb 22 05:41:15 UTC 2011


#2602: DNS Relay
-------------------------+--------------------------------------------------
 Reporter:  F_Ruta       |          Owner:     
     Type:  enhancement  |         Status:  new
 Priority:  normal       |      Milestone:     
Component:  Tor Relay    |        Version:     
 Keywords:  DNS relay    |         Parent:     
   Points:               |   Actualpoints:     
-------------------------+--------------------------------------------------
 Dear All,
 Most likely a ticket is not the right way to convey this info, but I
 haven't been able to find any other way.
 I had several apps leaking DNS packets so I wrote this simple dnsToTor
 relay (See below) that if you are interested I could release to the public
 domain.
 I needed it on a window machine so it is written specifically for window;
 however, porting should be trivial.
 On a Win machine, once you have the executable running, it is sufficient
 to change in the "Internet Protocol (TCP/IP) Properties the DNS setting to
 "Use the following DNS server address" and setting as IP "127.0.0.1". At
 this point all apps leaking DNS request will send their DNS request to the
 relay that will send a SOCKS5 Request to Tor and then generate a reply to
 the resolver providing the info returned by Tor. This is completely
 transparent for the apps that doesn't realize that the DNS query is
 handled by Tor.
 The relay only handles the basic DNS query (Type A Ipv4), but it should be
 sufficient for the most common usage scenarios.
 Hope it helps
 F.

 /*Copyright F.Ruta 2011 */
 #define WIN32_LEAN_AND_MEAN
 #include <winsock2.h>
 #include <windows.h>
 #include <ws2tcpip.h>
 #include <mstcpip.h>
 #include <iostream>
 #include <string.h>
 #include <stdint.h>
 using namespace std;

 #define DEBUG 0

 #define BUF_LEN   1024
 #define MAX_QUERY 512
 #define MAX_NAME  512


 //A Query name is in the form of length octet+domain segment
 //so a query for www.mydomain.com would be encoded as
 [3]www[8]mydomain[3]com
 int convertName( uint8_t const * const query, int8_t * const name, int32_t
 maxLen ) {
         int i,j,len, totalLen;

         i = 0;
         j = 0;

         do {
                 len = (uint8_t)query[i];
                 if ( len > 0 ) {
                         totalLen += len;
                         if ((j + len) < maxLen ) {
                             memcpy(&(name[j]), &(query[i+1]), len );
                             i += len+1;
                             j += len;
                             name[j++] = '.';
                         } else {
                                 return 0;
                         }
                 }
         } while (len > 0);
         name[--j] = '\0';
         return strlen((const char *)name);
 }

 int parseDnsQuery( uint8_t const * const packet, uint16_t *qid, uint8_t
 *rec, uint8_t * const query, int32_t *queryLen ) {
         uint16_t sv;
         uint16_t qdcount;
         uint8_t  qr;
         uint8_t  opcode;
         uint8_t  len;
         int i;

         memcpy( &sv, &packet[0], 2 );
         *qid = ntohs(sv);
         qr = (packet[2]&0x80)>>7;
         opcode = (packet[2]&0x78)>>3;
         *rec = (packet[2]&0x01);
         //Make sure it is a standard query
         if (( 0 == qr ) && (0 == opcode)) {
         memcpy( &sv, &packet[4], 2 );
         qdcount = ntohs(sv);

                 i = 12;
                 len = 0;
                 //store the query
                 while( packet[i++] != '\0' ){len++;}
                 if ( len < *queryLen ) {
             memcpy(query, &(packet[12]), len+1 );
                 *queryLen = len+1;
                 } else {
                         *queryLen = 0;
                 }

             memcpy( &sv, &packet[12+len+1], 2 );
                 if ( 1 != ntohs(sv)) { //Type A, IPv4 address
                         cout << "DNS request is not for type A, IPv4
 address" <<endl;
                         return -1;
                 }
             memcpy( &sv, &packet[12+len+1+2], 2 );
                 if ( 1 != ntohs(sv)) { //Class IN, Internet
                         cout << "DNS request is not for class IN" <<endl;
                         return -1;
                 }
                 return len;
         } else {
                 return -1;
         }
         return 0;
 }

 int parseDns( uint8_t const * const packet ) {
         uint16_t sv;
         uint8_t  cv;
         uint32_t lv;
         uint16_t len;
         uint16_t type;
         uint16_t questions, answers, authority, additional;
         int i,j,k;

         memcpy( &sv, &packet[0], 2 );
         cout << "ID = "<< (int)ntohs(sv) <<endl;
         cv = (packet[2]&0x80)>>7;
         cout << "QR = "<< (int)cv << " ";
         switch (cv) {
             case 0 : {
                         cout << "(Query)";
                         break;
             }
             case 1 : {
                         cout << "(Response)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cout << endl;
         cv = (packet[2]&0x78)>>3;
         cout << "Opcode = "<< (int)cv <<" ";
         switch (cv) {
             case 0 : {
                         cout << "QUERY, Standard query"<<endl;
                         break;
             }
             case 1 : {
                         cout << "IQUERY, Inverse query"<<endl;
                         break;
             }
             case 2 : {
                         cout << "STATUS, Server status request"<<endl;
                         break;
             }
             case 3 : {
                         cout << "NA"<<endl;
                         break;
             }
             case 4 : {
                         cout << "Notify"<<endl;
                         break;
             }
             case 5 : {
                         cout << "Update"<<endl;
                         break;
             }
             default: {
                     cout << "Reserved"<<endl;
                         break;
                 }
         }
         cv = (packet[2]&0x04)>>2;
         cout << "AA= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(Not authoritative)";
                         break;
             }
             case 1 : {
                         cout << "(Authoritative)";
                         break;
             }
             default: {
                     break;
                 }
         }

         cv = (packet[2]&0x02)>>1;
         cout << " TC= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(Not truncated)";
                         break;
             }
             case 1 : {
                         cout << "(Truncated)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cv = (packet[2]&0x01);
         cout << " RD= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(No Recursion)";
                         break;
             }
             case 1 : {
                         cout << "(Recursion)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cv = (packet[3]&0x80)>>7;
         cout << " RA= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(Recursion Not Avail)";
                         break;
             }
             case 1 : {
                         cout << "(Recursion Avail)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cv = (packet[3]&0x40)>>6;
         cout << " Z= "<< (int)cv;

         cv = (packet[2]&0x20)>>5;
         cout << " AD= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(Not Auth)";
                         break;
             }
             case 1 : {
                         cout << "(Auth)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cv = (packet[2]&0x10)>>4;
         cout << " CD= "<< (int)cv;
         switch (cv) {
             case 0 : {
                         cout << "(Not Check)";
                         break;
             }
             case 1 : {
                         cout << "(Check)";
                         break;
             }
             default: {
                     break;
                 }
         }
         cout << endl;

         cv = (packet[3]&0x0F);
         cout << "RCODE= "<< (int)cv << " ";
         switch (cv) {
             case 0 : {
                         cout << "No Error"<<endl;
                         break;
             }
             case 1 : {
                         cout << "Format Error"<<endl;
                         break;
             }
             case 2 : {
                         cout << "Server failure"<<endl;
                         break;
             }
             case 3 : {
                         cout << "Name Error"<<endl;
                         break;
             }
             case 4 : {
                         cout << "Not Implemented"<<endl;
                         break;
             }
             case 5 : {
                         cout << "Refused"<<endl;
                         break;
             }
             default: {
                     cout << "Undef"<<endl;
                         break;
                 }
         }

         memcpy( &sv, &packet[4], 2 );
         questions = ntohs(sv);
         cout << "QDCOUNT = "<< questions <<endl;
         memcpy( &sv, &packet[6], 2 );
         answers =  ntohs(sv);
         cout << "ANCOUNT = "<< answers <<endl;
         memcpy( &sv, &packet[8], 2 );
         authority = ntohs(sv);
         cout << "NSCOUNT = "<< authority <<endl;
         memcpy( &sv, &packet[10], 2 );
         additional = ntohs(sv);
         cout << "ARCOUNT = "<< additional <<endl;

         i = 12;
         j = 12;
         uint8_t buf[BUF_LEN];
         int8_t  name[MAX_NAME];
     cout << "Questions : " <<endl;
         for (k=0; k < questions;k++ ) {
                 len = 0;
                 j = i;
                 while( packet[j++] != '\0' ){len++;}
         memcpy(buf, &(packet[i]), len+1 );
                 convertName(buf, name, MAX_NAME-1);
         cout << k << ") Name: " << name << " ";
                 i += len+1;
             memcpy( &sv, &packet[i], 2 );
         cout << "Type = "<< ntohs(sv) <<"  ";
                 i += 2;
                 memcpy( &sv, &packet[i], 2 );
         cout << "Class = "<< ntohs(sv) <<endl;
                 i += 2;
         }
     cout << "Answers : " <<endl;
         for (k=0; k < answers;k++ ) {
                 len = 0;
                 j = i;
                 while( packet[j++] != '\0' ){len++;}
         memcpy(buf, &(packet[i]), len+1 );
                 buf[len+2] = '\0'; //redundant
                 convertName(buf, name, MAX_NAME-1);
         cout << k << ") Name: " << name << " ";
                 i += len+1;
             memcpy( &sv, &packet[i], 2 );
                 type = ntohs(sv);
         cout << "Type = "<< ntohs(sv) <<"  ";
                 i += 2;
                 memcpy( &sv, &packet[i], 2 );
         cout << "Class = "<< ntohs(sv) <<" ";
                 i += 2;
                 memcpy( &lv, &packet[i], 4 );
         cout << "TTL = "<< ntohl(lv) <<endl;
                 i += 4;
             memcpy( &sv, &packet[i], 2 );
                 len = ntohs(sv);
         cout << "  RdataLen = "<< ntohs(sv) <<"  ";
                 i += 2;
                 memcpy( buf, &packet[i], len );
                 i += len;
                 switch (type) {
                     case 1: //A records
                     {
                                 cout << "Data: " << (unsigned
 int)((unsigned char)buf[0])<<"."<< (unsigned int)((unsigned
 char)buf[1])<<"."<< (unsigned int)((unsigned char)buf[2])<<"."<< (unsigned
 int)((unsigned char)buf[3]) << endl;
                                 break;
                         }
                         default :
                         {
                                 cout << "Data: ";
                                 for(j=0;j<len;j++) cout << hex <<buf[j];
                                 cout << endl;
                                 break;
                         }
                 }
         }

         return 0;
 }

 int createDnsAnswer( uint16_t status, uint8_t const * const query,
 uint16_t qid, int8_t rec, uint32_t addr, uint8_t * const packet, int32_t
 maxLen ) {
         uint16_t sv;
         uint8_t  cv;
         uint32_t lv;
         int i,len;
     i = 0;

     if ( (12 + (int)strlen((const char *)query)+1 + 10 + 4) > maxLen ) {
         cerr << "Insufficient buffer space to build DNS answer"<<endl;
         return -1;
         }

     sv = htons(qid);
         memcpy( &packet[i], &sv, 2 ); //ID
         i+= 2;

         cv = 0;
         cv |= 1 << 7; //Response
         cv |= 1 << 2; //This is an authoritative answer
     cv |= rec;    //Recursion was requested
         packet[i++] = cv;

         cv = 0;
     cv |= rec << 7; //Recursion is available

         cv |= 1 << 5;   //Answer is authenticated
         if ( 0 != status ) {
          cv |= 0x02; //Hardcode error to Server Failure
         }
         packet[i++] = cv;

         sv = htons(1); //1 question was present
         memcpy( &packet[i], &sv, 2 );
         i+=2;
         sv = htons(1); //Only 1 answer is present
         memcpy( &packet[i], &sv, 2 );
         i+=2;
         sv = 0; //Zero Authority Responses are present
         memcpy( &packet[i], &sv, 2 );
         i+=2;
         sv = 0; //Zero Additional Responses are present
         memcpy( &packet[i], &sv, 2 );
         i+=2;
         //Populate the Queries portion
         len = strlen((const char *)query);//DNS query ends with a trailing
 zero

         memcpy( &packet[i], query, len+1 );//Name
         i+=len+1;

         sv = htons(1); //Type A
         memcpy( &packet[i], &sv, 2 );
         i+= 2;
         sv = htons(1); //Class IN
         memcpy( &packet[i], &sv, 2 );
         i+= 2;

         //Populate the Answers portion
         len = strlen((const char *)query);//DNS query ends with a trailing
 zero

         memcpy( &packet[i], query, len+1 );//Name
         i+=len+1;

         sv = htons(1); //Type A
         memcpy( &packet[i], &sv, 2 );
         i+= 2;
         sv = htons(1); //Class IN
         memcpy( &packet[i], &sv, 2 );
         i+= 2;

         lv = htonl(60); //TTL Hardcoded to 1 min
         memcpy( &packet[i], &lv, 4 );
         i+= 4;

         //As this is a response only for class A query, the rdata len is 4
         sv = htons(4); //RDLENGTH
         memcpy( &packet[i], &sv, 2 );
         i+= 2;

         memcpy( &packet[i], &addr, sizeof(addr));
         i+= sizeof(addr);

         return i;
 }

 int connectToSockProxy( int8_t const * const address, int8_t const * const
 port, SOCKET *outSocket ) {
     int status;
         uint8_t buf[BUF_LEN];
     ADDRINFO hints, *addrInfo;
     SOCKET sock;
     int optval;

     if ( INVALID_SOCKET == *outSocket ) {
                 if ( DEBUG ) cout << "Initializing TOR socket" << endl;
                 memset(&hints, 0, sizeof(hints));
                 hints.ai_family   = AF_INET;//PF_UNSPEC
                 hints.ai_socktype = SOCK_STREAM;
                 hints.ai_flags    = AI_NUMERICHOST;
                 hints.ai_protocol = IPPROTO_TCP;

                 status = getaddrinfo((char *)address, (char *)port,
 &hints, &addrInfo);
                 if ( 0 != status ) {
                         cerr << "getaddrinfo: " << WSAGetLastError() <<
 endl;
                         WSACleanup();
                         return -1;
                 }
                 sock = socket(addrInfo->ai_family, addrInfo->ai_socktype,
 addrInfo->ai_protocol);
                 if ( INVALID_SOCKET == sock ) {
                         cerr << "socket -TOR client: " <<
 WSAGetLastError() << endl;
                         freeaddrinfo(addrInfo);
                         return -1;
                 }

         //Set SO_REUSEADDR to true (1):
         optval = 1;
         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval,
 sizeof optval);

             if ( DEBUG ) cout << "Connect to the TOR proxy" << endl;
                 status = connect(sock, addrInfo->ai_addr,
 (int)addrInfo->ai_addrlen);
                 if ( SOCKET_ERROR == status ) {
                         cerr << "connect: " << WSAGetLastError() << endl;
                 freeaddrinfo(addrInfo);
                         closesocket(sock);
                         return -1;
                 }

         freeaddrinfo(addrInfo);

         } else {
                 if ( DEBUG ) cout << "Reusing previous socket " << endl;
                 sock = *outSocket;
         }

     // Send the initial SOCKS 5 connect request
         buf[0] = 0x5; //Ver 5
         buf[1] = 0x1; //1 Method
         buf[2] = 0x0; //No authentication
     if ( DEBUG ) cout << "Sending connect request to the TOR Proxy" <<
 endl;
     status = send(sock, (const char *) buf, (int) 3, 0);
     if ( SOCKET_ERROR == status ) {
         cerr << "send -TOR client: " << WSAGetLastError() << endl;
         closesocket(sock);
         return -1;
     }

         status = recv(sock, (char *) buf, BUF_LEN, 0);
         if ( SOCKET_ERROR == status ) {
                 if ( 0x5 != buf[0] ) {
                         cerr << "Received invalid header in SOCKS-5
 Connection Established response" << endl;
             closesocket(sock);
             return -1;
                 } else if ( 0xFF == buf[1] ) {
                         cerr << "Received invalid auth method in
 Connection Established response" << endl;
             closesocket(sock);
             return -1;
                 }
         } else if (0 == status) {
         cerr << "Connection closed" << endl;
         closesocket(sock);
         return -1;
         }
         if ( DEBUG ) cout << "Received connection ack from TOR Proxy" <<
 endl;
         *outSocket = sock;

         return 0;
 }

 int bindToDnsPort( int8_t const * const address, int8_t const * const
 port, SOCKET *outSocket ) {
     int status;
     ADDRINFO hints, *addrInfo;
     SOCKET sock;
         int optval;

     *outSocket = INVALID_SOCKET;

     //Bind to localhost and default DNS port
     memset(&hints, 0, sizeof(hints));
     hints.ai_family   = AF_INET;//PF_UNSPEC
     hints.ai_socktype = SOCK_DGRAM;
     hints.ai_flags    = AI_NUMERICHOST | AI_PASSIVE;
         hints.ai_protocol = IPPROTO_UDP;
     status = getaddrinfo((char *)address, (char *)port, &hints,
 &addrInfo);
     if ( 0 != status ) {
         cerr << "getaddrinfo -Local DNS Listener: " << WSAGetLastError()
 << endl;
                 freeaddrinfo(addrInfo);
         return -1;
     }

     sock = socket(addrInfo->ai_family, addrInfo->ai_socktype,
 addrInfo->ai_protocol);//PF_UNSPEC
     if ( INVALID_SOCKET == sock ) {
                 cerr << "socket -Local DNS Listener: " <<
 WSAGetLastError() << endl;
                 freeaddrinfo(addrInfo);
                 return -1;
     }

     //Set SO_REUSEADDR to true (1):
     optval = 1;
     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval,
 sizeof optval);

         status = bind( sock, addrInfo->ai_addr,
 (int)addrInfo->ai_addrlen);
     if ( SOCKET_ERROR == status ) {
                 cerr << "bind -Local DNS Listener: " << WSAGetLastError()
 << endl;
                 freeaddrinfo(addrInfo);
         closesocket(sock);
         return -1;
     }
         freeaddrinfo(addrInfo);

     *outSocket = sock;
     return 0;
 }

 int main(int argc, char* argv[])
 {
     WSADATA wsaData;
     int status;

         struct sockaddr_in from;
         int len, queryLen, nameLen;
     uint32_t  addr;

     SOCKET sockIn   = INVALID_SOCKET;
         SOCKET sockOut  = INVALID_SOCKET;
         int n;
     FD_SET fds;


         int8_t   name[MAX_NAME];
         uint8_t  query[MAX_QUERY];
         uint16_t qid;
         uint8_t  recursive;
     uint8_t  buf[BUF_LEN+1];
     struct timeval tv;

     const char *localAddress = "127.0.0.1";
         const char *dnsPort = "53"; //53 - DNS

     char  socksPort[6]  = {'9','0','5','0','\0'}; //SOCKS 5 Proxy - 9050

     if ( 3 < argc ) {
                 cerr << "Invalid number of arguments" << endl;
                 cerr << argv[0] << " [-p proxy-port]" << endl;
                 return -1;
     } else if ( 3 == argc ) {
         if (!strncmp("-p", argv[1], strlen("-p"))) {
                         if ( 0 != atoi(argv[2])) {
                    (void)strncpy(socksPort, argv[2], sizeof(socksPort)-1);
                         } else {
                         cerr << "Invalid argument:" << argv[2] << endl;
                         cerr << argv[0] << " [-p proxy-port]" << endl;
                                 return -1;
                         }
                 } else  {
                 cerr << "Invalid argument:" << argv[1] << endl;
                 cerr << argv[0] << " [-p proxy-port]" << endl;
                 return -1;
                 }
         } else if ( 2 == argc ) {
                 cerr << "Invalid argument:" << argv[1] << endl;
                 cerr << argv[0] << " [-p proxy-port]" << endl;
                 return -1;
         }

     status = WSAStartup(MAKEWORD(2, 2), &wsaData);
     if ( 0 != status ) {
                 cerr << "Winsock dll not found:"<< status <<endl;
         return -1;
     }

     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) {
         cerr <<  "Winsock version 2.2 not supported"<<endl;
         WSACleanup();
         return -1;
     }

     status = bindToDnsPort((int8_t *)localAddress, (int8_t *)dnsPort,
 &sockIn );
     if ( 0 != status ) {
                 cerr << "Unable to bind as a local DNS server" << endl;
         WSACleanup();
         return -1;
         }


         do {
                  FD_ZERO(&fds);
          FD_SET(sockIn, &fds);
          //FD_SET(sockOut, &fds);
                  n = sockIn +1;
                  status = select(n, &fds, NULL, NULL, NULL);
                  if ( SOCKET_ERROR == status ) {
                         cerr << "select: " << WSAGetLastError() << endl;
                         closesocket(sockIn);closesocket(sockOut);
                         WSACleanup();
                         return -1;
                  }

                  if (FD_ISSET(sockIn, &fds)) {
             //Received a DNS Query
                         if ( DEBUG ) cout << "Received a DNS request"
 <<endl;
                     len = sizeof(struct sockaddr_in);
                 status = recvfrom(sockIn, (char *) buf, BUF_LEN, 0,
 (struct sockaddr *) &from, &len );
             if ( SOCKET_ERROR == status ) {
                                 if ( 10054 != WSAGetLastError()) {
 //Ignore reset connection
                                     cerr << "recvfrom -Local DNS Listener:
 " << WSAGetLastError() << endl;
                                 }
                                 status = 0;
                                 continue;
                     }

             if ( DEBUG ) parseDns( buf);
             queryLen = MAX_QUERY-1;
                         status = parseDnsQuery( buf, &qid, &recursive,
 query, &queryLen );
                         if ( 0 > status ) {
                                 status = 0;
                                 cerr << "Unsupported request" << endl;
                                 continue;
                         }
                         if ( 0 < queryLen ) {
                                 nameLen = convertName( query, name,
 MAX_NAME-1);
                                 if ( UCHAR_MAX  < nameLen ) {
                                         cerr << "Queried Domain name
 length exceeds max length" << endl;
                                         continue;
                                 }
                                 if (DEBUG) cout << "Connecting to the TOR
 proxy" << endl;
                         //Connect to the SOCKS5 Server at localhost and
 Tor-Socks proxy port
                 status = connectToSockProxy((int8_t *)localAddress,
 (int8_t *)socksPort, &sockOut );
                 if ( 0 != status ) {
                             cerr << "Unable to connect to the Tor server"
 << endl;
                                         continue;
                     }

                 // Send the UDP Resolve request
                 buf[0] = 0x05; //Ver 5
                     buf[1] = 0xF0; //Cmd Resolve -- TOR Extension
                     buf[2] = 0x00; //Reserved
                     buf[3] = 0x03; //ATYP = DomainName
                     buf[4] = (uint8_t) nameLen;
                 memcpy( &(buf[5]), name, nameLen);
                                 buf[5+nameLen]   = 0; //Still need to add
 a fake port
                                 buf[5+nameLen+1] = 0;
                 len = nameLen + 5 + 2;

                                 if (DEBUG) cout << "Sending Resolve for ["
 << name << "] " << len << " to the TOR proxy" << endl;
                                 FD_ZERO(&fds);
                                 FD_SET(sockOut, &fds);
                                 //Forward the DNS request to the Socks
 proxy
                 status = send(sockOut, (char *) buf, len, 0);
                                 if ( SOCKET_ERROR == status ) {
                         cerr << "send -TOR client: " << WSAGetLastError()
 << endl;
                                         cerr <<"Unable to forward request"
 << endl;
                                         status = 0;
                                         continue;
                                 }
                                 //There's no way to correlate the TOR
 response with a request, we need to wait
                                 //for the answer to this request before
 handling any new query.
                                 //Wait for response/requests on the Tor
 sockets
                 if ( DEBUG ) cout << "Waiting for TOR response" <<endl;
                                 tv.tv_sec = 10;
                 tv.tv_usec = 500000;

                 n = sockOut +1;
                                 status = select(n, &fds, NULL, NULL, &tv
 );
                                 if ( SOCKET_ERROR == status ) {
                                          cerr << "select: " <<
 WSAGetLastError() << endl;
 closesocket(sockIn);closesocket(sockOut);
                                          WSACleanup();
                                          return -1;
                              } else if ( 0 == status ) {
                                          cerr << "No response received
 from Tor Proxy" << endl;
                                          closesocket(sockOut);
                                          sockOut = INVALID_SOCKET;
                                          continue;
                                  }

                                  if (FD_ISSET(sockOut, &fds)) {
                                          if ( DEBUG ) cout << "Received
 data from TOR " << endl;
                                      //Receive a response from the TOR
 proxy
                                      status = recv(sockOut, (char *) buf,
 BUF_LEN, 0 );
                                  if ( SOCKET_ERROR == status ) {
                                             cerr << "recv -TOR client: "
 << WSAGetLastError() << endl;
                                             status = 0;
                                                 closesocket(sockOut);
                                             sockOut = INVALID_SOCKET;
                                             continue;
                                          }
                                      status = 0;
                                  if ( 0x05 != buf[0] ) {
                                                  status = 1;
                                                  cerr <<"Invalid Header in
 Tor Response" << endl;
                                          }
                                  else if ( 0x00 != buf[1] )  {
                                                  status = 1;
                                                  cerr <<"The Tor Proxy
 returned an error:" <<(int)((unsigned char)buf[1]) << endl;
                                          }
                                  else if ( 0x01 != buf[3] )  {
                                                  status = 1;
                                                  cerr <<"The Tor Proxy
 returned an invalid ATYP:" <<(int)((unsigned char)buf[3]) << endl;
                                          }
                      memcpy( &addr, &buf[4], sizeof(addr));
                                          if ( DEBUG ) cout << "Creating a
 DNS response " << endl;
                      len = createDnsAnswer((uint16_t)status, query, qid,
 recursive, addr, buf, BUF_LEN);
                      if ( DEBUG) parseDns( buf );
                                          //Forward the DNS response
                      sendto( sockIn, (const char *) buf, len, 0, (struct
 sockaddr *) &from, sizeof(struct sockaddr_in));
                                          //Disconnect from the Socks proxy
                                          if (DEBUG) cout << "Disconnecting
 from the TOR proxy" <<endl;
                                      //status = shutdown(sockOut,
 SD_SEND);
                      if ( SOCKET_ERROR == status ) {
                          cerr << "shutdown: " << WSAGetLastError() <<
 endl;
                      }
                                          if (INVALID_SOCKET != sockOut)
 closesocket(sockOut);
                                          sockOut = INVALID_SOCKET;

                                 }
                         }
 /*
                     } else if (FD_ISSET(sockOut, &fds)) {
                                 //This should not happen unless the Tor
 proxy die
                                  status = recv(sockOut, (char *)buf,
 BUF_LEN, 0 );
                                  if ( SOCKET_ERROR == status ) {
                                         cerr << "Connection with Tor
 server dropped";
                                         status = 0;
                                         continue;
                                  }
                                  //discard
                         }
 */
             }
     } while (status >= 0);

     // shutdown the send half of the connection since no more data will be
 sent
     status = shutdown(sockOut, SD_SEND);
     if ( SOCKET_ERROR == status ) {
         cerr << "shutdown: " << WSAGetLastError() << endl;
     }

     if (INVALID_SOCKET != sockIn) closesocket(sockIn);
         if (INVALID_SOCKET != sockOut) closesocket(sockOut);

     WSACleanup();
     return 0;
 }

-- 
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/2602>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online


More information about the tor-bugs mailing list