mirror of
https://github.com/samba-team/samba.git
synced 2025-01-21 18:04:06 +03:00
traffic: load dns query from file and write stats to file
Signed-off-by: Joe Guo <joeg@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Wed May 1 01:10:42 UTC 2019 on sn-devel-184
This commit is contained in:
parent
35e52ebdd6
commit
2ee72cc615
@ -28,6 +28,8 @@ import signal
|
|||||||
from errno import ECHILD, ESRCH
|
from errno import ECHILD, ESRCH
|
||||||
|
|
||||||
from collections import OrderedDict, Counter, defaultdict, namedtuple
|
from collections import OrderedDict, Counter, defaultdict, namedtuple
|
||||||
|
from dns.resolver import query as dns_query
|
||||||
|
|
||||||
from samba.emulate import traffic_packets
|
from samba.emulate import traffic_packets
|
||||||
from samba.samdb import SamDB
|
from samba.samdb import SamDB
|
||||||
import ldb
|
import ldb
|
||||||
@ -967,22 +969,56 @@ class DnsHammer(Conversation):
|
|||||||
"""A lightweight conversation that generates a lot of dns:0 packets on
|
"""A lightweight conversation that generates a lot of dns:0 packets on
|
||||||
the fly"""
|
the fly"""
|
||||||
|
|
||||||
def __init__(self, dns_rate, duration):
|
def __init__(self, dns_rate, duration, query_file=None):
|
||||||
n = int(dns_rate * duration)
|
n = int(dns_rate * duration)
|
||||||
self.times = [random.uniform(0, duration) for i in range(n)]
|
self.times = [random.uniform(0, duration) for i in range(n)]
|
||||||
self.times.sort()
|
self.times.sort()
|
||||||
self.rate = dns_rate
|
self.rate = dns_rate
|
||||||
self.duration = duration
|
self.duration = duration
|
||||||
self.start_time = 0
|
self.start_time = 0
|
||||||
self.msg = random_colour_print()
|
self.query_choices = self._get_query_choices(query_file=query_file)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("<DnsHammer %d packets over %.1fs (rate %.2f)>" %
|
return ("<DnsHammer %d packets over %.1fs (rate %.2f)>" %
|
||||||
(len(self.times), self.duration, self.rate))
|
(len(self.times), self.duration, self.rate))
|
||||||
|
|
||||||
|
def _get_query_choices(self, query_file=None):
|
||||||
|
"""
|
||||||
|
Read dns query choices from a file, or return default
|
||||||
|
|
||||||
|
rname may contain format string like `{realm}`
|
||||||
|
realm can be fetched from context.realm
|
||||||
|
"""
|
||||||
|
|
||||||
|
if query_file:
|
||||||
|
with open(query_file, 'r') as f:
|
||||||
|
text = f.read()
|
||||||
|
choices = []
|
||||||
|
for line in text.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#'):
|
||||||
|
args = line.split(',')
|
||||||
|
assert len(args) == 4
|
||||||
|
choices.append(args)
|
||||||
|
return choices
|
||||||
|
else:
|
||||||
|
return [
|
||||||
|
(0, '{realm}', 'A', 'yes'),
|
||||||
|
(1, '{realm}', 'NS', 'yes'),
|
||||||
|
(2, '*.{realm}', 'A', 'no'),
|
||||||
|
(3, '*.{realm}', 'NS', 'no'),
|
||||||
|
(10, '_msdcs.{realm}', 'A', 'yes'),
|
||||||
|
(11, '_msdcs.{realm}', 'NS', 'yes'),
|
||||||
|
(20, 'nx.realm.com', 'A', 'no'),
|
||||||
|
(21, 'nx.realm.com', 'NS', 'no'),
|
||||||
|
(22, '*.nx.realm.com', 'A', 'no'),
|
||||||
|
(23, '*.nx.realm.com', 'NS', 'no'),
|
||||||
|
]
|
||||||
|
|
||||||
def replay(self, context=None):
|
def replay(self, context=None):
|
||||||
|
assert context
|
||||||
|
assert context.realm
|
||||||
start = time.time()
|
start = time.time()
|
||||||
fn = traffic_packets.packet_dns_0
|
|
||||||
for t in self.times:
|
for t in self.times:
|
||||||
now = time.time() - start
|
now = time.time() - start
|
||||||
gap = t - now
|
gap = t - now
|
||||||
@ -990,16 +1026,21 @@ class DnsHammer(Conversation):
|
|||||||
if sleep_time > 0:
|
if sleep_time > 0:
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
|
|
||||||
|
opcode, rname, rtype, exist = random.choice(self.query_choices)
|
||||||
|
rname = rname.format(realm=context.realm)
|
||||||
|
success = True
|
||||||
packet_start = time.time()
|
packet_start = time.time()
|
||||||
try:
|
try:
|
||||||
fn(None, None, context)
|
answers = dns_query(rname, rtype)
|
||||||
|
if exist == 'yes' and not len(answers):
|
||||||
|
# expect answers but didn't get, fail
|
||||||
|
success = False
|
||||||
|
except Exception:
|
||||||
|
success = False
|
||||||
|
finally:
|
||||||
end = time.time()
|
end = time.time()
|
||||||
duration = end - packet_start
|
duration = end - packet_start
|
||||||
print("%f\tDNS\tdns\t0\t%f\tTrue\t" % (end, duration))
|
print("%f\tDNS\tdns\t%s\t%f\t%s\t" % (end, opcode, duration, success))
|
||||||
except Exception as e:
|
|
||||||
end = time.time()
|
|
||||||
duration = end - packet_start
|
|
||||||
print("%f\tDNS\tdns\t0\t%f\tFalse\t%s" % (end, duration, e))
|
|
||||||
|
|
||||||
|
|
||||||
def ingest_summaries(files, dns_mode='count'):
|
def ingest_summaries(files, dns_mode='count'):
|
||||||
@ -1516,17 +1557,30 @@ def replay_seq_in_fork(cs, start, context, account, client_id, server_id=1):
|
|||||||
os._exit(status)
|
os._exit(status)
|
||||||
|
|
||||||
|
|
||||||
def dnshammer_in_fork(dns_rate, duration):
|
def dnshammer_in_fork(dns_rate, duration, context, query_file=None):
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
pid = os.fork()
|
pid = os.fork()
|
||||||
if pid != 0:
|
if pid != 0:
|
||||||
return pid
|
return pid
|
||||||
|
|
||||||
|
sys.stdin.close()
|
||||||
|
os.close(0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sys.stdout.close()
|
||||||
|
os.close(1)
|
||||||
|
except IOError as e:
|
||||||
|
LOGGER.warn("stdout closing failed with %s" % e)
|
||||||
|
pass
|
||||||
|
filename = os.path.join(context.statsdir, 'stats-dns')
|
||||||
|
sys.stdout = open(filename, 'w')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
status = 0
|
status = 0
|
||||||
signal.signal(signal.SIGTERM, flushing_signal_handler)
|
signal.signal(signal.SIGTERM, flushing_signal_handler)
|
||||||
hammer = DnsHammer(dns_rate, duration)
|
hammer = DnsHammer(dns_rate, duration, query_file=query_file)
|
||||||
hammer.replay()
|
hammer.replay(context=context)
|
||||||
except Exception:
|
except Exception:
|
||||||
status = 1
|
status = 1
|
||||||
print(("EXCEPTION in child PID %d, the DNS hammer" % (os.getpid())),
|
print(("EXCEPTION in child PID %d, the DNS hammer" % (os.getpid())),
|
||||||
@ -1544,6 +1598,7 @@ def replay(conversation_seq,
|
|||||||
lp=None,
|
lp=None,
|
||||||
accounts=None,
|
accounts=None,
|
||||||
dns_rate=0,
|
dns_rate=0,
|
||||||
|
dns_query_file=None,
|
||||||
duration=None,
|
duration=None,
|
||||||
latency_timeout=1.0,
|
latency_timeout=1.0,
|
||||||
stop_on_any_error=False,
|
stop_on_any_error=False,
|
||||||
@ -1593,7 +1648,8 @@ def replay(conversation_seq,
|
|||||||
children = {}
|
children = {}
|
||||||
try:
|
try:
|
||||||
if dns_rate:
|
if dns_rate:
|
||||||
pid = dnshammer_in_fork(dns_rate, duration)
|
pid = dnshammer_in_fork(dns_rate, duration, context,
|
||||||
|
query_file=dns_query_file)
|
||||||
children[pid] = 1
|
children[pid] = 1
|
||||||
|
|
||||||
for i, cs in enumerate(conversation_seq):
|
for i, cs in enumerate(conversation_seq):
|
||||||
|
@ -50,6 +50,8 @@ def main():
|
|||||||
|
|
||||||
parser.add_option('--dns-rate', type='float', default=0,
|
parser.add_option('--dns-rate', type='float', default=0,
|
||||||
help='fire extra DNS packets at this rate')
|
help='fire extra DNS packets at this rate')
|
||||||
|
parser.add_option('--dns-query-file', dest="dns_query_file",
|
||||||
|
help='A file contains DNS query list')
|
||||||
parser.add_option('-B', '--badpassword-frequency',
|
parser.add_option('-B', '--badpassword-frequency',
|
||||||
type='float', default=0.0,
|
type='float', default=0.0,
|
||||||
help='frequency of connections with bad passwords')
|
help='frequency of connections with bad passwords')
|
||||||
@ -403,6 +405,7 @@ def main():
|
|||||||
creds=creds,
|
creds=creds,
|
||||||
accounts=accounts,
|
accounts=accounts,
|
||||||
dns_rate=opts.dns_rate,
|
dns_rate=opts.dns_rate,
|
||||||
|
dns_query_file=opts.dns_query_file,
|
||||||
duration=opts.duration,
|
duration=opts.duration,
|
||||||
latency_timeout=opts.latency_timeout,
|
latency_timeout=opts.latency_timeout,
|
||||||
badpassword_frequency=opts.badpassword_frequency,
|
badpassword_frequency=opts.badpassword_frequency,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user