Skip to content
Snippets Groups Projects
Verified Commit 438f45bd authored by Tomas Krizek's avatar Tomas Krizek
Browse files

replay/shotgun.lua: replace UI with lua config

parent 51e361fa
No related branches found
No related tags found
1 merge request!27ui: allow traffic mixing
local config = {}
config.pcap = {{ pcap }}
config.verbosity = {{ verbosity }}
config.drift_s = {{ drift_s }}
config.threads = {}
{% for i, thread in enumerate(threads) %}
local thrconf = {}
thrconf.name = {{ thread.name }}
thrconf.channel_size = {{ thread.channel_size|default(2048) }}
thrconf.max_clients = {{ thread.max_clients|default(200000) }}
thrconf.target_ip = {{ thread.target_ip }}
thrconf.target_port = {{ thread.target_port }}
thrconf.timeout_s = {{ thread.timeout_s }}
thrconf.handshake_timeout_s = {{ thread.handshake_timeout_s }}
thrconf.idle_timeout_s = {{ thread.idle_timeout_s }}
thrconf.protocol_func = {{ thread.protocol_func }}
thrconf.tls_priority = {{ thread.tls_priority }}
thrconf.http_method = {{ thread.http_method }}
thrconf.output_file = {{ thread.output_file }}
thrconf.max_batch_size = {{ thread.max_batch_size|default(32) }}
thrconf.bind_ips = {} -- TODO
config.threads[{{ i + 1 }}] = thrconf
{% endfor %}
return config
# vim: syntax=lua
#!/usr/bin/env dnsjit
--- Check if a file or directory exists in this path
local function exists(file)
local ok, err, code = os.rename(file, file)
if not ok then
if code == 13 then
-- Permission denied, but it exists
return true
end
end
return ok, err
end
local dir = os.getenv("PWD") or ""
local object = require("dnsjit.core.objects")
local log = require("dnsjit.core.log")
local getopt = require("dnsjit.lib.getopt").new({
{ "v", "verbose", 2, "Verbosity level (0-5)", "?" },
{ "T", "threads", 1, "Number of sender threads", "?" },
{ "p", "port", 53, "Target port", "?" },
{ "P", "protocol", "udp", "Protocol to use: udp, tcp, dot, doh", "?" },
{ "M", "http-method", "GET", "HTTP method for DoH: GET, POST", "?" },
{ "s", "server", "::1", "Target IPv6 address", "?" },
{ "t", "timeout", 2, "Timeout for requests", "?" },
{ "k", "hanshake_timeout", 5, "Timeout for session handshake", "?" },
{ "e", "idle_timeout", 10, "Idle timeout for stateful transports", "?" },
{ nil, "tls-priority", "NORMAL", "GnutTLS priority string", "?" },
{ nil, "bind-pattern", "", "Source IPv6 bind address pattern (example: 'fd00::%x')", "?" },
{ nil, "bind-num", 1, "Number of source IPs per thread (when --bind-pattern is set)", "?" },
{ nil, "drift", 1, "Maximum realtime drift (seconds)", "?" },
{ "O", "outdir", dir, "Directory for output files (must exist)", "?" },
})
local pcap = unpack(getopt:parse())
if getopt:val("help") then
getopt:usage()
return
local getopt = require("dnsjit.lib.getopt").new({})
local confpath = unpack(getopt:parse())
if confpath == nil then
log.fatal("lua config file must be specified as first argument")
end
local ok, config = pcall(dofile, confpath)
if not ok then
log.fatal("failed to load lua config file \""..config.."\"")
end
local v = getopt:val("v")
if v > 0 then
if config.verbosity > 0 then
log.enable("warning")
end
if v > 1 then
if config.verbosity > 1 then
log.enable("notice")
end
if v > 2 then
if config.verbosity > 2 then
log.display_file_line(true)
end
if v > 3 then
if config.verbosity > 3 then
log.enable("info")
end
if v > 4 then
if config.verbosity > 4 then
log.enable("debug")
end
if pcap == nil then
print("usage: "..arg[1].." <pcap>")
return
end
local SEND_THREADS = getopt:val("T")
local TARGET_IP = getopt:val("s")
local TARGET_PORT = getopt:val("p")
local TIMEOUT = getopt:val("t")
local HANDSHAKE_TIMEOUT = getopt:val("k")
local IDLE_TIMEOUT = getopt:val("e")
local BIND_IP_PATTERN = getopt:val("bind-pattern")
local NUM_BIND_IP = getopt:val("bind-num")
local REALTIME_DRIFT = getopt:val("drift")
local MAX_CLIENTS_DNSSIM = 200000
local CHANNEL_SIZE = 2048
local MAX_BATCH_SIZE = 32 -- libuv default
local PROTOCOLS = {
udp = "udp",
tcp = "tcp",
tls = "tls",
dot = "tls",
https2 = "https2",
doh = "https2",
}
local proto = getopt:val("P")
local PROTOCOL = PROTOCOLS[proto]
if PROTOCOL == nil then
log.fatal("unknown protocol: "..proto)
end
local HTTP_METHOD = getopt:val("M")
if HTTP_METHOD ~= "GET" and HTTP_METHOD ~= "POST" then
log.fatal("unsupported HTTP method: "..HTTP_METHOD)
end
local TLS_PRIORITY = getopt:val("tls-priority")
if string.find(TLS_PRIORITY, '"') ~= nil or string.find(TLS_PRIORITY, "'") ~= nil then
log.fatal("tls priority string may not contain quotes");
end
local OUTDIR = getopt:val("O")
if OUTDIR == "" or not exists(OUTDIR .. "/") then
log.fatal("output directory \"" .. OUTDIR .. "\" doesn't exist")
end
-- TODO remove dead code
--local PROTOCOLS = {
-- udp = "udp",
-- tcp = "tcp",
-- tls = "tls",
-- dot = "tls",
-- https2 = "https2",
-- doh = "https2",
--}
--local proto = getopt:val("P")
--local PROTOCOL = PROTOCOLS[proto]
--if PROTOCOL == nil then
-- log.fatal("unknown protocol: "..proto)
--end
--local HTTP_METHOD = getopt:val("M")
--if HTTP_METHOD ~= "GET" and HTTP_METHOD ~= "POST" then
-- log.fatal("unsupported HTTP method: "..HTTP_METHOD)
--end
--local TLS_PRIORITY = getopt:val("tls-priority")
--if string.find(TLS_PRIORITY, '"') ~= nil or string.find(TLS_PRIORITY, "'") ~= nil then
-- log.fatal("tls priority string may not contain quotes");
--end
--local OUTDIR = getopt:val("O")
--if OUTDIR == "" or not exists(OUTDIR .. "/") then
-- log.fatal("output directory \"" .. OUTDIR .. "\" doesn't exist")
--end
--
--
local function send_thread_main(thr)
local channel = thr:pop()
local running
......@@ -112,29 +72,29 @@ local function send_thread_main(thr)
output:handshake_timeout(thr:pop())
output:idle_timeout(thr:pop())
local protocol = thr:pop()
local protocol_func = thr:pop()
local tls_priority = thr:pop()
local http_method = thr:pop()
local cmd = "output:" .. protocol
local cmd = "output:" .. protocol_func
if protocol == "udp" then
if protocol_func == "udp" then
if type(output.udp_only) == "function" then
-- backward compat with dnsjit 1.0.0
-- https://github.com/DNS-OARC/dnsjit/pull/173
cmd = "output:udp_only"
end
cmd = cmd .. "()"
elseif protocol == "tcp" then
elseif protocol_func == "tcp" then
cmd = cmd .. "()"
elseif protocol == "tls" then
elseif protocol_func == "tls" then
cmd = cmd .. "('" .. tls_priority .. "')"
elseif protocol == "https2" then
elseif protocol_func == "https2" then
if type(output.https2) ~= "function" then
log:fatal("https2 isn't supported with this version of dnsjit")
end
cmd = cmd .. "({ method = '" .. http_method .. "' }, '" .. tls_priority .. "')"
else
log:fatal("unknown protocol: " .. protocol)
log:fatal("unknown protocol_func: " .. protocol_func)
end
assert(loadstring(cmd))()
......@@ -200,14 +160,14 @@ local function send_thread_main(thr)
end
-- setup input
---- setup input
local input = require("dnsjit.input.fpcap").new()
local delay = require("dnsjit.filter.timing").new()
local layer = require("dnsjit.filter.layer").new()
local ipsplit = require("dnsjit.filter.ipsplit").new()
local copy = require("dnsjit.filter.copy").new()
input:open(pcap)
delay:realtime(REALTIME_DRIFT)
input:open(config.pcap)
delay:realtime(config.drift_s)
delay:producer(input)
layer:producer(delay)
ipsplit:overwrite_dst()
......@@ -218,36 +178,29 @@ local channel = require("dnsjit.core.channel")
local threads = {}
local channels = {}
-- send threads
local outname = OUTDIR.."/shotgun-"..os.time().."-%s.json"
for i = 1, SEND_THREADS do
channels[i] = channel.new(CHANNEL_SIZE)
---- initialize send threads
for i, thrconf in ipairs(config.threads) do
channels[i] = channel.new(thrconf.channel_size)
ipsplit:receiver(channels[i])
local name = string.format("%s-%02d", proto, i)
threads[i] = thread.new()
threads[i]:start(send_thread_main)
threads[i]:push(channels[i])
threads[i]:push(MAX_CLIENTS_DNSSIM)
threads[i]:push(name)
threads[i]:push(TARGET_IP)
threads[i]:push(TARGET_PORT)
threads[i]:push(TIMEOUT)
threads[i]:push(HANDSHAKE_TIMEOUT)
threads[i]:push(IDLE_TIMEOUT)
threads[i]:push(PROTOCOL)
threads[i]:push(TLS_PRIORITY)
threads[i]:push(HTTP_METHOD)
threads[i]:push(string.format(outname, name))
threads[i]:push(MAX_BATCH_SIZE)
if BIND_IP_PATTERN ~= "" then
threads[i]:push(NUM_BIND_IP)
for j = 1, NUM_BIND_IP do
local addr = string.format(BIND_IP_PATTERN, NUM_BIND_IP*(i-1)+j)
threads[i]:push(addr)
end
else
threads[i]:push(0)
threads[i]:push(thrconf.max_clients)
threads[i]:push(thrconf.name)
threads[i]:push(thrconf.target_ip)
threads[i]:push(thrconf.target_port)
threads[i]:push(thrconf.timeout_s)
threads[i]:push(thrconf.handshake_timeout_s)
threads[i]:push(thrconf.idle_timeout_s)
threads[i]:push(thrconf.protocol_func)
threads[i]:push(thrconf.tls_priority)
threads[i]:push(thrconf.http_method)
threads[i]:push(thrconf.output_file)
threads[i]:push(thrconf.max_batch_size)
threads[i]:push(#thrconf.bind_ips)
for _, bind_ip in thrconf.bind_ips do
threads[i]:push(bind_ip)
end
end
......@@ -266,9 +219,9 @@ while true do
end
-- teardown
for i = 1, SEND_THREADS do
for i, _ in ipairs(config.threads) do
channels[i]:close()
end
for i = 1, SEND_THREADS do
for i, _ in ipairs(config.threads) do
threads[i]:stop()
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment