I saw a thread about how to do DNS query via different server in PHP because OpenDNS always resolve all domains even they should result NXDOMAN. I don’t know how to do that in PHP, but I am sure there is some libraries already for such task as same in Python, such as PyDNS or dnspython.

The website of PyDNS isn’t very helpful, there is no sample code as I didn’t see any, but README is well enough to get started. I wrote a quick after I learned a bit of PyDNS, it was hard to use as you can see as the following sample code:

# -*- coding: utf-8 -*-
import DNS

print 'PyDNS %s' % DNS.__version__

DNS.DiscoverNameServers()
print 'NS: %s' % DNS.defaults['server']

DN = 'example.com'
IDN = u'παράδειγμα.δοκιμή'
NXDN = 'foobar.example.com'

def q(name, qtype):

  print '%4s Query on %s -> %s' % (qtype, name.encode('utf-8'), DNS.dnslookup(name, qtype))

q('google.com', 'A')
q('google.com', 'AAAA')
q(DN, 'A')
q(DN, 'AAAA')
q(IDN, 'A')
q(IDN, 'AAAA')

# Catching error
try:
  q(NXDN, 'A')
except DNS.ServerError as e:
  if e.rcode == 3:
    print 'Cannot resolve %s' % NXDN.encode('utf-8')
  else:
    raise e

# Again, but let it raise
q(NXDN, 'A')
PyDNS 2.3.6
NS: ['168.95.192.1', '168.95.1.1']
   A Query on google.com -> ['72.14.203.102', '72.14.203.113', '72.14.203.138', '72.14.203.139', '72.14.203.100', '72.14.203.101']
AAAA Query on google.com -> []
   A Query on example.com -> ['192.0.43.10']
AAAA Query on example.com -> [' \x01\x05\x00\x00\x88\x02\x00\x00\x00\x00\x00\x00\x00\x00\x10']
   A Query on παράδειγμα.δοκιμή -> ['199.7.85.13']
AAAA Query on παράδειγμα.δοκιμή -> ['& \x00\x00(0\x020\x00\x00\x00\x00\x00\x00\x00\x10']
Cannot resolve foobar.example.com
Traceback (most recent call last):
  File "<stdin>", line 34, in <module>
  File "<stdin>", line 15, in q
  File "/home/livibetter/lib/python2.5/DNS/lazy.py", line 37, in dnslookup
    result.header['rcode'])
DNS.Base.ServerError: ('DNS query status: NXDOMAIN', 3)

You can use DNS.DiscoverNameServers() for system’s name servers for querying.

On my system, none of any packages were built with IDN (nor IPv6) support. But since you can do a manual query, querying IDN isn’t a problem and changing the default DNS isn’t very hard:

# -*- coding: utf-8 -*-
import DNS

DNS.DiscoverNameServers()
print 'NS: %s' % DNS.defaults['server']

NXDN = 'foobar.example.com'

def q(name, qtype):

  try:
    print '%4s Query on %s -> %s' % (qtype, name.encode('utf-8'), DNS.dnslookup(name, qtype))
  except DNS.ServerError as e:
    if e.rcode == 3:
      print 'Cannot resolve %s' % name.encode('utf-8')
    else:
      raise e

q(NXDN, 'A')

DNS.defaults['server'] = ['208.67.222.222', '208.67.220.220']
print 'NS changed to OpenDNS: %s' % DNS.defaults['server']

q(NXDN, 'A')
NS: ['168.95.192.1', '168.95.1.1']
Cannot resolve foobar.example.com
NS changed to OpenDNS: ['208.67.222.222', '208.67.220.220']
   A Query on foobar.example.com -> ['67.215.65.132']

More practical method should generate a request object and query through it, check out dnslookup function in lazy.py to see how you can do it more comprehensive.