initial commit
This commit is contained in:
commit
1e3d9e7564
4 changed files with 76 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/venv/
|
9
README.md
Normal file
9
README.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
`numfinder` scans for nameservers incrementally to find the first available numerical domain
|
||||||
|
|
||||||
|
WARNING: It's usually inaccurate because a registered domain can (and many do) have no nameservers
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- Scan `.com` and `.eu`:
|
||||||
|
`python3 main.py com eu`
|
||||||
|
- Scan `.rocks` from 100 up to 1000:
|
||||||
|
`python3 main.py --min 100 --max 1000 rocks`
|
65
main.py
Normal file
65
main.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import argparse
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import dns.message
|
||||||
|
import dns.query
|
||||||
|
|
||||||
|
from dns.resolver import resolve, NXDOMAIN
|
||||||
|
from dns.rcode import Rcode
|
||||||
|
|
||||||
|
def get_resolvers(tld: str) -> List[str] | None:
|
||||||
|
try:
|
||||||
|
answers = resolve(tld, 'NS')
|
||||||
|
except NXDOMAIN:
|
||||||
|
return
|
||||||
|
|
||||||
|
return [resolve(i.target, 'A')[0].address for i in answers]
|
||||||
|
|
||||||
|
def name_exists(name: str, resolver: str) -> bool:
|
||||||
|
msg = dns.message.make_query(name, 'NS')
|
||||||
|
answer_msg = dns.query.udp(msg, resolver)
|
||||||
|
|
||||||
|
return answer_msg.rcode() == Rcode.NOERROR
|
||||||
|
|
||||||
|
def main(tld: str, min_num: int, max_num: int) -> int:
|
||||||
|
resolvers = get_resolvers(tld)
|
||||||
|
|
||||||
|
if resolvers is None:
|
||||||
|
print(f"Unknown TLD: {tld}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(f"Scanning TLD '{tld}' with {len(resolvers)} rootservers")
|
||||||
|
run_loop(tld, min_num, max_num, resolvers)
|
||||||
|
|
||||||
|
def run_loop(tld: str, min_num: int, max_num: int, resolvers: List[str]):
|
||||||
|
global name
|
||||||
|
|
||||||
|
for i in range(min_num, max_num):
|
||||||
|
name = f'{i}.{tld}'
|
||||||
|
resolver = resolvers[i % len(resolvers)]
|
||||||
|
|
||||||
|
if not name_exists(name, resolver):
|
||||||
|
print(name)
|
||||||
|
try:
|
||||||
|
input('Press Enter to continue, or Ctrl+C to skip TLD')
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('')
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"No free domains found in range {min_num} - {max_num} for TLD: {tld}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-m', '--min', help='Min number', type=int, default=10)
|
||||||
|
parser.add_argument('--max', help='Max number', type=int, default=10000)
|
||||||
|
parser.add_argument('tld', help='TLD', nargs='+')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
for tld in args.tld:
|
||||||
|
if main(tld, args.min, args.max) == 1:
|
||||||
|
break
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print(f"You interrupted at {name}")
|
||||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
dnspython==2.6.1
|
Loading…
Reference in a new issue