Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
DNS Toys (dns.toys)
946 points by edent on June 11, 2022 | hide | past | favorite | 104 comments


“Why? For fun.”

I love this. It doesn’t need a reason to exist. It’s interesting on its own.

That being said, can anyone think of additional interesting reasons for why this would be useful rather than the same toys over HTTP?


Simplicity / latency / efficiency - DNS typically just fires off one UDP packet (generally one IP packet & ethernet frame too) and then gets one back (hopefully) and it's done. HTTP requires the TCP 3-way connection handshake, then the out & back roundtrip for request/response, then the 4-way teardown handshake. If it's HTTPS you also need the 4-way TLS <= 1.2 handshake and close notification alert. Although QUIC or TLS 1.3 improves that a bit.

Anyway if you're using a 14.4 modem in a rusty bunker at the bottom of the sea you'll notice a substantial improvement :)


This.

I measured the difference using `tcpdump`, and this was my conclusion:

> A big advantage of using DNS queries instead of HTTP queries is bandwidth: querying ns-aws.sslip.io requires a mere 592 bytes spread over 2 packets; Querying https://icanhazip.com/ requires 8692 bytes spread out over 34 packets—over 14 times as much! Admittedly bandwidth usage is a bigger concern for the one hosting the service than the one using the service.

(I had set up a service to determine your IP address via DNS, i.e. `dig @ns.sslip.io txt ip.sslip.io +short`, and measured why it was (marginally) better than using HTTP)


To be fair in the comparison; you can also query (via curl) icanhazip.com via HTTP instead of HTTPS, and it is only 5 packets and 385 bytes.


Good catch!


A couple decades ago I did SSH over DNS at the request of a client. It was pretty fun, worked surprisingly well. At the time, exactly zero firewalls stopped it.


I used to use iodine, a tunneling server which uses DNS as the transport, which would work even through captive portals at the time.

https://github.com/yarrick/iodine


ooh, MOSH over DNS. Theres all kinds of features to compensate for UDP lossiness built in.


Most tunnel protocols are UDP these days, vxlan, geneve, wireguard etc... Just because it doesn't guarantee delivery, meaning you don't get the retransmit amplification you'd get with TCP over TCP.


Why do you need to know the time in Paris while you're relaxing in a bunker at the bottom of the ocean? I know remote work is a thing now, but sheesh, some people just don't know how to disconnect ;)


> Although QUIC or TLS 1.3 improves that a bit.

On a TLS1.3 QUIC connection with a session supporting 0-rtt would DNS still require less round trips?


But you generally don't wanna keep a "connection" open to everyone in every scenario, like the one in the post.


You don't need a connection, you just need to have a session cached that you can resume. That's how 0-RTT works.


Well it depends very strongly on what you're doing. Looking at these packet sizes, on a 14.4 modem I'd expect the extra traffic to take about a second. But also you're waiting 10-20 seconds for HN to load or minutes for your average web page to load.


I came across "open" WiFis that required another form of login inside that filtered all HTTP traffic but let through DNS. But no, it's not really useful outside of special circumstances.


I have WireGuard endpoints of UDP 53, 443 and a high random port - at least one of them tends to work (although not always — one hotel recently only allowed tcp/80 and tcp/443


> one hotel recently only allowed tcp/80 and tcp/443

How did DNS resolution work? Do they force you to use their proxy server?


They could set up a recursive dnsmasq on the router, and block udp/53 traffic to the outside world.


This may work on pay to use Wi-Fi. There was a previous interesting post here about tunneling through DNS on airplane or other pay to use Wi-Fi.

https://news.ycombinator.com/item?id=511908


I have used this trick when I in high school grade.

Just setup openvpn with port 53 UDP with cheap vps, then connect it, and get unlimited internet access

Internet connection in my country is very limited and expensive in that day


You have no idea how badly I was looking for a way to tunnel via airplane wifi. Even going as far as trying to use the "free tier" fb messenger access to move packets. Now the ToS have a very low bandwidth limit on the free tier (eg. 100mb), so I'm not sure if it'd work for any real application.

I never thought to use DNS as a tunnel, but I have seen some pretty interesting loopholes that I was trying to find. Some airline's captive portal used to rely on some google service (captcha probs), and for a period of time didn't block any google-owned IP address that wasn't a consumer website (eg search, yt) so GCP and developer docs would load if you had the URL. I couldn't reliably get to user-generated content through it though.


> I never thought to use DNS as a tunnel

Most firewalls drop or hijack packets on port 53.


I have experienced this, i.e., hijacking, but I would respectfullly contest the term "most". But perhaps the statement was only referring to airports. I could be wrong but I like to think it is a minority of networks that hijack or block DNS. For example, a minority of consumer ISPs, other networks controlled by third parties (airports, hotels, etc.) or countries that conduct extremely aggressive internet censorship.


I can see the IP echo command be useful to verify if DNS traffic is routed differently than other traffic on a corporate network. Assuming outbound port 53 is not blocked completely on the network that is.


My default is the other way around, I'll question why something that is not a web page uses HTTP as an application-layer protocol when better fitted alternatives usually exist.

Add a bonus withering stare for assuming JSON is the only data serialization/interchange format.


maybe on a wifi network before authentication when it may allow DNS resolution but not HTTP requests?


Could you shuttle more data through this method to have a browser that works on unauthenticated captive portal wifi networks?


It's called dns tunnelling.

https://github.com/yarrick/iodine


looks like this can be used to get free wifi on airplane


> During the last decade, several types of software and malware used the DNS protocol for data exchange.

https://resources.infosecinstitute.com/topic/bypassing-secur...


That doesn’t mean the protocol isn’t useful for other purposes. Part of why it’s useful for the malware writers is that it’s highly available and often ignored by firewall rules.

That availability can also be used for good.


I can see using this on an isolated network of iot-like devices that don't quite have the guts or spare bandwidth for HTTPS. MQTT over DNS?


Maybe less likely to be blocked by some firewall policy?


"Prior art" for this is DNS block lists (DNSBLs).

Typically these are used like this: your mail server gets an SMTP connection from some address (let's use the familiar IPv4 example): 10.20.30.40.

You reverse these octets and do an "A" record dns query to some 40.30.10.10.dnsbl.example.com to look up that IP in example.com's list. If a match is returned, the address is listed. If you do a "TXT" record query, you can find out why it's listed.

Block lists are typically blacklists, but they can be whitelists as well.

DNSBL's are hammered with queries from vast numbers of mail servers; DNS keeps things efficient.


What is the difference between a block list and a black list? Is there a similar distinction between white list and allow list?


Fun tool! I use `pi.neomantra.net` for unit testing:

  > dig pi.neomantra.net +short
  3.141.59.26
  
  > dig pi.neomantra.net +short  -t AAAA
  3141:5926:5358:9793:2384:6264:3383:2795

Just added pi support to it: https://github.com/knadh/dns.toys/pull/9


Remember the bert.secret-wg.org RPN calculator via DNS from the old days. It's still going.

Recursive

   DNSCACHEIP=185.49.141.200 dnstxt 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org 
   dq txt 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org 
   drill 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org txt
   kdig 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org txt
   dig 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org txt
Non-recursive

   dnsq txt 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org 185.49.141.200  
   dq -a txt 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org 185.49.141.200
   drill -ord 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org @185.49.141.200 txt 
   kdig +nord 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org @185.49.141.200 txt
   dig +nord 4.9.+.3.+.7.+.7.+.7.+.5.+.rp.secret-wg.org @185.49.141.200 txt
Two different TXT RRs will be returned. The second one is new as of last year.

Read more at https://bert.secret-wg.org/Tools/index.html


In case anyone else is as unfamiliar as I was with the commands here: https://en.wikipedia.org/wiki/Dig_(command)



I guess you could deliver web pages over DNS too, if you wanted... though I'm not sure why you'd want to.

Instead of DoH it would be HoD.


You can also use iodine (https://github.com/yarrick/iodine/) to tunnel IPv4 data through DNS (useful e.g. when on a captive portal network that doesn't block DNS requests). Performance isn't great obviously, but the concept is fascinating nonetheless.


So you could tunnel ipv4 through DNS, and serve HTML via DNS, and use DNS over HTTPS?


It’s not DNS. There’s no way it’s DNS. It was DNS.


Example and more conversation on that here: https://news.ycombinator.com/item?id=28218406


I experimented with this over 10 years ago. I used a modified dnstxt from djbdns and put MIME headers and HTML into TXT RRs. tinydns allows a wider variety of bytes in RRs than other DNS software. At least, it was generally less restrictive than the other DNS software available at that time.


Awesome idea and already with the requests lol: Would it be possible to add the resource records as subdomain of dns.toys?

Eg.

dig newyork.time.dns.toys with a low ttl?

This way folks operating in an environment where they can't egress on port 53 can still use the tools?


Picky overcorrect comment: Try

    dig +short
instead of

    dig +noall +answer +additional
i.e.

    dig +short mumbai.time @dns.toys
gives you the short and breve answer you probably expect :-)


Not quite, some queries have multiple records and multiple response fields, so it's necessary to do:

  dig +short london.time @dns.toys |head -n 1 |cut -d '"' -f4
In order to get clean time for a city, for example. At which point you'd be better learning the arguments to local tools. But anyway, cute hack and cool mountain-name. :)


You wouldn't use London.time in your query in a script though, because it returns multiple answers. You'd use London/gb or London/ca.time

And furthermore, +short gives you the same multiple answers that +noall +answer +additional does, without the extra dns stuff that you don't need.


Awesome! Surprised to see the resolver correctly handle my typo:

$ dig seat2222tle.time @dns.toys +short "Seattle (America/Los_Angeles, US)" "Sat, 11 Jun 2022 08:22:42 -0700"


It is probably levenshtein distance


probably just removing numbers etc

dig seattlr.time @dns.toys +short


Interesting find on this site: The Norwegian Meteorological Institute has a free weather API

https://developer.yr.no/featured-products/forecast/


As does the National Weather Service: https://www.weather.gov/documentation/services-web-api


Hey cool somebody has reimplemented finger!


This is a fun tool, but it has some assumptions around IPv4.

It appears to work by responding with TXT records when given a query for A records. I have a `.digrc` file setup to query for AAAA records by default (since I mostly deal with IPv6 only networks). So I have to set the query for either A or TXT. Unfortunately, AAAA doesn't get the special treatment that A gets.


To others, yr.no is a free weather service with API: https://developer.yr.no

I see that dns.toys use it.


Out of curiosity, I looked at the headers after clicking on your link and I found that it was sending Referrer as: https://news.ycombinator.com which is not an issue. But then I refreshed the page and saw the same Referrer again. So I checked where it was getting the Referrer from and it was not storing anything in localStorage, not in URL, nor in sessionStorage, nor in cookies. Any idea where the site was getting the Referrer from?


Referer [sic] is determined by your browser, not the site. If you just refreshed the tab then its probably looking at the history.

Also, no browser that wants to make any claim of caring about privacy should still be sending cross-domain Referer headers by default which is yet another reason why Mozilla's privacy marketing is just that: marketing without substance.


sic is used to highlight that a spelling or grammar mistake in your writing is part of a direct quote being provided unaltered, and not your own mistake. It isn't used to provide corrections. Anyway, both spellings are fine in various regions.


Got it. So it gets the Referer from the browser history?


Your browser remembers and replays it. localStorage/sessionStorage/cookies aren't available to parse by the time request headers are sent.

You'll notice this behavior goes away if you select the URL bar and hit enter (as if you were navigating to the site manually).


Yeah you're right. Selecting the URL and hitting enter did clear the Referer. One comment says the browser identifies the Referer by looking at the history is that so?


They also have nice graphs on their website. Been using yr.no as my primary site for weather info for years now.


Really pleasing - though the most surprising thing was learning a forward slash is a valid character in a domain name. Are there any real world examples?


Domain names can't have slashes. But I think the DNS protocol just works with binary strings that are up to 255 bytes long (or was it 256?). So I guess most CLI DNS tools don't care if it is a valid domain name.


RFC 2317 (BCP 20) says to use it, but in my experience, everyone implementing this scheme uses a dash instead of a slash.


Ha, no one has pointed out who the author is yet - a CTO of one of India's recent unicorns.


Shameless plug:

Since I was in the process of implementing plugins for kittendns (https://github.com/fusion/kittendns), I felt I should at least implement the timezone toy as proof of concept. This forced me to implement 'fetch' in the javascript plugin so, I guess, everyone wins :)


I love it!

I am not a DNS expert, but if one format for DNS queries is <x>.<y>, i.e., "mumbai.time", "berlin.weather" as seems to be the case -- then I think it would be interesting to see if a general-purpose query in this format -- could be passed along to a search engine, then get the result back from that, strip the HTML, and pass the resulting text back in the answer section...

Why?

Well, it could have emergency preparedness applications -- imagine that for whatever reason, all computers complex enough to run modern web browsers suddenly stopped working -- and all that still works are dumb terminals and mostly text-based computers from the 1980's...

In that scenario (and we hope it never happens!) -- it would be awesome, truly awesome, to have a way to still be able to query search engines and possibly other Internet services -- if most of the other infrastructure is no longer working.

It might also be possible to implement some type of rudimentary email system over this, as well...

Anyway, I think what you've done is absolutely brilliant!


This is awesome but I'm getting NXDOMAIN when I try to use it. Am I doing something wrong, perhaps something to do with EDNS?

    $ dig 42km-mi.unit @dns.toys 

    ; <<>> DiG 9.16.27-Debian <<>> @dns.toys 42km-mi.unit
    ; (1 server found)
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 2059
    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ; COOKIE: efe3c6f9e0b6e4da56aba44d62a4e63ba7a19bed262b0e1a (good)
    ;; QUESTION SECTION:
    ;42km-mi.unit.   IN A

    ;; AUTHORITY SECTION:
    .   6959 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2022061100 1800 900 604800 86400

    ;; Query time: 44 msec
    ;; SERVER: 138.197.68.199#53(138.197.68.199)
    ;; WHEN: Sat Jun 11 14:00:11 CDT 2022
    ;; MSG SIZE  rcvd: 144


You should ask for a TXT record, not an A record.


I think it would work to use "time" etc as subdomains instead of TLD to be able to use any DNS server for the query.


Then you'd be at the mercy of caching in whatever recursive resolver is in between you and dns.toys. Sure, you can specify the TTL but if you give one to low many resolvers will ignore it and just make up their own.


But they'd still need a domain for those, and you'd still have to enter it.


For years now I have published DNS TXT records for my domain that include my twitter handle, email address, and a Google Voice number. I always thought it would be a fun "protocol" for people to adopt, but never knew how to advance it.

  dig TXT trevormanternach.com


That was the intention behind the .tel TLD: https://en.wikipedia.org/wiki/.tel


Fun :). It would be interesting to see how accurate one could get the time records (I see a TTL of 1 second, but what if the algorithm for reporting the time could try to measure latency between DNS client and itself and . . . yadda yadda yadda). Wish we had more submissions like this one.


The TTL doesn't really matter in this case because you query the dns.toys DNS server directly, rather than going through a remote recursive resolver (which would normally cache any results it gets based on the TTL).


Will a local stub resolver respect the TTL, or are queries to authoritative name servers never cached? I know something like dnsproxy would care about the TTL, but not sure about, say, systemd-resolved. But good point nonetheless.


Rule 53: if you can think of it, someone's done it in the DNS.


Isn’t this sort of a continuation/improvement on the ancient single-purpose protocols and commands like `finger` or `ident` etc. but consolidated into a single port/command?

Maybe we could formalize this into a new protocol? Send some text, get some text back, with minimal overhead. Let’s call it “ask” or “q” (for query)


Neat! For unit conversions there is an older tool called 'unit' which can convert nearly anything.



I used the BSD version of this (which seems the same AFAICT) a few times years ago and managed to misunderstand the output a few times and gave up. I doubt it was an actual error in the conversion but the UI is comically bad. The typical search engine UI is great, ask for a conversion using whatever abbreviations you want and it gives you a detailed explanation of what it thinks you asked for and the result (and not some other number you didn't ask for). I see GNU units at least has a -1 option to just give the result.

Firefox has a hidden simple unit conversion tool that can be enabled by setting browser.urlbar.unitConversion.enabled to true. It only has a few conversions, though, and doesn't give much detail about what it thinks you asked for.

It looks like there is a rust unit conversion utility called rink that seems better although, like many rust utilities, it lacks a man page or any local documentation besides a brief --help message (there is an online manual). Some units are a bit annoying; you can't just do c to f, only degC to degF (and not even degc to degf either). But much nicer than units and can also be easily be used as an interactive calculator.

https://rinkcalc.app/

Edit: Playing around with rink a bit more it has some neat stuff. It gives info if you enter a unit (or constant or substance), usually defined in terms of the base unit of each type but if you give the base unit it has a brief text explaining how the base unit is defined. "c to f" not working is because it doesn't use context and c is the speed of light. You can use 'units for' to see available units for a particular type, although it doesn't look like you can show all available units other than checking the source (based on the GNU units definitions but with some differences, such as degC). It suggests a supported unit if you type one it doesn't understand.


I did, now too late to edit


Fun fact: units can do math too! Try it:

    units -t '12 * 45 * 11'
This can be combined with unit conversion of course:

    units -t '(8 lbf) / (9.8 m/s^2)' slug
Be careful using it for temperature conversion. You need to use tempC and tempF functions, not degC and degF units, because of the linear offset from absolute zero.

Correct way (absolute temperature):

    units -t 'tempF(71)' tempC
Incorrect way (temperature difference):

    units -t '71 degF' degC

I use units a ton, so I have the following in my .zshrc:

    # in-terminal calculator: e.g. `calc 60 * 60 * 4`
    _calc () {
        units -t "$*"
    }
    alias calc='noglob _calc'

    # units convenience, use ( and * without quoting
    alias u='noglob units -t'


Interesting if "normal" (unrestricted) Internet connection. Fails if using a VPN solution (PIA and Mullvad, so far) - probably because they trap name resolution attempts, if forcing using their own.


Nice. like a command-line version of Charlie Cheever's bunny1. https://github.com/ccheever/bunny1


This is great. It's especially useful if you're already in a terminal. No special tools needed.


I was expecting a collection of DNS utilities, but this is much more fun!


Does this configured to handle DNS amplification attack our of the box?


the one where you can get the weather reminds me of graph.no, a service where you can retrieve the weather using the Finger Protocol.

e.g.

   finger new_york@graph.no


ELIFreshman, please


DNS servers _usually_ reply with information about a queried domain name or a host name. dig is a command-line tool that queries a given name server (or a preset one) for that information. For example `dig news.ycombinator.com` returns the IP address of HN, and `dig news.ycombinator.com @example.com` queries the example.com nameserver for that domain.

dns.toys runs a DNS server that dynamically returns answers such as times, currency information, etc (instead of domain name information) if you format your query right.

So for example, `dig mumbai.time @dns.toys` returns the time in Mumbai in a DNS TXT record instead of an IP address (or an NXDOMAIN response, saying the domain does not exists).

Play around with the `dig` command, it is an intuitive tool that you will eventually use if you are a CS or a related Freshman.


this is insane cool. it's such an amazing creative idea. i hope people like them never stop having awesome ideas


really cool. wonder if it does any checks to ensure packet response stays within 512 bytes to avoid packet frags.


dig -6 aaaa ip @dns.toys doesn't work.


nice, some stuff for me to try on a plane


Love it!


brilliant!


Copy and run the below commands to try it out.

I can't make it work from the explorer bar, powershell prompt, dos shell.

Bye.


Have you tried nslookup?


dig is a unix utility, you'll have to download a windows version somewhere if you want to try it. He should have warned people I guess. Also I think currently it got the HN hug of death as it doesn't work in linux either :)




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: