Untitled

mail@pastecode.io avatar
unknown
python
a year ago
3.2 kB
5
Indexable
Never
import socket
import struct

dns_cache = {}
 
def build_dns_query(domain, qtype=1):
    # Build a DNS query packet
    ID = 1337  # Unique identifier for the query
    FLAGS = 0x0100  # Standard query
    QDCOUNT = 1  # Number of questions
    ANCOUNT = 0  # Number of answers
    NSCOUNT = 0  # Number of authority records
    ARCOUNT = 0  # Number of additional records
 
    query = struct.pack('!HHHHHH', ID, FLAGS, QDCOUNT, ANCOUNT, NSCOUNT, ARCOUNT)
 
    for part in domain.split('.'):
        query += struct.pack('B', len(part)) + part.encode('utf-8')
 
    query += b'\x00'  # Null-terminator for domain name
    query += struct.pack('!H', qtype)  # Query type (A, CNAME, etc.)
    query += struct.pack('!H', 1)  # Query class IN (Internet)
 
    return query
 
def parse_dns_response(response):
    # Parse DNS response
    _, flags, _, ancount, _, _, _, _, _, _, _, _ = struct.unpack('!HHHHHHHHHHHH', response[:24])
 
    # Check if response is valid
    if flags & 0x8000 != 0x8000:  # Check if it's a response
        raise Exception("Not a DNS response")
 
    # Skip questions section
    pos = response.find(b'\x00', 24) + 5
 
    # Extract IP addresses, CNAME, and NS IP from answers
    ip_addresses = []
    cname = None
    ns_ip = None
    for _ in range(ancount):
        _, qtype, _, _, _, data_len = struct.unpack('!HHHHHH', response[pos:pos + 12])
        pos += 12
        if qtype == 1:  # A record
            ip = '.'.join(str(byte) for byte in response[pos:pos + data_len])
            ip_addresses.append(ip)
        elif qtype == 5:  # CNAME record
            cname = response[pos:pos + data_len]
        elif qtype == 2:  # NS record
            ns_ip = '.'.join(str(byte) for byte in response[pos:pos + data_len])
        pos += data_len
 
    return ip_addresses, cname, ns_ip
 
def resolve_dns(domain):
    if domain in dns_cache:
        print(f"Using cached result for {domain}")
        return dns_cache[domain]

    max_iterations = 5
    iterations = 0

    while iterations < max_iterations:
        server = ('8.8.8.8', 53)  # Google's public DNS server
        query = build_dns_query(domain)

        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
            sock.sendto(query, server)
            response, _ = sock.recvfrom(1024)

        ip_addresses, cname, ns_ip = parse_dns_response(response)

        if ip_addresses:
            dns_cache[domain] = ip_addresses
            return ip_addresses

        if cname:
            domain = cname.decode('utf-8')
        elif ns_ip:
            server = (ns_ip, 53)
        else:
            break

        iterations += 1

    raise Exception("DNS resolution failed after multiple iterations")

def main():
    domain = input("Enter domain name: ")

    try:
        ip_addresses = resolve_dns(domain)

        print("\nResolved IP Addresses:")
        for ip in ip_addresses:
            print(f"{domain} has IP address: {ip}")
    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    main()