Library for specifying a name server and dig with python

Trigger

There was a task to check that multiple records in multiple zones matched for each name server, and there were so many, so I scripted it with python.

At that time, I wondered if there was something good about a library that digs with NS specification in python, but as of early 202006, I could not find a page with useful information, so I will write it down here. thought.

I think python was faster to write in a shell script if I wanted to do it easily because I'm just studying python.

environment

To check the operation when writing this article, Installed on Windows10 / WSL / Ubuntu-18.04

# pyenv --version
pyenv 1.2.17-2-ga8ca63fc

# pipenv --version
pipenv, version 2018.11.26

# python --version
Python 3.8.2

I have confirmed it at.

Apart from the above, it is also implemented in the same version pyenv / pipenv / python on CentOS8.

When checking with the dig command

A sample of what I wanted to try.

# dig blog.watarinohibi.tokyo @8.8.8.8

;; ANSWER SECTION:
blog.watarinohibi.tokyo. 19     IN      A       157.230.43.191

# dig blog.watarinohibi.tokyo @dns1.p06.nsone.net 

;; ANSWER SECTION:
blog.watarinohibi.tokyo. 20     IN      A       157.230.45.115

dns1.p06.nsone.net is Netlify's NS server The URL you are searching for is your blog site deployed on Netlify The above is an example, and it was actually performed for A record, SOA record, TXT record, MX record, etc. that return one specific record.

Library that seems to be usable

socket

https://docs.python.org/ja/3/library/socket.html#socket.gethostbyname

socket.gethostbyname_ex(hostname) Obtains various IPv4 format address information from the host name. The return value is a tuple of (hostname, aliaslist, ipaddrlist), hostname is the official name of the host specified by ip_address, aliaslist is a list of aliases for the same address (which can be empty), and ipaddrlist is for the same interface on the same host. Shows a list of IPv4 addresses (mostly just a single address).

How to use

test1.py


#!/usr/bin/env python3
import socket

domain = 'blog.watarinohibi.tokyo'
ns1 = '8.8.8.8' # google DNS
ns2 = 'dns1.p06.nsone.net' # Netlify DNS

# socket
print ("=== socket.getaddinfo")
addrs = socket.getaddrinfo(domain, 80)
for addr in addrs:
    print(addr)

print ("=== socket.gethostbyname")
addrs = socket.gethostbyname(domain)
print (addrs)
 # ./test.py
=== socket.getaddinfo
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('157.230.45.115', 80))
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('157.230.45.115', 80))
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_RAW: 3>, 0, '', ('157.230.45.115', 80))
(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('2400:6180:0:d1::575:a001', 80, 0, 0))
(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('2400:6180:0:d1::575:a001', 80, 0, 0))
(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_RAW: 3>, 0, '', ('2400:6180:0:d1::575:a001', 80, 0, 0))
=== socket.gethostbyname
157.230.45.115

There is no option to specify NS (probably not overlooked). Not suitable for this use, but if you want to try name resolution with the standard library, this is fine.

dnspython

http://www.dnspython.org/ https://github.com/rthalley/dnspython https://pypi.org/project/dnspython/

How to use

http://www.dnspython.org/examples.html  Please refer to the area. This time, I want to try lookup of A record by specifying NS.

test.py


import dns.resolver

print ("=== dns.resolver @", ns1)
resolver = dns.resolver.Resolver()
resolver.nameservers = [ns1]
answers = resolver.query(domain, 'A')
for rdata in answers:
    print (rdata)

print ("=== dns.resolver @", ns2)
resolver = dns.resolver.Resolver()
resolver.nameservers = [ns2]
answers = resolver.query(domain, 'A')
for rdata in answers:
    print (rdata)
 # ./test.py
=== dns.resolver @ 8.8.8.8
134.209.106.40
=== dns.resolver @ dns1.p06.nsone.net
Traceback (most recent call last):
  ~~~ stack trace

With that feeling, it worked with NS specification with IPv4 address, but an error occurred with NS specification with CNAME record such as Netlify DNS. https://github.com/rthalley/dnspython/issues/235 There is an exchange that seems to be this error, but it seems that it is not supported because it is not in RFC. However, I don't really understand here because there is an image that NS records are used in CNAME at all. ..

pynslookup

https://github.com/wesinator/pynslookup https://pypi.org/project/nslookup/

How to use

test.py


from nslookup import Nslookup

print ("=== nslookup @", ns1)
dns_query = Nslookup(dns_servers=[ns1])
ips_record = dns_query.dns_lookup(domain)
print(ips_record.response_full, ips_record.answer)

print ("=== nslookup @", ns2)
dns_query = Nslookup(dns_servers=[ns2])
ips_record = dns_query.dns_lookup(domain)
print(ips_record.response_full, ips_record.answer)
 # ./test.py
=== nslookup @ 8.8.8.8
['blog.watarinohibi.tokyo. 19 IN A 178.128.17.49'] ['178.128.17.49']
=== nslookup @ dns1.p06.nsone.net
Traceback (most recent call last):
~~~ stack trace

