104

Over the years (since 2005), I have seen logs of strange random DNS requests done, on the multiple DNS / BIND servers I have maintained.

May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#24123 (verxkgiicjmcnxg): view internal: query: verxkgiicjmcnxg IN A + (1.1.1.1)
May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#29159 (epqoaqsayo): view internal: query: epqoaqsayo IN A + (1.1.1.1)
May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#27411 (qlllglwcjglu): view internal: query: qlllglwcjglu IN A + (1.1.1.1)

I usually chalked it up to some Windows malware. However, I have starting noticing it also is coming from Linux and Mac clients, lately. Again I thought it could be due to some malicious browser plug-in(s).

However, while debugging a Google Chrome browser issue, in my newly installed Macbook Pro/Chrome, using the URL chrome://net-internals/#dns, I found similar requests in my Chrome DNS statistics page.

My Chrome browser has rather innocuous plug-ins installed and no apparent signs of malware.

I have my honest doubts whether it should be or not malicious activity. What is happening?

(As seen in the image, pnxcygqqemww, ryzypwbheguutkd, and snplueo DNS names requests made by Chrome).

dns

Sniffing the DNS activity when the Chrome browser is opening, with:

sudo tcpdump -n port 53

I am able to see the following DNS requests, and again the random requests at 10:20:34:

Opening Chrome:

tcpdump: data link type PKTAP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
10:20:27.119736 IP 1.1.1.2.12568 > 1.1.1.1.53: 10990+ A? apis.google.com. (33)
10:20:27.119962 IP 1.1.1.2.34930 > 1.1.1.1.53: 13828+ A? disconnect.me. (31)
10:20:27.120078 IP 1.1.1.2.17860 > 1.1.1.1.53: 37420+ A? mxr.mozilla.org. (33)
10:20:27.120314 IP 1.1.1.1.53 > 1.1.1.2.12568: 10990 2/4/4 CNAME plus.l.google.com., A 216.58.214.174 (206)
10:20:27.120479 IP 1.1.1.1.53 > 1.1.1.2.34930: 13828 3/4/8 A 54.197.255.152, A 54.225.94.202, A 204.236.239.134 (339)
10:20:27.120666 IP 1.1.1.1.53 > 1.1.1.2.17860: 37420 1/4/5 A 63.245.215.42 (234)
10:20:27.123394 IP 1.1.1.2.51642 > 1.1.1.1.53: 58375+ A? ssl.gstatic.com. (33)
10:20:27.123658 IP 1.1.1.2.17933 > 1.1.1.1.53: 48570+ A? www.google.pt. (31)
10:20:27.123726 IP 1.1.1.1.53 > 1.1.1.2.51642: 58375 1/4/4 A 216.58.214.163 (192)
10:20:27.123897 IP 1.1.1.2.57779 > 1.1.1.1.53: 7559+ A? www.gstatic.com. (33)
10:20:27.123946 IP 1.1.1.1.53 > 1.1.1.2.17933: 48570 1/4/4 A 216.58.207.163 (193)
10:20:27.124192 IP 1.1.1.1.53 > 1.1.1.2.57779: 7559 16/4/4 A 194.210.238.166, A 194.210.238.170, A 194.210.238.174, A 194.210.238.176, A 194.210.238.177, A 194.210.238.181, A 194.210.238.185, A 194.210.238.187, A 194.210.238.144, A 194.210.238.148, A 194.210.238.152, A 194.210.238.154, A 194.210.238.155, A 194.210.238.159, A 194.210.238.163, A 194.210.238.165 (432)
10:20:27.432926 IP 1.1.1.2.29865 > 1.1.1.1.53: 62300+ A? clients4.google.com. (37)
10:20:27.433219 IP 1.1.1.2.28193 > 1.1.1.1.53: 23734+ A? translate.googleapis.com. (42)
10:20:27.433703 IP 1.1.1.1.53 > 1.1.1.2.29865: 62300 2/4/4 CNAME clients.l.google.com., A 216.58.211.238 (213)
10:20:27.464772 IP 1.1.1.1.53 > 1.1.1.2.28193: 23734 1/4/4 A 216.58.198.202 (201)
10:20:28.430622 IP 1.1.1.2.46792 > 1.1.1.1.53: 1963+ A? accounts.google.com. (37)
10:20:28.431046 IP 1.1.1.1.53 > 1.1.1.2.46792: 1963 1/4/4 A 216.58.201.141 (189)
10:20:32.348765 IP 1.1.1.2.16654 > 1.1.1.1.53: 39847+ A? www.google.com. (32)
10:20:32.349362 IP 1.1.1.1.53 > 1.1.1.2.16654: 39847 1/4/4 A 216.58.213.164 (184)

