8 Commits

Author SHA1 Message Date
47dbc6afe3 Update installation notes to reflect recent changes 2017-05-02 14:18:52 +04:30
39e564e626 Use cymruwhois from pypi and remove submodule
- cymruwhois maintainer recovered his access to pypi and
  uploaded latest package. There is no need to use it as
  submodule anymore. So we added an external dependency.

- Refactor whois data caching in dnstraceroute and unbreak
  caching mechanism which was broken since previous commit
  due to a bug in time delta calculation.
2017-05-02 14:16:17 +04:30
3df692e6db No more needed 2017-04-30 21:18:45 +04:30
2dcf0e7b78 Fix setuptools 2017-04-30 21:12:08 +04:30
a0f9cae673 Fix setuptool installation and dependecies 2017-04-30 19:35:36 +04:30
51e3d252f2 Add color mode to dnseval ("-C" option) 2017-04-26 12:53:05 +04:30
7db7684c95 Fix display in case of no answer (fix #34) 2017-04-25 22:28:22 +04:30
bde3263cfa Use semantic versioning
and more standard constant names
2017-04-24 17:43:47 +04:30
9 changed files with 90 additions and 55 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "cymruwhois"]
path = cymruwhois
url = https://github.com/JustinAzoff/python-cymruwhois.git

View File