That's why this is also an error. When I checked the code, https://github.com/wesinator/pynslookup/blob/master/nslookup/nslookup.py

nslookup.py


import dns.resolver, dns.exception

It seems that dnspython is used as it is internally.

pydig

https://github.com/leonsmith/pydig https://pypi.org/project/pydig/

How to use

test.py


import pydig

print ("=== nslookup @", ns1)
resolver = pydig.Resolver(
    nameservers = [ns1]
)
answer = resolver.query(domain, 'A')
print (answer)

print ("=== nslookup @", ns2)
resolver = pydig.Resolver(
    nameservers = [ns2]
)
answer = resolver.query(domain, 'A')
print (answer)
 # ./test.py
=== nslookup @ 8.8.8.8
['157.230.35.153']
=== nslookup @ dns1.p06.nsone.net
['206.189.89.118']

Oh, it worked. This guy seems to work even with the NS designation of CNAME. If you check the code, https://github.com/leonsmith/pydig/blob/master/pydig/resolver.py

import subprocess
--
Builds up the final arguments to pass into subprocess

Was written, and the local dig was just running in subprocess. I see. If the dig path is different or you want to specify it, you can specify it as an option.

>>> resolver = pydig.Resolver(
...     executable='/usr/bin/dig',
...     nameservers=[
...         '1.1.1.1',
...         '1.0.0.1',
...     ],
...     additional_args=[
...         '+time=10',
...     ]
... )

Conclusion

If you want to use dig with NS specified in Python, you can use pydig which is a wrapper of the dig command, but it seems that it is just a wrapper, so you may write it by yourself in subprocess. unknown.

DNS is messy.

Recommended Posts

Library for specifying a name server and dig with python
Installation procedure for Python and Ansible with a specific version
A sample for drawing points with PIL (Python Imaging Library).
Create a striped illusion with gamma correction for Python3 and openCV3
A memo with Python2.7 and Python3 on CentOS
Try HTML scraping with a Python library
Rock-paper-scissors with Python Let's run on a Windows local server for beginners
Build a lightweight server in Python and listen for Scratch 2 HTTP extensions
Causal reasoning and causal search with Python (for beginners)
Get a ticket for a theme park with python
Building a python environment with virtualenv and direnv
Create a LINE BOT with Minette for Python
Procedure for creating a LineBot made with Python
Start a simple Python web server with Docker
Get git branch name and tag name with python
Commands for creating a python3 environment with virtualenv
Until you install Python with pythonbrew and run Flask on a WSGI server
[Python] How to create a local web server environment with SimpleHTTPServer and CGIHTTPServer
Local server with python
Building a Docker working environment for R and Python
Build a python virtual environment with virtualenv and virtualenvwrapper
Benchmark for C, Java and Python with prime factorization
Build a python environment for each directory with pyenv-virtualenv
Let's make a simple game with Python 3 and iPhone
A server that echoes data POSTed with flask / python
Build a python virtual environment with virtualenv and virtualenvwrapper
Create a Layer for AWS Lambda Python with Docker
[Python] Delete by specifying a tag with Beautiful Soup
Create a fake Minecraft server in Python with Quarry
Create a company name extractor with python using JCLdic
[Vagrant] Set up a simple API server with python
Build API server for checking the operation of front implementation with python3 and Flask
[Building a CI environment in 2 hours] Procedure for building a Python Web server with CircleCI and passing an HTTP communication test
Programming with Python and Tkinter
Encryption and decryption with Python
Create a decision tree from 0 with Python and understand it (3. Data analysis library Pandas edition)
screen and split screen with python and ssh login to remote server
Python and hardware-Using RS232C with Python-
Recommendations for django, wagtail ~ Why develop a website with python ~
Associate Python Enum with a function and make it Callable
Create a child account for connect with Stripe in Python
[Python] Create a date and time list for a specified period
Experiment to make a self-catering PDF for Kindle with Python
Let's create a PRML diagram with Python, Numpy and matplotlib.
Analyze stocks with python and look for favorable trading phases
Solving with Ruby, Perl, Java and Python AtCoder ATC 002 A
I made a server with Python socket and ssl and tried to access it from a browser
Create a Twitter BOT with the GoogleAppEngine SDK for Python
Build a Python environment and transfer data to the server
Make a fortune with Python
Package python runtime and pypi library with chef / omnibus and Docker
Hash with python and escape from a certain minister's egosa
<Python> Build a dedicated server for Jupyter Notebook data analysis
python with pyenv and venv
Simple HTTP Server for python
Get a list of CloudWatch Metrics and a correspondence table for Unit units with Python boto
Create a directory with python
[In-Database Python Analysis Tutorial with SQL Server 2017] Step 5: Training and saving a model using T-SQL
Turn an array of strings with a for statement (Python3)
Build a python environment on CentOS 7.7 for your home server
This and that for using Step Functions with CDK + Python