After a couple of seconds, the mentioned random DNS requests, do indeed appear:

10:20:34.159229 IP 1.1.1.2.5042 > 1.1.1.1.53: 47676+ A? kblxfid.xxx.xxx.xxx. (44)
10:20:34.159829 IP 1.1.1.2.63360 > 1.1.1.1.53: 55094+ A? weefjmw.xxx.xxx.xxx. (44)
10:20:34.159893 IP 1.1.1.1.53 > 1.1.1.2.5042: 47676 NXDomain* 0/1/0 (104)
10:20:34.160230 IP 1.1.1.1.53 > 1.1.1.2.63360: 55094 NXDomain* 0/1/0 (104)
10:20:34.160872 IP 1.1.1.2.29339 > 1.1.1.1.53: 22434+ A? luebcanqpumlaj.xxx.xxx.xxx. (51)
10:20:34.161290 IP 1.1.1.1.53 > 1.1.1.2.29339: 22434 NXDomain* 0/1/0 (111)
10:20:34.162489 IP 1.1.1.2.64592 > 1.1.1.1.53: 49055+ A? kblxfid.xxx.xxx.xxx. (44)
10:20:34.162859 IP 1.1.1.1.53 > 1.1.1.2.64592: 49055 NXDomain* 0/1/0 (104)
10:20:34.164105 IP 1.1.1.2.50225 > 1.1.1.1.53: 1276+ A? weefjmw.xxx.xxx.xxx. (44)
10:20:34.164386 IP 1.1.1.2.52389 > 1.1.1.1.53: 59022+ A? luebcanqpumlaj.xxx.xxx.xxx. (51)
10:20:34.164472 IP 1.1.1.1.53 > 1.1.1.2.50225: 1276 NXDomain* 0/1/0 (104)
10:20:34.164751 IP 1.1.1.1.53 > 1.1.1.2.52389: 59022 NXDomain* 0/1/0 (111)

Opening a new tab in Chrome:

10:20:44.106915 IP 1.1.1.2.26171 > 1.1.1.1.53: 14460+ A? clients2.google.com. (37)
10:20:44.139387 IP 1.1.1.1.53 > 1.1.1.2.26171: 14460 2/4/4 CNAME clients.l.google.com., A 216.58.211.238 (213)

Also, according to @Gilles link, when using a proxy (Squid) in Chrome, you can see the random DNS names in the corresponding Squid access.log log file, when Chrome is booting:

1494276554.709    216 127.0.0.1 TCP_MISS/504 277 HEAD http://vgifrooogs/ - DIRECT/vgifrooogs text/html
1494276554.731    238 127.0.0.1 TCP_MISS/504 277 HEAD http://cbwknhka/ - DIRECT/cbwknhka text/html  
1494276554.875    382 127.0.0.1 TCP_MISS/504 277 HEAD http://vtjhiag/ - DIRECT/vtjhiag text/html
2

1 Answer 1

143

I found a series of posts/bug reports about random DNS requests made by Chrome. The conclusion is those random DNS requests are neither generated by malware nor by plugins or add-ons.

The requests are done by Chrome, to learn if it can handle searches made from its address bar.

The best explanation I have found is quoted below, from this link.

