ptrstream

- Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.acid.vegas/-c.git
Log | Files | Refs | Archive | README

commit 37157fb8b89ac2ac79ca11227f07754b9383a770
Author: acidvegas <acid.vegas@acid.vegas>
Date: Thu, 23 Nov 2023 03:08:28 -0500

Initial commit

Diffstat:
AREADME.md | 3+++
Aptrstream.py | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md
@@ -0,0 +1,3 @@
+# PTR Stream
+
+## More to come
diff --git a/ptrstream.py b/ptrstream.py
@@ -0,0 +1,106 @@
+#/usr/bin/env python
+# ptrstream - developed by acidvegas in python (https://git.acid.vegas/ptrstream)
+
+import argparse
+import asyncio
+import ipaddress
+import random
+import time
+import urllib.request
+
+try:
+	import aiodns
+except ImportError:
+	raise ImportError('missing required \'aiodns\' library (pip install aiodns)')
+
+
+def get_dns_servers() -> list:
+	'''Get a list of DNS servers to use for lookups.'''
+	source = urllib.request.urlopen('https://public-dns.info/nameservers.txt')
+	results = source.read().decode().split('\n')
+	return [server for server in results if ':' not in server]
+
+
+async def rdns(semaphore: asyncio.Semaphore, ip_address: str, custom_dns_server: str):
+	'''
+	Perform a reverse DNS lookup on an IP address.
+
+	:param ip_address: The IP address to lookup.
+	:param custom_dns_server: The DNS server to use for lookups.
+	:param semaphore: A semaphore to limit the number of concurrent lookups.
+	:param timeout: The timeout for the lookup.
+	'''
+	async with semaphore:
+		resolver = aiodns.DNSResolver(nameservers=[custom_dns_server], rotate=False, timeout=args.timeout)
+		reverse_name = ipaddress.ip_address(ip_address).reverse_pointer
+		try:
+			answer = await resolver.query(reverse_name, 'PTR')
+			return ip_address, answer.name
+		except:
+			return ip_address, None
+
+
+def rig(seed: int) -> str:
+	'''
+	Random IP generator.
+
+	:param seed: The seed to use for the random number generator.
+	'''
+	max_value = 256**4
+	random.seed(seed)
+	for _ in range(max_value):
+		shuffled_index = random.randint(0, max_value - 1)
+		ip = ipaddress.ip_address(shuffled_index)
+		yield str(ip)
+
+
+async def main():
+	'''Generate random IPs and perform reverse DNS lookups.'''
+	semaphore = asyncio.Semaphore(args.concurrency)
+	tasks = []
+	results_cache = []
+
+	while True:
+		dns_servers = []
+		while not dns_servers:
+			try:
+				dns_servers = get_dns_servers()
+			except:
+				time.sleep(300)
+
+		seed = random.randint(10**9, 10**10 - 1)
+		ip_generator = rig(seed)
+
+		for ip in ip_generator:
+			if len(tasks) < args.concurrency:
+				dns = random.choice(dns_servers)
+				task = asyncio.create_task(rdns(semaphore, ip, dns))
+				tasks.append(task)
+			else:
+				done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
+				tasks = list(pending)
+				for task in done:
+					ip, result = task.result()
+					if result:
+						for exclude in ('undefined.hostname.localhost', 'localhost', '127.0.0.1'):
+							if result == exclude:
+								continue
+						if not result.endswith('.in-addr.arpa') and result != ('undefined.hostname.localhost') and result != ('localhost.'):
+							print(f'{ip.ljust(15)} -> {result}')
+							results_cache.append(f'{ip}:{result}')
+
+					if len(results_cache) >= 1000:
+						stamp = time.strftime('%Y%m%d')
+						with open(f'ptr_{stamp}_{seed}.txt', 'a') as file:
+							file.writelines(f"{record}\n" for record in results_cache)
+						results_cache = []
+
+
+
+if __name__ == '__main__':
+	parser = argparse.ArgumentParser(description='Perform asynchronous reverse DNS lookups.')
+	parser.add_argument('-c', '--concurrency', type=int, default=50, help='Control the speed of lookups.')
+	parser.add_argument('-t', '--timeout', type=int, default=5, help='Timeout for DNS lookups.')
+	args = parser.parse_args()
+
+	asyncio.run(main())