@ -1,2 +1 @@
include LICENSE README.md TODO.md public-servers.txt include LICENSE README.md TODO.md public-servers.txt
include cymruwhois/*.py

View File

@ -29,8 +29,6 @@ of view.
This script requires python3 as well as latest This script requires python3 as well as latest
[dnspython](http://www.dnspython.org/) and [dnspython](http://www.dnspython.org/) and
[cymruwhois](https://pythonhosted.org/cymruwhois/). [cymruwhois](https://pythonhosted.org/cymruwhois/).
All required third-party modules are included as GIT submodules. You just need
to run `git submodule update --init` and project directory to pull the required code.
# installation # installation
@ -43,13 +41,13 @@ There are several ways that you can use this toolset. However using the sourceco
``` ```
git clone https://github.com/farrokhi/dnsdiag.git git clone https://github.com/farrokhi/dnsdiag.git
cd dnsdiag cd dnsdiag
git submodule update --init pip3 install -r requirements.txt
``` ```
2. You can alternatively install the package using pip: 2. You can alternatively install the package using pip:
``` ```
pip3 install --process-dependency-links dnsdiag pip3 install dnsdiag
``` ```
## From Binary ## From Binary

Submodule cymruwhois deleted from a34543335c

View File

@ -38,15 +38,33 @@ from statistics import stdev
import dns.rdatatype import dns.rdatatype
import dns.resolver import dns.resolver
__VERSION__ = 1.6 __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__PROGNAME__ = os.path.basename(sys.argv[0]) __license__ = 'BSD'
__version__ = "1.6.3"
__progname__ = os.path.basename(sys.argv[0])
shutdown = False shutdown = False
resolvers = dns.resolver.get_default_resolver().nameservers resolvers = dns.resolver.get_default_resolver().nameservers
class Colors(object):
N = '\033[m' # native
R = '\033[31m' # red
G = '\033[32m' # green
O = '\033[33m' # orange
B = '\033[34m' # blue
def __init__(self, mode):
if not mode:
self.N = ''
self.R = ''
self.G = ''
self.O = ''
self.B = ''
def usage(): def usage():
print("""%s version %1.1f print("""%s version %s
usage: %s [-h] [-f server-list] [-c count] [-t type] [-w wait] hostname usage: %s [-h] [-f server-list] [-c count] [-t type] [-w wait] hostname
-h --help show this help -h --help show this help
@ -56,8 +74,9 @@ usage: %s [-h] [-f server-list] [-c count] [-t type] [-w wait] hostname
-t --type DNS request record type (default: A) -t --type DNS request record type (default: A)
-T --tcp Use TCP instead of UDP -T --tcp Use TCP instead of UDP
-e --edns Disable EDNS0 (Default: Enabled) -e --edns Disable EDNS0 (Default: Enabled)
-C --color Print colorful output
-v --verbose Print actual dns response -v --verbose Print actual dns response
""" % (__PROGNAME__, __VERSION__, __PROGNAME__)) """ % (__progname__, __version__, __progname__))
sys.exit() sys.exit()
@ -194,11 +213,12 @@ def main():
use_tcp = False use_tcp = False
use_edns = True use_edns = True
verbose = False verbose = False
color_mode = False
hostname = 'wikipedia.org' hostname = 'wikipedia.org'
try: try:
opts, args = getopt.getopt(sys.argv[1:], "hf:c:t:w:Tev", opts, args = getopt.getopt(sys.argv[1:], "hf:c:t:w:TevC",
["help", "file=", "count=", "type=", "wait=", "tcp", "edns", "verbose"]) ["help", "file=", "count=", "type=", "wait=", "tcp", "edns", "verbose", "color"])
except getopt.GetoptError as err: except getopt.GetoptError as err:
print(err) print(err)
usage() usage()
@ -224,12 +244,16 @@ def main():
use_tcp = True use_tcp = True
elif o in ("-e", "--edns"): elif o in ("-e", "--edns"):
use_edns = False use_edns = False
elif o in ("-C", "--color"):
color_mode = True
elif o in ("-v", "--verbose"): elif o in ("-v", "--verbose"):
verbose = True verbose = True
else: else:
print("Invalid option: %s" % o) print("Invalid option: %s" % o)
usage() usage()
color = Colors(color_mode)
try: try:
if fromfile: if fromfile:
with open(inputfilename, 'rt') as flist: with open(inputfilename, 'rt') as flist:
@ -286,12 +310,16 @@ def main():
if s_ttl == "None": if s_ttl == "None":
s_ttl = "N/A" s_ttl = "N/A"
print("%s %-8.3f %-8.3f %-8.3f %-8.3f %%%-3d %-8s %21s" % ( if r_lost_percent > 0:
s, r_avg, r_min, r_max, r_stddev, r_lost_percent, s_ttl, text_flags), flush=True) l_color = color.O
if verbose: else:
l_color = color.N
print("%s %-8.3f %-8.3f %-8.3f %-8.3f %s%%%-3d%s %-8s %21s" % (
s, r_avg, r_min, r_max, r_stddev, l_color, r_lost_percent, color.N, s_ttl, text_flags), flush=True)
if verbose and hasattr(answers, 'response'):
ans_index = 1 ans_index = 1
for answer in answers.response.answer: for answer in answers.response.answer:
print("Answer %d [ %s ]" % (ans_index, answer)) print("Answer %d [ %s%s%s ]" % (ans_index, color.B, answer, color.N))
ans_index += 1 ans_index += 1
print("") print("")

View File

@ -38,13 +38,15 @@ import dns.flags
import dns.rdatatype import dns.rdatatype
import dns.resolver import dns.resolver
__VERSION__ = 1.6 __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__PROGNAME__ = os.path.basename(sys.argv[0]) __license__ = 'BSD'
__version__ = "1.6.3"
__progname__ = os.path.basename(sys.argv[0])
shutdown = False shutdown = False
def usage(): def usage():
print("""%s version %1.1f print("""%s version %s
usage: %s [-ehqv] [-s server] [-p port] [-P port] [-S address] [-c count] [-t type] [-w wait] hostname usage: %s [-ehqv] [-s server] [-p port] [-P port] [-S address] [-c count] [-t type] [-w wait] hostname
-h --help Show this help -h --help Show this help
-q --quiet Quiet -q --quiet Quiet
@ -61,7 +63,7 @@ usage: %s [-ehqv] [-s server] [-p port] [-P port] [-S address] [-c count] [-t ty
-i --interval Time between each request (default: 0 seconds) -i --interval Time between each request (default: 0 seconds)
-t --type DNS request record type (default: A) -t --type DNS request record type (default: A)
-e --edns Disable EDNS0 (default: Enabled) -e --edns Disable EDNS0 (default: Enabled)
""" % (__PROGNAME__, __VERSION__, __PROGNAME__)) """ % (__progname__, __version__, __progname__))
sys.exit(0) sys.exit(0)
@ -172,7 +174,7 @@ def main():
response_time = [] response_time = []
i = 0 i = 0
print("%s DNS: %s:%d, hostname: %s, rdatatype: %s" % (__PROGNAME__, dnsserver, dst_port, hostname, dnsrecord)) print("%s DNS: %s:%d, hostname: %s, rdatatype: %s" % (__progname__, dnsserver, dst_port, hostname, dnsrecord))
for i in range(count): for i in range(count):
if shutdown: if shutdown:

View File

@ -39,13 +39,20 @@ import dns.query
import dns.rdatatype import dns.rdatatype
import dns.resolver import dns.resolver
from cymruwhois import cymruwhois import cymruwhois
# Global Variables
__author__ = 'Babak Farrokhi (babak@farrokhi.net)' __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD' __license__ = 'BSD'
__version__ = 1.6 __version__ = "1.6.3"
_ttl = None _ttl = None
quiet = False quiet = False
whois_cache = {}
shutdown = False
# Constants
__progname__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache'
class CustomSocket(socket.socket): class CustomSocket(socket.socket):
@ -64,11 +71,6 @@ def test_import():
pass pass
# Constants
__PROGNAME__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache'
class Colors(object): class Colors(object):
N = '\033[m' # native N = '\033[m' # native
R = '\033[31m' # red R = '\033[31m' # red
@ -85,40 +87,46 @@ class Colors(object):
self.B = '' self.B = ''
# Globarl Variables def whois_lookup(ip):
shutdown = False
def whoisrecord(ip):
try: try:
currenttime = time.perf_counter() global whois_cache
currenttime = time.time()
ts = currenttime ts = currenttime
if ip in whois: if ip in whois_cache:
asn, ts = whois[ip] asn, ts = whois_cache[ip]
else: else:
ts = 0 ts = 0
if (currenttime - ts) > 36000: if (currenttime - ts) > 36000:
c = cymruwhois.Client() c = cymruwhois.Client()
asn = c.lookup(ip) asn = c.lookup(ip)
whois[ip] = (asn, currenttime) whois_cache[ip] = (asn, currenttime)
return asn return asn
except Exception as e: except Exception as e:
return e return e
try: def load_whois_cache(cachefile):
pkl_file = open(WHOIS_CACHE, 'rb')
try: try:
whois = pickle.load(pkl_file) pkl_file = open(cachefile, 'rb')
except EOFError: try:
whois = pickle.load(pkl_file)
pkl_file.close()
except Exception:
whois = {}
except IOError:
whois = {} whois = {}
except IOError: return whois
whois = {}
def save_whois_cache(cachefile, whois_data):
pkl_file = open(cachefile, 'wb')
pickle.dump(whois_data, pkl_file)
pkl_file.close()
def usage(): def usage():
print('%s version %1.1f\n' % (__PROGNAME__, __version__)) print('%s version %s\n' % (__progname__, __version__))
print('usage: %s [-aeqhCx] [-s server] [-p port] [-c count] [-t type] [-w wait] hostname' % __PROGNAME__) print('usage: %s [-aeqhCx] [-s server] [-p port] [-c count] [-t type] [-w wait] hostname' % __progname__)
print(' -h --help Show this help') print(' -h --help Show this help')
print(' -q --quiet Quiet') print(' -q --quiet Quiet')
print(' -x --expert Print expert hints if available') print(' -x --expert Print expert hints if available')
@ -303,7 +311,7 @@ def main():
trace_path = [] trace_path = []
if not quiet: if not quiet:
print("%s DNS: %s:%d, hostname: %s, rdatatype: %s" % (__PROGNAME__, dnsserver, dest_port, hostname, dnsrecord), print("%s DNS: %s:%d, hostname: %s, rdatatype: %s" % (__progname__, dnsserver, dest_port, hostname, dnsrecord),
flush=True) flush=True)
while True: while True:
@ -367,11 +375,11 @@ def main():
if curr_addr: if curr_addr:
as_name = "" as_name = ""
if as_lookup: if as_lookup:
asn = whoisrecord(curr_addr) asn = whois_lookup(curr_addr)
as_name = '' as_name = ''
try: try:
if asn and asn.asn != "NA": if asn and asn.asn != "NA":
as_name = "[%s %s] " % (asn.asn, asn.owner) as_name = "[AS%s %s] " % (asn.asn, asn.owner)
except AttributeError: except AttributeError:
if shutdown: if shutdown:
sys.exit(0) sys.exit(0)
@ -404,7 +412,7 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
try: try:
whois_cache = load_whois_cache(WHOIS_CACHE)
main() main()
finally: finally:
pkl_file = open(WHOIS_CACHE, 'wb') save_whois_cache(WHOIS_CACHE, whois_cache)
pickle.dump(whois, pkl_file)

View File

@ -1 +1,2 @@
dnspython==1.15.0 dnspython>=1.15.0
cymruwhois>=1.6

View File

@ -2,8 +2,11 @@ from setuptools import setup, find_packages
setup( setup(
name="dnsdiag", name="dnsdiag",
version="1.6.0", version="1.6.3",
packages=find_packages(), packages=find_packages(),
scripts=["dnseval.py", "dnsping.py", "dnstraceroute.py"],
install_requires=['dnspython>=1.15.0', 'cymruwhois>=1.6'],
classifiers=[ classifiers=[
"Topic :: System :: Networking", "Topic :: System :: Networking",
"Environment :: Console", "Environment :: Console",