If you type in a single-word search query, chrome needs to send a DNS request to check if this might be a single-word host name: For example, "test" might be a search for "test" or a navigation to "http://test". If the query ends up being a host, chrome shows an infobar that asks "did you mean to go to 'test' instead". For performance reasons, the DNS query needs to be asynchronous.

Now some ISPs started showing ads for non-existent domain names ( http://en.wikipedia.org/wiki/DNS_hijacking ), meaning Chrome would always show that infobar for every single-word query. Since this is annoying, chrome now sends three random DNS requests at startup, and if they all resolve (to the same IP, I think), it now knows not to show the "did you mean" infobar for single-word queries that resolve to that IP.

Beyond ISP level or malware DNS hijacking, mentioned in the Wikipedia entry above, some paid wireless access points or captive portals also hijack DNS. Random requests are made at seemingly random intervals,and not just when starting Chrome. At least, they happen each time the current network interface gets a new IP address.

Here is another link related to the theme from @Gilles: Unusual HEAD requests to nonsense URLs from Chrome. Hence, adding to the question the topic of proxy test setup. You end up seeing proxy logs because, when a proxy is configured, the requests are made via the proxy; and, it is up to the proxy to resolve the DNS requests.

Lacking more solid details online, I downloaded and perused the Chromium source code, with the command below.

git clone https://chromium.googlesource.com/chromium/src 

The quote below was copied from the Chromium source code comments:

Because this function can be called during startup, when kicking off a URL fetch can eat up 20 ms of time, we delay seven seconds, which is hopefully long enough to be after startup, but still get results back quickly.

This component sends requests to three randomly generated, and thus likely nonexistent, hostnames. If at least two redirect to the same hostname, this suggests the ISP is hijacking NXDOMAIN, and the omnibox should treat similar redirected navigations as 'failed' when deciding whether to prompt the user with a 'did you mean to navigate' infobar for certain search inputs.

trigger: "On startup and when IP address of the computer changes."

We generate a random hostname with between 7 and 15 characters.

My conclusion is that those random DNS request names are not a manifestation of malware behaviour ; they are probes for Chromium (and Google Chrome) to learn what it can do, concerning at least searches.

Lacking more solid details online, I downloaded the Chromium sources in my investigation. The logic dealing with this functionality can be found at in the file, src/chrome/browser/intranet_redirect_detector.cc and src/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc.

Below is an excerpt of src/chrome/browser/intranet_redirect_detector.cc:

void IntranetRedirectDetector::FinishSleep() {
  in_sleep_ = false;

  // If another fetch operation is still running, cancel it.
  fetchers_.clear();
  resulting_origins_.clear();

  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  if (cmd_line->HasSwitch(switches::kDisableBackgroundNetworking))
    return;

  DCHECK(fetchers_.empty() && resulting_origins_.empty());

  // Create traffic annotation tag.
  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("intranet_redirect_detector", R"(
        semantics {
          sender: "Intranet Redirect Detector"
          description:
            "This component sends requests to three randomly generated, and "
            "thus likely nonexistent, hostnames.  If at least two redirect to "
            "the same hostname, this suggests the ISP is hijacking NXDOMAIN, "
            "and the omnibox should treat similar redirected navigations as "
            "'failed' when deciding whether to prompt the user with a 'did you "
            "mean to navigate' infobar for certain search inputs."
          trigger: "On startup and when IP address of the computer changes."
          data: "None, this is just an empty request."
          destination: OTHER
        }
        policy {
          cookies_allowed: false
          setting: "This feature cannot be disabled by settings."
          policy_exception_justification:
              "Not implemented, considered not useful."
        })");

  // Start three fetchers on random hostnames.
  for (size_t i = 0; i < 3; ++i) {
    std::string url_string("http://");
    // We generate a random hostname with between 7 and 15 characters.
    const int num_chars = base::RandInt(7, 15);
    for (int j = 0; j < num_chars; ++j)
      url_string += ('a' + base::RandInt(0, 'z' - 'a'));
    GURL random_url(url_string + '/');
    std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create(
        random_url, net::URLFetcher::HEAD, this, traffic_annotation);
    // We don't want these fetches to affect existing state in the profile.
    fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                          net::LOAD_DO_NOT_SAVE_COOKIES |
                          net::LOAD_DO_NOT_SEND_COOKIES |
                          net::LOAD_DO_NOT_SEND_AUTH_DATA);
    fetcher->SetRequestContext(g_browser_process->system_request_context());
    fetcher->Start();
    net::URLFetcher* fetcher_ptr = fetcher.get();
    fetchers_[fetcher_ptr] = std::move(fetcher);
  }
}

