forked from VigneshSP94/ppdns_stress
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathdns_load_gen.py
114 lines (102 loc) · 3.7 KB
/
dns_load_gen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python3
import argparse
import random
import socket
import struct
import sys
class MyParser(argparse.ArgumentParser):
def error(self, message):
sys.stderr.write(f"ERROR: {message}\n\n")
self.print_help()
sys.exit(2)
class DNSQueryGenerator:
def __init__(self, count, destinations, record, rtype, verbose):
self.count = count
self.destinations = destinations
self.record = record
self.rtype = rtype
self.verbose = verbose
def build_packet(self, record):
rtypes = {
"a": 1, "cname": 5, "mx": 15, "ns": 2, "ptr": 12, "soa": 6,
"srv": 33, "txt": 16
}
packet = struct.pack(">H", random.randrange(1, 65535)) # Query Ids
packet += struct.pack(">H", 256) # Flags
packet += struct.pack(">H", 1) # Questions
packet += struct.pack(">H", 0) # Answers
packet += struct.pack(">H", 0) # Authorities
packet += struct.pack(">H", 0) # Additional
split_record = record.split(".")
for part in split_record:
packet += struct.pack("B", len(part))
for byte in part:
packet += struct.pack("c", bytes(byte, "utf-8"))
packet += struct.pack("B", 0) # End of String
packet += struct.pack(">H", rtypes[self.rtype]) # Record Type
packet += struct.pack(">H", 1) # Query Class
return packet
def send_queries(self, work_queue):
count = 0
skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
skt.bind(("", 5000))
for dest in self.destinations:
for item in work_queue:
skt.sendto(bytes(item), (str(dest), 53))
count += 1
if self.verbose:
sys.stdout.write(
f"\rSent {int(count/len(self.destinations))} queries for "
f"{self.rtype.upper()} records of"
f" {self.record} to {len(self.destinations)} destinations. "
f"Total of {count} queries sent.\n"
)
else:
sys.stdout.write(f"\rSent {count} queries.\n")
def queue_handler(self):
"""
Builds a worker queue with the record and counts specified
then sends it to be processed.
"""
work_queue = []
query_count = 0
while query_count < self.count:
work_queue.append(self.build_packet(self.record))
query_count += 1
self.send_queries(work_queue)
def main():
parser = MyParser()
parser.add_argument(
"-c", "--count", default="10", metavar="10", type=int,
help="Set how many queries will be generated. "
"Default: 10"
)
parser.add_argument(
"-d", "--destinations", metavar="192.0.2.1", nargs="+",
required=True, type=str,
help="Set DNS server(s) to query. Accepts multiple entries "
"separated by space."
)
parser.add_argument(
"-r", "--record", metavar="example.com",
required=True, type=str,
help="Set name of the record to query."
)
parser.add_argument(
"-t", "--type",
choices=["a", "cname", "mx", "ns", "ptr", "soa", "srv", "txt"],
default="a", type=str,
help="Set type of record to query the DNS servers for. "
"Default: A Record"
)
parser.add_argument(
"-v", "--verbose", action="store_true",
help="Provide more detailed output."
)
args = parser.parse_args()
return DNSQueryGenerator(
count=args.count, destinations=args.destinations, record=args.record,
rtype=args.type, verbose=args.verbose
).queue_handler()
if __name__ == "__main__":
main()