├── .github └── workflows │ └── python-publish.yml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── rapiddns ├── Exceptions.py ├── RapidDns.py ├── __init__.py ├── __main__.py └── __version__.py ├── screenshots └── example1.png └── setup.py /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ffs 2 | .DS_Store 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | *.py,cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | cover/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | .pybuilder/ 79 | target/ 80 | 81 | # Jupyter Notebook 82 | .ipynb_checkpoints 83 | 84 | # IPython 85 | profile_default/ 86 | ipython_config.py 87 | 88 | # pyenv 89 | # For a library or package, you might want to ignore these files since the code is 90 | # intended to run in multiple environments; otherwise, check them in: 91 | # .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # poetry 101 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 102 | # This is especially recommended for binary packages to ensure reproducibility, and is more 103 | # commonly ignored for libraries. 104 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 105 | #poetry.lock 106 | 107 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 108 | __pypackages__/ 109 | 110 | # Celery stuff 111 | celerybeat-schedule 112 | celerybeat.pid 113 | 114 | # SageMath parsed files 115 | *.sage.py 116 | 117 | # Environments 118 | .env 119 | .venv 120 | env/ 121 | venv/ 122 | ENV/ 123 | env.bak/ 124 | venv.bak/ 125 | 126 | # Spyder project settings 127 | .spyderproject 128 | .spyproject 129 | 130 | # Rope project settings 131 | .ropeproject 132 | 133 | # mkdocs documentation 134 | /site 135 | 136 | # mypy 137 | .mypy_cache/ 138 | .dmypy.json 139 | dmypy.json 140 | 141 | # Pyre type checker 142 | .pyre/ 143 | 144 | # pytype static type analyzer 145 | .pytype/ 146 | 147 | # Cython debug symbols 148 | cython_debug/ 149 | 150 | # PyCharm 151 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 152 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 153 | # and can be added to the global gitignore or merged into this file. For a more nuclear 154 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 155 | #.idea/ 156 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 nullter@bugdelivery.com 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. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | Simple python module (unofficial) allowing you to access data from rapiddns.io. You can also use it as a module. 3 | 4 | As mentioned on the rapiddns.io: 5 | 6 | *Rapiddns currently has more than 3 billion DNS resolution data, supporting A, CNAME, AAAA, MX types. A records 2.1 billion, CNAME records 250 million, AAAA records 103 million and MX records 510 million. Can query the domain name of the same IP website (support IPv6). You can also query subdomain information.* 7 | 8 | ![example](./screenshots/example1.png) 9 | 10 | # Installation 11 | ``` 12 | git clone https://github.com/nullt3r/rapiddns 13 | cd rapiddns 14 | pip3 install . 15 | ``` 16 | 17 | If you can't run the rapiddns directly from command line you should check if $HOME/.local/bin is in your path. 18 | 19 | Add the following line to your `~/.zshrc` or `~/.bashrc`: 20 | 21 | ``` 22 | export PATH="$HOME/.local/bin:$PATH" 23 | ``` 24 | 25 | # Usage 26 | To extract subdomains: 27 | ``` 28 | rapiddns --subdomains twitter.com 29 | ``` 30 | To extract domains from IP or CIDR: 31 | ``` 32 | rapiddns --ip 8.8.8.8/24 33 | ``` 34 | You can also combine both options. 35 | 36 | To display full output, use option --full. 37 | 38 | To use rapiddns as the module: 39 | 40 | ``` python 41 | from rapiddns import RapidDns 42 | 43 | enum_subdomains = RapidDns.subdomains("domain.com") 44 | enum_domains = RapidDns.sameip("1.2.3.4/24") 45 | 46 | for subdomain in enum_subdomains: 47 | print(" ".join(subdomain)) 48 | 49 | for domain in enum_domains: 50 | print(" ".join(domain)) 51 | 52 | ``` 53 | 54 | # License 55 | Read file LICENSE. 56 | 57 | # Disclaimer 58 | I am not responsible for any damages. You are responsible for your own 59 | actions. Attacking targets without prior mutual consent is illegal.* -------------------------------------------------------------------------------- /rapiddns/Exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | class RapidDnsNetworkError(Exception): 3 | pass 4 | 5 | class RapidDnsHTTPError(Exception): 6 | pass 7 | 8 | class RapidDnsHTMLParserError(Exception): 9 | pass -------------------------------------------------------------------------------- /rapiddns/RapidDns.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | 4 | from rapiddns import Exceptions 5 | 6 | def __extract_items(url): 7 | items = [] 8 | 9 | try: 10 | response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"}) 11 | html = response.content 12 | except Exception as e: 13 | raise Exceptions.RapidDnsNetworkError("can't connect to rapiddns.io") 14 | 15 | if response.status_code != 200: 16 | raise Exceptions.RapidDnsHTTPError("there was an error while reaching the rapiddns.io, the server responded with non-200 satus code") 17 | 18 | try: 19 | soup = BeautifulSoup(html, "html.parser") 20 | table = soup.find("table", id="table") 21 | rows = table.findAll("tr") 22 | items = [] 23 | for row in rows: 24 | cells = row.findAll("td") 25 | items.append([value.text.strip() for value in cells]) 26 | except Exception as e: 27 | raise Exceptions.RapidDnsHTMLParserError("can't parse HTML data from rapiddns.io") 28 | 29 | return items[1:] 30 | 31 | def subdomains(domain): 32 | url = f"https://rapiddns.io/subdomain/{domain}?full=1&down=1" 33 | return __extract_items(url) 34 | 35 | def sameip(ip): 36 | url = f"https://rapiddns.io/s/{ip}?full=1&down=1" 37 | return __extract_items(url) 38 | 39 | 40 | -------------------------------------------------------------------------------- /rapiddns/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | pass -------------------------------------------------------------------------------- /rapiddns/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from rapiddns import RapidDns 4 | 5 | def main(): 6 | from rapiddns import __version__ 7 | 8 | parser = argparse.ArgumentParser(description=f"rapiddns v{__version__.__version__} - a simple python client for rapiddns.io by @nullt3r") 9 | 10 | parser.add_argument( 11 | "--subdomains", 12 | "-s", 13 | action="store", 14 | help="expecting a domain name", 15 | required=False, 16 | ) 17 | parser.add_argument( 18 | "--ip", 19 | action="store", 20 | help="expecting an IP adress or CIDR", 21 | required=False, 22 | ) 23 | parser.add_argument( 24 | "--full", 25 | action="store_true", 26 | help="full output with detailed information", 27 | required=False, 28 | ) 29 | 30 | args = parser.parse_args() 31 | 32 | arg_subdomains = args.subdomains 33 | arg_ip = args.ip 34 | arg_full = args.full 35 | 36 | if (arg_subdomains or arg_ip) is None: 37 | parser.error('parameter --subdomains or --ip is required. You can specify both.') 38 | 39 | if arg_subdomains is not None: 40 | if arg_full is True: 41 | for line in RapidDns.subdomains(arg_subdomains): 42 | print(" ".join(line)) 43 | else: 44 | subdomains = [resource[0] for resource in RapidDns.subdomains(arg_subdomains)] 45 | print("\n".join(set(subdomains))) 46 | 47 | if arg_ip is not None: 48 | if arg_full is True: 49 | for line in RapidDns.sameip(arg_ip): 50 | print(" ".join(line)) 51 | else: 52 | domains = [resource[0] for resource in RapidDns.sameip(arg_ip)] 53 | print("\n".join(set(domains))) 54 | 55 | if __name__ == "__main__": 56 | main() -------------------------------------------------------------------------------- /rapiddns/__version__.py: -------------------------------------------------------------------------------- 1 | VERSION = (1, 0, 0) 2 | 3 | __version__ = '.'.join(map(str, VERSION)) -------------------------------------------------------------------------------- /screenshots/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nullt3r/rapiddns/69ddf2afe3eedca641a96ecbfcef52e266fc5ccb/screenshots/example1.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | from setuptools import setup, find_packages 3 | 4 | from rapiddns import __version__ 5 | 6 | # The directory containing this file 7 | HERE = pathlib.Path(__file__).parent 8 | 9 | # The text of the README file 10 | README = (HERE / "README.md").read_text() 11 | 12 | # This call to setup() does all the work 13 | setup( 14 | name="rapiddns", 15 | version=__version__.__version__, 16 | description="Simple python client for rapiddns.io.", 17 | long_description=README, 18 | long_description_content_type="text/markdown", 19 | url="https://github.com/nullt3r/rapiddns", 20 | author="nullt3r", 21 | author_email="nullt3r@bugdelivery.com", 22 | license="MIT", 23 | python_requires='>=3.6, <4', 24 | classifiers=[ 25 | "License :: OSI Approved :: MIT License", 26 | "Programming Language :: Python :: 3", 27 | "Programming Language :: Python :: 3.7", 28 | "Programming Language :: Python :: 3.9", 29 | ], 30 | packages=find_packages(), 31 | install_requires=["requests", "bs4"], 32 | entry_points={ 33 | "console_scripts": [ 34 | "rapiddns=rapiddns.__main__:main", 35 | ] 36 | }, 37 | ) 38 | --------------------------------------------------------------------------------