shared_ptr<DnsClientResult>DnsLookupClient::LookupDiscoveryService( shared_ptr<Domain>domain) { if (domain.get() == nullptr) { throw exceptions::RMSInvalidArgumentException("Invalid domain"); } auto pResolver = IDnsServerResolver::Create(); string domainString = domain->GetDomainStringForDnsLookup(); vector<string> possibleDomains = GetPossibleDomains(domainString); for (auto possibleDomainIt = begin(possibleDomains); possibleDomainIt != end(possibleDomains); ++possibleDomainIt) { Logger::Hidden("possibleDomain: %s", possibleDomainIt->c_str()); string dnsRequest(RMS_QUERY_PREFIX + *possibleDomainIt); auto dnsResponse = pResolver->lookup(dnsRequest); if (dnsResponse.empty()) { Logger::Hidden("Failed DNS lookup with domain: %s", possibleDomainIt->c_str()); continue; } Logger::Hidden("Successfully queried results with domain: %s", possibleDomainIt->c_str()); return DnsClientResult::Create(dnsResponse); } return DnsClientResult::Create(string("api.aadrm.com")); }
// use during setup, as this discards all incoming requests until it returns bool EtherCard::dnsLookup (const char* name, bool fromRam) { word start = millis(); while(!isLinkUp()) { packetLoop(packetReceive()); if ((word) (millis() - start) >= 30000) return false; //timeout waiting for link } start = millis(); while(clientWaitingGw()) { packetLoop(packetReceive()); if ((word) (millis() - start) >= 30000) return false; //timeout waiting for gateway ARP } memset(hisip, 0, 4); dnsRequest(name, fromRam); start = millis(); while (hisip[0] == 0) { if ((word) (millis() - start) >= 30000) return false; //timout waiting for dns response word len = packetReceive(); if (len > 0 && packetLoop(len) == 0) //packet not handled by tcp/ip packet loop if(checkForDnsAnswer(len)) return false; //DNS response recieved with error } return true; }
bool RuleList::removeDomain(QString appName, QString domainName, unsigned int port) { bool ret=true; QList<QString> ips=dnsRequest(domainName); for(int i=0;i<ips.size();i++) if(!removeRule(appName, ips[i], port)) ret=false; return ret; }
bool RuleList::addDomain(QString appName, QString domainName, unsigned int port) { //If we forbid to add a domain if(maxDomainsPerApplication()==0) return false; //If we only one domain per app, then, delete the currently allowed domain if(rules[appName].size()>0 && maxDomainsPerApplication()==1) removeAppRules(appName); //Add the domain QList<QString> ips=dnsRequest(domainName); for(int i=0;i<ips.size();i++) addRule(appName, ips[i], port); return true; }
// use during setup, as this discards all incoming requests until it returns bool EtherCard::dnsLookup (prog_char* name, bool fromRam) { while (!isLinkUp() || clientWaitingGw()) packetLoop(packetReceive()); memset(hisip, 0, 4); dnsRequest(name, fromRam); word start = millis(); while (hisip[0] == 0) { if ((word) (millis() - start) >= 30000) return false; word len = packetReceive(); if (len > 0 && packetLoop(len) == 0) checkForDnsAnswer(len); } return true; }
IPv4Address NetworkUtils::getIPv4Address(std::string hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL, int dnsTimeout, IPv4Address dnsServerIP, IPv4Address gatewayIP) { IPv4Address result = IPv4Address::Zero; // open the device if not already opened bool closeDeviceAtTheEnd = false; if (!device->isOpened()) { closeDeviceAtTheEnd = true; if (!device->open()) { LOG_ERROR("Cannot open device"); return result; } } // first - resolve gateway MAC address // if gateway IP wasn't provided - try to find the default gateway if (gatewayIP == IPv4Address::Zero) { gatewayIP = device->getDefaultGateway(); } if (!gatewayIP.isValid() || gatewayIP == IPv4Address::Zero) { LOG_ERROR("Gateway address isn't valid or couldn't find default gateway"); return result; } // send the ARP request to find gateway MAC address double arpResTime; MacAddress gatewayMacAddress = getMacAddress(gatewayIP, device, arpResTime); if (gatewayMacAddress == MacAddress::Zero) { LOG_ERROR("Coulnd't resolve gateway MAC address"); return result; } if (dnsTimeout <= 0) dnsTimeout = NetworkUtils::DefaultTimeout; // validate DNS server IP. If it wasn't provided - set the system-configured DNS server if (dnsServerIP == IPv4Address::Zero && device->getDnsServers().size() > 0) { dnsServerIP = device->getDnsServers().at(0); } if (!dnsServerIP.isValid()) { LOG_ERROR("DNS server IP isn't valid"); return result; } // create DNS request Packet dnsRequest(100); MacAddress sourceMac = device->getMacAddress(); EthLayer ethLayer(sourceMac, gatewayMacAddress, PCPP_ETHERTYPE_IP); IPv4Layer ipLayer(device->getIPv4Address(), dnsServerIP); ipLayer.getIPv4Header()->timeToLive = 128; // randomize source port to a number >= 10000 int srcPortLowest = 10000; int srcPortRange = (2^16) - srcPortLowest; uint16_t srcPort = (rand() % srcPortRange) + srcPortLowest; UdpLayer udpLayer(srcPort, DNS_PORT); // create the DNS request for the hostname DnsLayer dnsLayer; // randomize transaction ID uint16_t transactionID = rand() % (2^16); dnsLayer.getDnsHeader()->transactionID = htons(transactionID); dnsLayer.addQuery(hostname, DNS_TYPE_A, DNS_CLASS_IN); // add all layers to packet if (!dnsRequest.addLayer(ðLayer) || !dnsRequest.addLayer(&ipLayer) || !dnsRequest.addLayer(&udpLayer) || !dnsRequest.addLayer(&dnsLayer)) { LOG_ERROR("Couldn't construct DNS query"); return result; } dnsRequest.computeCalculateFields(); // set a DNS response filter on the device PortFilter dnsResponseFilter(53, SRC); if (!device->setFilter(dnsResponseFilter)) { LOG_ERROR("Couldn't set DNS respnse filter"); return result; } // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between the capture // thread and the main thread. When the capture thread starts running the main thread is blocking on the conditional mutex. // When the DNS response are captured the capture thread signals the main thread and the main thread stops capturing and continues // to the next iteration. if a timeout passes and no DNS response is captured, the main thread stops capturing pthread_mutex_t mutex; pthread_cond_t cond; // init the conditonal mutex pthread_mutex_init(&mutex, 0); pthread_cond_init(&cond, 0); // this is the token that passes between the 2 threads DNSRecievedData data = { &mutex, &cond, hostname, transactionID, clock(), IPv4Address::Zero, 0, 0 }; struct timeval now; gettimeofday(&now,NULL); // create the timeout timespec timeout = { now.tv_sec + dnsTimeout, now.tv_usec }; // start capturing. The capture is done on another thread, hence "dnsResponseRecieved" is running on that thread device->startCapture(dnsResponseRecieved, &data); // send the DNS request device->sendPacket(&dnsRequest); pthread_mutex_lock(&mutex); // block on the conditional mutex until capture thread signals or until timeout expires int res = pthread_cond_timedwait(&cond, &mutex, &timeout); // stop the capturing thread device->stopCapture(); pthread_mutex_unlock(&mutex); // check if timeout expired if (res == ETIMEDOUT) { LOG_ERROR("DNS request time out"); return result; } pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); if (closeDeviceAtTheEnd) device->close(); else device->clearFilter(); result = data.result; dnsResponseTimeMS = data.dnsResponseTime; dnsTTL = data.ttl; return result; }