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

shotgun: add minimalistic UI

A slight improvement over the previous UI.

- now it's possible to select protocol and send 100% of traffic over it
  (udp, tcp, dot, doh)
- check dir exists to fail early (instead of after test)
- rename options related to binding to IP, these are likely to change in
  the future
- remove stats_interval, since it's better to always use 1s with updated
  dnsjit

Related #6
parent 93fc188f
No related branches found
No related tags found
1 merge request!17shotgun: updates
#!/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
--- Check if a directory exists in this path
local function isdir(path)
-- "/" works on both Unix and Windows
return exists(path.."/")
end
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 TCP sessions", "?" },
{ "P", "priority", "NORMAL", "GnutTLS priority string", "?" },
{ "b", "bind", "", "Source IPv6 bind address pattern (example: 'fd00::%x')", "?" },
{ "i", "ips", 1, "Number of source IPs per thread (when -b is set)", "?" },
{ "d", "drift", 1.0, "Maximum realtime drift (seconds)", "?" },
{ "S", "stats_interval", 5, "Log statistics every N seconds", "?" },
{ "O", "outdir", ".", "Directory for output files (must exist)", "?" },
{ "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", os.getenv("PWD"), "Directory for output files (must exist)", "?" },
})
local pcap = unpack(getopt:parse())
if getopt:val("help") then
......@@ -49,28 +69,81 @@ local TARGET_PORT = getopt:val("p")
local TIMEOUT = getopt:val("t")
local HANDSHAKE_TIMEOUT = getopt:val("k")
local IDLE_TIMEOUT = getopt:val("e")
local TLS_PRIORITY = getopt:val("P")
local BIND_IP_PATTERN = getopt:val("b")
local NUM_BIND_IP = getopt:val("i")
local REALTIME_DRIFT = getopt:val("d")
local LOG_INTERVAL = getopt:val("S")
local OUTDIR = getopt:val("O")
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 = 16384 -- empirically tested value suitable for UDP dnssim
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 not isdir(OUTDIR) then
log.fatal("output directory \"" .. OUTDIR .. "\" doesn't exist")
end
local function thread_output(thr)
local function send_thread_main(thr)
local channel = thr:pop()
local output = require("dnsjit.output.dnssim").new(thr:pop())
local running
-- output must be global (per thread) to be accesible in loadstring()
-- luacheck: globals output, ignore log
output = require("dnsjit.output.dnssim").new(thr:pop())
local log = require("dnsjit.core.log")
output:target(thr:pop(), thr:pop())
output:timeout(thr:pop())
output:handshake_timeout(thr:pop())
output:idle_timeout(thr:pop())
output:tls(thr:pop())
output:stats_collect(thr:pop())
local protocol = thr:pop()
local tls_priority = thr:pop()
local http_method = thr:pop()
local cmd = "output:" .. protocol
if protocol == "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
cmd = cmd .. "()"
elseif protocol == "tls" then
cmd = cmd .. "('" .. tls_priority .. "')"
elseif protocol == "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)
end
assert(loadstring(cmd))()
output:stats_collect(1)
output:free_after_use(true)
local outfile = thr:pop()
......@@ -138,7 +211,7 @@ for i = 1, SEND_THREADS do
ipsplit:receiver(channels[i])
threads[i] = thread.new()
threads[i]:start(thread_output)
threads[i]:start(send_thread_main)
threads[i]:push(channels[i])
threads[i]:push(MAX_CLIENTS_DNSSIM)
threads[i]:push(TARGET_IP)
......@@ -146,8 +219,9 @@ for i = 1, SEND_THREADS do
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(LOG_INTERVAL)
threads[i]:push(HTTP_METHOD)
threads[i]:push(string.format(outname, i))
threads[i]:push(MAX_BATCH_SIZE)
if BIND_IP_PATTERN ~= "" then
......
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