Question about very rare DNS leak

First thing first, I’m using DNS over TLS and everything has been working fine for months.

I have a script on my monitoring server that checks for DNS leaks every hour using bash.ws/dnsleak API. I normally get an output such as this (currently):

108.162.240.93 [Canada, AS13335 CloudFlare Inc.] ❘ 108.162.240.94 [Canada, AS13335 CloudFlare Inc.]

However, once every blue moon, I get what seems to be a leak. Here are some examples:

Thu Sept 28 11:35:21 EDT 2023 162.158.125.17 [Canada, AS13335 CloudFlare Inc.] | 195.140.213.48 [United Kingdom, AS25369 Hydra Communications Ltd]
Sun Oct 1 18:07:21 EDT 2023 31.20.234.216 [Netherlands, AS50266 T-Mobile Thuis BV] | 162.158.125.17 [Canada, AS13335 CloudFlare Inc.]
Mon Nov 13 18:27:15 EST 2023 108.162.240.93 [Canada, AS13335 CloudFlare Inc.] | 108.162.240.94 [Canada, AS13335 CloudFlare Inc.] | 108.162.240.95 [Canada, AS13335 CloudFlare Inc.] | 108.162.240.96 [Canada, AS13335 CloudFlare Inc.] | 194.126.177.48 [Germany, AS209103 Proton AG] | 194.126.177.50 [Germany, AS209103 Proton AG] | 194.126.177.51 [Germany, AS209103 Proton AG] | 194.126.177.52 [Germany, AS209103 Proton AG] | 194.126.177.53 [Germany, AS209103 Proton AG] | 194.126.177.54 [Germany, AS209103 Proton AG] | 194.126.177.57 [Germany, AS209103 Proton AG] | 194.126.177.58 [Germany, AS209103 Proton AG] | 194.126.177.59 [Germany, AS209103 Proton AG]
Mon Nov 27 01:47:15 EST 2023 74.125.44.132 [United States of America, AS15169 Google LLC] | 162.158.125.68 [Canada, AS13335 CloudFlare Inc.]
Mon Nov 27 15:13:15 EST 2023 80.255.10.194 [Germany, AS201011 Core-Backbone GmbH] | 108.162.240.94 [Canada, AS13335 CloudFlare Inc.] | 162.158.125.68 [Canada, AS13335 CloudFlare Inc.]

If I run the script again (manually), it’s already gone, no more leak. I’m pretty certain it has nothing to do with my setup, any leak test ran manually hundred of times will return only Cloudflare, and this API also returns Cloudflare 24 times every day for almost every day. I don’t think there is any problem per se, but I’m curious at to why it happens.

Is there somewhere else I should ask about this?

Domain?

Hi @danieldl,

First, Cloudflare’s DNS resolver runs at multiple places, and the traffic could be steered to another location if a datacenter need to be put offline for maintenance for example. So in this case, the backend IP changed from 108.162.240.93/108.162.240.94 to something else.

Second, you might want to check your system’s DNS setup, confirming if it has some other DNS servers specified, like VPN or DHCP change, resulting the change of DNS.

1 Like

@danieldl Mind showing what your script looks like? Also, on which device are you running this script? Is it a Linux box? Please show the output of cat /etc/resolv.conf. How did you setup DNS over TLS? DNS ‘Leaks’ are never a DNS provider’s issue, only a client issue. The ‘leak’ name comes from VPN terminology, where DNS queries are not sent via the VPN server but leaked outside (possibly to your ISP’s nameservers), thus leaking data about your connections.

2 Likes

Sorry for the delay.

The script runs on my router (OPNsense), the output format is for my Checkmk monitoring server. here it is:

#!/usr/bin/env python3
# encoding=utf-8
# Any questions: [email protected]
# https://bash.ws/dnsleak

import os
import subprocess
import json
from random import randint
from platform import system as system_name
from subprocess import call as system_call

try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen


def ping(host):
    fn = open(os.devnull, 'w')
    command = ['ping', '-c', '1', host]
    retcode = system_call(command, stdout=fn, stderr=subprocess.STDOUT)
    fn.close()
    return retcode == 0


leak_id = randint(1000000, 9999999)
for x in range(0, 10):
    ping('.'.join([str(x), str(leak_id), "bash.ws"]))

response = urlopen("https://bash.ws/dnsleak/test/"+str(leak_id)+"?json")
data = response.read().decode("utf-8")
parsed_data = json.loads(data)

servers = 0
for dns_server in parsed_data:
    if dns_server['type'] == "dns":
        servers = servers + 1

result = ''
status = 0
if servers == 0:
    status = 3
    result = "No DNS servers found | "
else:
    for dns_server in parsed_data:
        if dns_server['type'] == "dns":
            if dns_server['country_name']:
                if dns_server['asn']:
                    result = f"{result}{dns_server['ip']} [{dns_server['country_name']}, {dns_server['asn']}] | "
                    if "cloudflare" not in dns_server['asn'].lower(): status = 2
                else:
                    status = 1
                    result = f"{result}{dns_server['ip']} [{dns_server['country_name']}] | "
            else:
                status = 1
                result = f"{result}{dns_server['ip']} "

print(f"{status} \"DNS Leak Test\" dns_servers={servers} {result[:-2]}")

My resolv.conf with my domain:

domain home.dnll.xyz
nameserver 127.0.0.1
search home.dnll.xyz

Relevant Unbound settings:

I don’t think there is anything wrong with my settings, DNS over TLS works, I never get any leaks when I actually check by myself, it’s only because I added an automatic check running every hour that I eventually noticed that sometimes it’s not reported as Cloudflare.

Only one occurrence of the problem since I posted.

Sat Jan 6 07:55:33 EST 2024 80.255.10.194 [Germany, AS201011 Core-Backbone GmbH] | 162.158.125.68 [Canada, AS13335 CloudFlare Inc.]

I would ignore that script.

The script is generating a number, that it is calling “leak_id”, which is supposed to be a random number.

Let’s say that this number is “1234567890”.

The script is then pinging all the hostnames:

1.1234567890.bash.ws
2.1234567890.bash.ws
3.1234567890.bash.ws
4.1234567890.bash.ws
5.1234567890.bash.ws
6.1234567890.bash.ws
7.1234567890.bash.ws
8.1234567890.bash.ws
9.1234567890.bash.ws
10.1234567890.bash.ws

Now, ask yourself, … is the number “1234567890” very random, … or not?

If you receive the leak_id1234567890” on your machine while checking, and I have just recently been receiving the leak_id1234567890”, for example a couple of some seconds or minutes before you, then we have what we could call a duplicated leak_id.

Question now becomes, … was that “1234567890” check yours, or was it mine?

Since we’re both working with the exact same “leak_id” as the unique identifier, it causes issues like the one you see.

The script is simply loading bash.ws results for you, that were actually my results, and vice versa.

1 Like

Interesting theory! The script was adapted from the original made by the creator of the website, here: dnsleaktest/dnsleaktest.py at master · macvk/dnsleaktest · GitHub

The odds of getting the same ID within a certain timeframe would be low unless a lot of people use the endpoint. Only the owner could tell. I will open an issue on GitHub, they could easily make their endpoint give us a number rather than generate a number clientside to avoid any potential collision.

With that said, what makes me skeptical is the fact that I’m still getting Cloudflare as well as part of my DNS servers, meaning I would be pinging 1.1234567890.bash.ws before someone else and then 2.1234567790.bash.ws after that same someone else. Now, odds of that are almost non-existent I’d say?

As a temporary workaround, I noticed the website actually supports greater numbers.

Before:

leak_id = randint(1000000, 9999999)

After:

leak_id = randint(100000000, 999999999)

Collisions should be non-existent now. I will report back if I do get a potential leak again in the future.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.