├── .gitignore ├── LICENSE.md ├── MANIFEST.in ├── README.md ├── domnibus ├── __init__.py ├── cli.py ├── exceptions.py ├── operations.py └── utils.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | 3 | #####=== Python ===##### 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | env/ 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *,cover 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | 64 | README.txt 65 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Cyriac Thomas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Domnibus 2 | 3 | Wrapper to collect all information possible around a domain 4 | 5 | ## Installation 6 | 7 | ```pip install domnibus``` 8 | 9 | ## Usage 10 | 11 | ### Python 12 | 13 | ```python 14 | from domnibus import Domnibus 15 | 16 | d = Domnibus('google.com') 17 | 18 | for method in Domnibus.allowed_methods: 19 | print "{} details".format(method) 20 | print d[method] 21 | ``` 22 | 23 | You can also access the data as ```d.``` 24 | 25 | ### Command-line 26 | 27 | #### Generic usage 28 | ```domni domains``` 29 | 30 | #### Examples 31 | 32 | ##### List all ```methods``` 33 | 34 | ```domni ls``` or ```domni list``` 35 | 36 | ``` 37 | ssl 38 | whois 39 | dns 40 | ``` 41 | 42 | ##### SSL 43 | ```domni ssl google.com``` 44 | 45 | ``` 46 | version: 3 47 | subject_alt_name: [["DNS", "*.google.com"], ["DNS", "*.android.com"], ["DNS", "*.appengine.google.com"], ["DNS", "*.cloud.google.com"], ["DNS", "*.gcp.gvt2.com"], ["DNS", "*.google-analytics.com"], ["DNS", "*.google.ca"], ["DNS", "*.google.cl"], ["DNS", "*.google.co.in"], ["DNS", "*.google.co.jp"], ["DNS", "*.google.co.uk"], ["DNS", "*.google.com.ar"], ["DNS", "*.google.com.au"], ["DNS", "*.google.com.br"], ["DNS", "*.google.com.co"], ["DNS", "*.google.com.mx"], ["DNS", "*.google.com.tr"], ["DNS", "*.google.com.vn"], ["DNS", "*.google.de"], ["DNS", "*.google.es"], ["DNS", "*.google.fr"], ["DNS", "*.google.hu"], ["DNS", "*.google.it"], ["DNS", "*.google.nl"], ["DNS", "*.google.pl"], ["DNS", "*.google.pt"], ["DNS", "*.googleadapis.com"], ["DNS", "*.googleapis.cn"], ["DNS", "*.googlecommerce.com"], ["DNS", "*.googlevideo.com"], ["DNS", "*.gstatic.cn"], ["DNS", "*.gstatic.com"], ["DNS", "*.gvt1.com"], ["DNS", "*.gvt2.com"], ["DNS", "*.metric.gstatic.com"], ["DNS", "*.urchin.com"], ["DNS", "*.url.google.com"], ["DNS", "*.youtube-nocookie.com"], ["DNS", "*.youtube.com"], ["DNS", "*.youtubeeducation.com"], ["DNS", "*.ytimg.com"], ["DNS", "android.clients.google.com"], ["DNS", "android.com"], ["DNS", "developer.android.google.cn"], ["DNS", "developers.android.google.cn"], ["DNS", "g.co"], ["DNS", "goo.gl"], ["DNS", "google-analytics.com"], ["DNS", "google.com"], ["DNS", "googlecommerce.com"], ["DNS", "source.android.google.cn"], ["DNS", "urchin.com"], ["DNS", "www.goo.gl"], ["DNS", "youtu.be"], ["DNS", "youtube.com"], ["DNS", "youtubeeducation.com"]] 48 | issuer: [[["countryName", "US"]], [["organizationName", "Google Inc"]], [["commonName", "Google Internet Authority G2"]]] 49 | not_after: Jul 14 08:26:00 2017 GMT 50 | subject: [[["countryName", "US"]], [["stateOrProvinceName", "California"]], [["localityName", "Mountain View"]], [["organizationName", "Google Inc"]], [["commonName", "*.google.com"]]] 51 | crl_distribution_points: ["http://pki.google.com/GIAG2.crl"] 52 | serial_number: 53D7F33DC726A8AD 53 | ca_issuers: ["http://pki.google.com/GIAG2.crt"] 54 | not_before: Apr 21 09:13:03 2017 GMT 55 | OCSP: ["http://clients1.google.com/ocsp"] 56 | ``` 57 | 58 | ##### WHOIS 59 | ```domni whois google.com``` 60 | 61 | ``` 62 | updated_date: [datetime.datetime(2011, 7, 20, 0, 0), u'2015-06-12T10:38:52-0700'] 63 | status: ["clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited", "clientTransferProhibited https://icann.org/epp#clientTransferProhibited", "clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited", "serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited", "serverTransferProhibited https://icann.org/epp#serverTransferProhibited", "serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited", "clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)", "clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)", "clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)", "serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)", "serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)", "serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)"] 64 | name: Dns Admin 65 | dnssec: unsigned 66 | city: Mountain View 67 | expiration_date: [datetime.datetime(2020, 9, 14, 0, 0), u'2020-09-13T21:00:00-0700'] 68 | zipcode: 94043 69 | domain_name: ["GOOGLE.COM", "google.com"] 70 | country: US 71 | whois_server: whois.markmonitor.com 72 | state: CA 73 | registrar: MarkMonitor, Inc. 74 | referral_url: http://www.markmonitor.com 75 | address: Please contact contact-admin@google.com, 1600 Amphitheatre Parkway 76 | name_servers: ["NS1.GOOGLE.COM", "NS2.GOOGLE.COM", "NS3.GOOGLE.COM", "NS4.GOOGLE.COM", "ns1.google.com", "ns3.google.com", "ns2.google.com", "ns4.google.com"] 77 | org: Google Inc. 78 | creation_date: [datetime.datetime(1997, 9, 15, 0, 0), u'1997-09-15T00:00:00-0700'] 79 | emails: ["abusecomplaints@markmonitor.com", "contact-admin@google.com", "dns-admin@google.com"] 80 | ``` 81 | 82 | ##### DNS 83 | ```domni dns google.com``` 84 | 85 | ``` 86 | A: ["172.217.27.110"] 87 | AAAA: ["2404:6800:4003:c00::65"] 88 | MX: ["50 alt4.aspmx.l.google.com.", "30 alt2.aspmx.l.google.com.", "20 alt1.aspmx.l.google.com.", "40 alt3.aspmx.l.google.com.", "10 aspmx.l.google.com."] 89 | NS: ["ns1.google.com.", "ns4.google.com.", "ns2.google.com.", "ns3.google.com."] 90 | SOA: ["ns3.google.com. dns-admin.google.com. 154006190 900 900 1800 60"] 91 | TXT: ["\"v=spf1 include:_spf.google.com ~all\""] 92 | ``` 93 | 94 | 95 | -------------------------------------------------------------------------------- /domnibus/__init__.py: -------------------------------------------------------------------------------- 1 | from .exceptions import * 2 | from .operations import * 3 | from .utils import * 4 | import collections 5 | 6 | class Domnibus(DomnibusOperationMixin): 7 | FUNC_PREFIX = '_get_value_for_' 8 | 9 | def __init__(self, domain): 10 | self.domain = domain 11 | self._data = {} 12 | 13 | def __getitem__(self, method): 14 | return self._get_and_save_data(method) 15 | 16 | def __getattr__(self, method): 17 | if method in self.allowed_methods(): 18 | attr = self[method] 19 | else: 20 | attr = super(Domnibus, self).__getattr__(method) 21 | return attr 22 | 23 | @classmethod 24 | def allowed_methods(cls): 25 | allowed_methods = set() 26 | 27 | for func in dir(cls): 28 | if func.startswith(cls.FUNC_PREFIX) and isinstance(getattr(cls, func), collections.Callable): 29 | func_name = func.lstrip(cls.FUNC_PREFIX) 30 | allowed_methods.add(func_name) 31 | 32 | return allowed_methods 33 | 34 | def _get_and_save_data(self, key): 35 | if key in self.allowed_methods(): 36 | 37 | if key not in self._data: 38 | value, store = getattr(self, '{}{}'.format(self.FUNC_PREFIX, key))() 39 | value = unify_key_formats(value) 40 | if store: 41 | self._data[key] = value 42 | else: 43 | value = self._data[key] 44 | 45 | return value 46 | 47 | else: 48 | raise DomnibusMethodError("Method '{}' not implemented".format(key)) 49 | 50 | -------------------------------------------------------------------------------- /domnibus/cli.py: -------------------------------------------------------------------------------- 1 | import fire 2 | import copy 3 | from domnibus import Domnibus 4 | 5 | class DomnibusMeta(type): 6 | def __init__(cls, name, bases, attrs, **kwargs): 7 | allowed_methods = Domnibus.allowed_methods() 8 | cls.list = cls.ls = ['{} '.format(am) for am in allowed_methods] 9 | 10 | for method in allowed_methods: 11 | def get_method(method): 12 | def execute_method(domain, method): 13 | 14 | try: 15 | return Domnibus(domain)[method] 16 | except Exception as e: 17 | print('\033[91m' + str(e) + '\033[0m') 18 | 19 | return lambda self, domain: execute_method(domain, method) 20 | 21 | setattr(cls, method, get_method(method)) 22 | 23 | return super(DomnibusMeta, cls).__init__(name, bases, attrs) 24 | 25 | 26 | class DomnibusCLI(object): 27 | __metaclass__ = DomnibusMeta 28 | 29 | def cli(): 30 | fire.Fire(DomnibusCLI) 31 | 32 | if __name__ == '__main__': 33 | cli() 34 | -------------------------------------------------------------------------------- /domnibus/exceptions.py: -------------------------------------------------------------------------------- 1 | class DomnibusMethodError(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /domnibus/operations.py: -------------------------------------------------------------------------------- 1 | class DomnibusOperationMixin(object): 2 | 3 | def _get_value_for_whois(self): 4 | import whois 5 | return (whois.whois(self.domain), True) 6 | 7 | def _get_value_for_ssl(self): 8 | import ssl, socket 9 | 10 | ctx = ssl.create_default_context() 11 | s = ctx.wrap_socket(socket.socket(), server_hostname=self.domain) 12 | s.connect((self.domain, 443)) 13 | return (s.getpeercert(), True) 14 | 15 | def _get_value_for_dns(self): 16 | import dns.resolver 17 | from dns.resolver import NoAnswer 18 | from collections import OrderedDict 19 | 20 | values = OrderedDict() 21 | for tp in ["A", "AAAA", "MX", "NS", "SOA", "TXT"]: 22 | try: 23 | values[tp] = [entry.to_text() 24 | for entry in list(dns.resolver.query(self.domain, tp))] 25 | except NoAnswer: 26 | values[tp] = [] 27 | return (values, True) 28 | -------------------------------------------------------------------------------- /domnibus/utils.py: -------------------------------------------------------------------------------- 1 | def camel_case_to_lower_case_underscore(string): 2 | """ 3 | Split string by upper case letters. 4 | 5 | F.e. useful to convert camel case strings to underscore separated ones. 6 | 7 | @return words (list) 8 | """ 9 | if not string.isupper(): 10 | words = [] 11 | from_char_position = 0 12 | for current_char_position, char in enumerate(string): 13 | if char.isupper() and from_char_position < current_char_position: 14 | words.append(string[from_char_position:current_char_position].lower()) 15 | from_char_position = current_char_position 16 | words.append(string[from_char_position:].lower()) 17 | string = '_'.join(words) 18 | 19 | return string 20 | 21 | def unify_key_formats(response_dict): 22 | value = {} 23 | for k, v in response_dict.items(): 24 | value[camel_case_to_lower_case_underscore(k)] = v 25 | return value -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | dnspython==1.15.0 2 | ipython==5.3.0; python_version < '3.3' 3 | fire==0.1.0 4 | python-whois==0.6.5 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from pip.req import parse_requirements 5 | from pip.download import PipSession 6 | from setuptools import find_packages 7 | 8 | try: 9 | from setuptools import setup 10 | except ImportError: 11 | from distutils.core import setup 12 | 13 | # reading requirements 14 | install_reqs = parse_requirements('requirements.txt', session=PipSession()) 15 | reqs = [str(ir.req) for ir in install_reqs] 16 | sys.path.insert(0, os.path.dirname(__file__)) 17 | version = '1.0.4' 18 | setup( 19 | name='domnibus', 20 | author='cyriac', 21 | author_email='me@cyriacthomas.com', 22 | version=version, 23 | packages=find_packages(), 24 | install_requires=reqs, 25 | include_package_data=True, 26 | license='MIT', 27 | description='Get all possible information about a domain', 28 | keywords = ['domnibus', 'domni', 'whois', 'ssl', 'nameserver', 'dns'], 29 | url='https://github.com/cyriac/domnibus', 30 | download_url = 'https://github.com/cyriac/domnibus/archive/v{version}.tar.gz'.format(version=version), 31 | entry_points=''' 32 | [console_scripts] 33 | domni=domnibus.cli:cli 34 | ''' 35 | ) 36 | --------------------------------------------------------------------------------