void IntranetRedirectDetector::OnURLFetchComplete(
    const net::URLFetcher* source) {
  // Delete the fetcher on this function's exit.
  auto it = fetchers_.find(const_cast<net::URLFetcher*>(source));
  DCHECK(it != fetchers_.end());
  std::unique_ptr<net::URLFetcher> fetcher = std::move(it->second);
  fetchers_.erase(it);

  // If any two fetches result in the same domain/host, we set the redirect
  // origin to that; otherwise we set it to nothing.
  if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) {
    if ((resulting_origins_.empty()) ||
        ((resulting_origins_.size() == 1) &&
         resulting_origins_.front().is_valid())) {
      resulting_origins_.push_back(GURL());
      return;
    }
    redirect_origin_ = GURL();
  } 

....

Below is an excerpt of the file, src/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc:

// Returns true if |final_url| doesn't represent an ISP hijack of
// |original_url|, based on the IntranetRedirectDetector's RedirectOrigin().
bool IsValidNavigation(const GURL& original_url, const GURL& final_url) {

....

void ChromeOmniboxNavigationObserver::NavigationEntryCommitted(
    const content::LoadCommittedDetails& load_details) {
  load_state_ = LOAD_COMMITTED;
  if (ResponseCodeIndicatesSuccess(load_details.http_status_code) &&
      IsValidNavigation(match_.destination_url,
                        load_details.entry->GetVirtualURL()))
    OnSuccessfulNavigation();
  if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE))
    OnAllLoadingFinished();  // deletes |this|!
}

...

void ChromeOmniboxNavigationObserver::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK_EQ(fetcher_.get(), source);
  const net::URLRequestStatus& status = source->GetStatus();
  int response_code = source->GetResponseCode();
  fetch_state_ =
      (status.is_success() && ResponseCodeIndicatesSuccess(response_code)) ||
              ((status.status() == net::URLRequestStatus::CANCELED) &&
               ((response_code / 100) == 3) &&
               IsValidNavigation(alternate_nav_match_.destination_url,
                                 source->GetURL()))
          ? FETCH_SUCCEEDED
          : FETCH_FAILED;
  if (load_state_ == LOAD_COMMITTED)
    OnAllLoadingFinished();  // deletes |this|!
}

Related link: Mixed case DNS requests - Malware in my network?.

Slightly related: Why does Chromium not cache DNS for more than a minute?

6
  • @cat Thanks, since you like this perhaps you would like this one too unix.stackexchange.com/questions/363498/… Commented May 7, 2017 at 14:17
  • 4
    "There are also hints those random requests are made at seemingly random intervals, and not just when starting Chrome" — definitely true. I see them in packet logs even though I basically never restart chrome.
    – Kevin
    Commented May 8, 2017 at 2:41
  • 3
    @Kevin "whenever the computer's IP address changes" -- your computer needs to renew its DHCP lease with the router at seemingly random intervals, which would trigger this.
    – Riking
    Commented Jul 26, 2018 at 5:51
  • @Riking Indeed. I commented that out expressly. I am not however sure whether it happens in other conditions. Commented Jul 26, 2018 at 10:50
  • 1
    For context, queries like these made up ~50% of queries at the root zone (read it here - blog.verisign.com/domain-names/…) Also, apparently as of Chromium 87 this "feature" has been removed (read it here - blog.verisign.com/domain-names/…)
    – kimbo
    Commented Jan 20, 2021 at 17:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .