DNS Looking Glass
Python Shell Go Other
Switch branches/tags
Nothing to show
Failed to load latest commit information.



This software is a "DNS looking glass". The DNS (Domain Name System)
is the distributed database used to retrieve data (typically IP
addresses) from domain
names. <http://en.wikipedia.org/wiki/Domain_Name_System>

A "looking glass", among Internet engineers, typically refers to a
server on one network which serves information seen from this network
(two points of the Internet may see different things, that's why
looking glasses are important). Their main use, today, is to see BGP
<http://en.wikipedia.org/wiki/Border_Gateway_Protocol> routes from
another point of view
<http://en.wikipedia.org/wiki/Looking_Glass_servers>. But it is time
to extend them to the DNS.

The "DNS looking glass" allows you to get DNS data from another
server. This is useful to check site-dependent behavior. Among the
many reasons why the DNS data can be different in various places:
* cache poisoning, for instance by a Kaminsky attack 
* DNSSEC validation enabled at some places but not others,
* network problems making name servers unreachable from some places,
* caching effects (data in the cache at some places but not others),
* censorship making some names such as thepiratebay.org or
  wikileaks.org unavailable in some sites.


A simple, permissive, free software license, known as 2-clause BSD
license (or simplified BSD license; it is equivalent to the ISC
license). See LICENSE for the full text.


We assume that someone installed the software. If you install it
yourself, see the next section.

The major usage of this program is through REST requests
<http://en.wikipedia.org/wiki/Representational_state_transfer> (if you
do not know REST, do not worry; basically, it means we use ordinary
HTTP requests). If the program is installed at
<http://dns.example.net/>, the URL for the requests will be
<http://dns.example.net/$DOMAIN[/$TYPE][/$CLASS]> where DOMAIN is the
domain name and TYPE a DNS record type (such as AAAA or MX).

More formally, following the language of URI Templates (RFC 6570), the
URLs of this service are

There is a non-standard pseudo-querytype ADDR to request both A and
AAAA, specially for the links in the HTML output.

The default output format is determined by HTTP content negotiation,
so it depends on your client. You can use this program from an
ordinary Web browser, which will typically get HTML by default. With a
command-line client like curl, you can add the relevant header to get
the format you want;

curl -v -H 'Accept: application/json' $URLBASE/org/SOA

If content negotiation does not suit you, you can add in the URL the
option format=FORMAT where FORMAT is XML, HTML, TEXT, ZONE or JSON
(see next section). So, for instance, to get the IPv6 address of
www.example.com in XML, it will be

You can add an option to select the name server to query (the default
one is chosen by the server, typically the default resolver(s) of the
machine). server=IP-ADDRESS (names are *not* supported)

To activate DNSSEC in the responses (to send the DO bit), use option
dodnssec=1 in the URL. This option will allow you (if the resolver
supports it) to see the AD (Authentic Data) flag.

To disable DNSSEC validation (if the resolver does it and you don't
want it), use option cd=1 (cd = Checking Disabled)

To use TCP (instead of UDP) for the request, use option tcp=1 in the

By default, the server queries the name servers with EDNS0 and a
buffer size of 4096 bytes. To change that, use the option buffersize
with the value you want. Setting it to 0 will disable EDNS.

For finding a domain name from an IP address, you can do requests with
the arpa domain name, for instance
<http://dns.example.net/> but you can also
use the option reverse to ask for the address to be turned into an
arpa domain name, for instance

There is a rate-limiter so, if you receive HTTP status code 429, it
means you have been too aggressive.

Format-specific things

The XML option follows partially the format of Internet-Draft
draft-mohan-dns-query-xml for the outer elements (plus some
extensions) and of draft-daley-dns-schema for the resource data. Note
that the query format does *not* follow the first draft's syntax.

The JSON option's format is documented in the file JSON.txt.

The HTML option's format is not documented. To style the output, a
sample CSS file is included in dnslg.css.

The Text option's format is not documented. It is intended for human
reading. If you need a structured format, use XML or JSON. If you
prefer text-based formats, for instance for processing with common
Unix CLI tools (awk, grep, etc), the best one is probably the Zone

The Zone option's format follows section 5 of RFC 1035, with tabs as

Using it from a program

Of course, an important reason to have a structured output format is
to use it from a program. See the directory usages/ for sample
programs which query the DNS looking glass.


Requires Python, then SimpleTAL, dnspython, webob and netaddr. If you
want to use the database of existing looking glasses, you will also
need the yaml module.
Debian/Ubuntu: packages "python-netaddr python-dnspython python-webob python-simpletal python-yaml"


python setup.py build
$SUDO-OR-SIMILAR python setup.py install

Then you have to configure a HTTP server to run this WSGI
script. Some configuration data can be sent by environment
variables. For instance, if you use Google Webmasters and have the
code (the cookie) "google1234baddcaf5678", *and* you want the program
to serve the file itself (it is not mandatory), then you need to
define the environment variable DNSLG_GOOGLE_WEBMASTERS_CODE to this

For Apache, this is typically something like:

<VirtualHost *:80>
    ServerName dns.example.net
    DocumentRoot "/var/www/dns.example.net/root"

    <Directory "/var/www/dns.example.net/scripts">
        Options -Indexes FollowSymLinks +ExecCGI
        SetHandler wsgi-script
        Order allow,deny
        Allow from all
    WSGIScriptAlias / /var/www/dns.example.net/scripts/dnslg.py
    WSGIDaemonProcess dns.example.net processes=5 threads=10 display-name=%{GROUP}
    WSGIProcessGroup dns.example.net

where dnslg.py is copied and adapted from sample-wsgi-dnslg.py or

The starters with a configuration file use the INI format. Use
sample-config-file.ini as an example.

There are many other possibilities, either with Apache or with another
HTTP server with WSGI support. Browse the Web!

The official source is at Github
<https://github.com/bortzmeyer/dns-lg>. The best place to report bugs,
submit patches and give opinions is through the Github issue tracker.


To try it locally;
% python test-server.py
Then, from another window:
% curl http://localhost:8080/example.org/A

Other DNS looking glasses

http://live.icmynet.com/icmynet-dns/ No API, Web only

http://www.zonecut.net/dns/index.cgi No API, Web only

http://www.whatsmydns.net/ REST URLs but no API

See also a more up-to-date list at the end of

Other code for DNS looking glasses

* <http://dns-lg.sidnlabs.nl/index.html> written in Go


Written by Stephane Bortzmeyer <bortzmeyer+dnslg@nic.fr>. (To report
bugs and submit patches, I suggest that you use the Github issue
tracker instead of email.)

Favicon <http://www.favicon.cc/?action=icon&file_id=513990>, 
by Philippe Regnauld <http://www.favicon.cc/?action=icon_list&user_id=155740>

Implementation details