const std::vector<ConsoleKeyword> g_consoleKeywords{
/* keyword, function, parameters, description */
{ "addACL", true, "netmask", "add to the ACL set who can use this server" },
- { "addAction", true, "DNS rule, DNS action [, {uuid=\"UUID\"}]", "add a rule" },
+ { "addAction", true, "DNS rule, DNS action [, {uuid=\"UUID\", name=\"name\"}]", "add a rule" },
{ "addBPFFilterDynBlocks", true, "addresses, dynbpf[[, seconds=10], msg]", "This is the eBPF equivalent of addDynBlocks(), blocking a set of addresses for (optionally) a number of seconds, using an eBPF dynamic filter" },
{ "addConsoleACL", true, "netmask", "add a netmask to the console ACL" },
{ "addDNSCryptBind", true, "\"127.0.0.1:8443\", \"provider name\", \"/path/to/resolver.cert\", \"/path/to/resolver.key\", {reusePort=false, tcpFastOpenQueueSize=0, interface=\"\", cpus={}}", "listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of `provider name`, using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth optional parameter is a table of parameters" },
{ "addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" },
{ "addDynBlockSMT", true, "names, message[, seconds [, action]]", "block the set of names with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" },
{ "addLocal", true, "addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface=\"\", cpus={}}]", "add `addr` to the list of addresses we listen on" },
- { "addCacheHitResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\"}]", "add a cache hit response rule" },
- { "addResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\"}]", "add a response rule" },
- { "addSelfAnsweredResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\"}]", "add a self-answered response rule" },
+ { "addCacheHitResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\", name=\"name\"}}]", "add a cache hit response rule" },
+ { "addResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\", name=\"name\"}}]", "add a response rule" },
+ { "addSelfAnsweredResponseAction", true, "DNS rule, DNS response action [, {uuid=\"UUID\", name=\"name\"}}]", "add a self-answered response rule" },
{ "addTLSLocal", true, "addr, certFile(s), keyFile(s) [,params]", "listen to incoming DNS over TLS queries on the specified address using the specified certificate (or list of) and key (or list of). The last parameter is a table" },
{ "AllowAction", true, "", "let these packets go through" },
{ "AllowResponseAction", true, "", "let these packets go through" },
{ "newPacketCache", true, "maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, options={}]", "return a new Packet Cache" },
{ "newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity" },
{ "newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`" },
- { "newRuleAction", true, "DNS rule, DNS action [, {uuid=\"UUID\"}]", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
+ { "newRuleAction", true, "DNS rule, DNS action [, {uuid=\"UUID\", name=\"name\"}]", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
{ "newServer", true, "{address=\"ip:port\", qps=1000, order=1, weight=10, pool=\"abuse\", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName=\"a.root-servers.net.\", checkType=\"A\", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source=\"address|interface name|address@interface\", sockets=1, reconnectOnUp=false}", "instantiate a server" },
{ "newServerPolicy", true, "name, function", "create a policy object from a Lua function" },
{ "newSuffixMatchNode", true, "", "returns a new SuffixMatchNode" },
{ "RemoteLogAction", true, "RemoteLogger [, alterFunction [, serverID]]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes. `serverID` is the server identifier." },
{ "RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME [, serverID]]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records. `serverID` is the server identifier." },
{ "rmACL", true, "netmask", "remove netmask from ACL" },
- { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
- { "rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
- { "rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
- { "rmSelfAnsweredResponseRule", true, "id", "remove self-answered response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
+ { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" },
+ { "rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" },
+ { "rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" },
+ { "rmSelfAnsweredResponseRule", true, "id", "remove self-answered response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" },
{ "rmServer", true, "id", "remove server with index 'id' or whose uuid matches if 'id' is an UUID string" },
{ "roundrobin", false, "", "Simple round robin over available servers" },
{ "sendCustomTrap", true, "str", "send a custom `SNMP` trap from Lua, containing the `str` string"},
static void addAction(GlobalStateHolder<vector<T> > *someRulActions, const luadnsrule_t& var, const std::shared_ptr<ActionT>& action, boost::optional<luaruleparams_t>& params) {
setLuaSideEffect();
+ std::string name;
boost::uuids::uuid uuid;
uint64_t creationOrder;
- parseRuleParams(params, uuid, creationOrder);
+ parseRuleParams(params, uuid, name, creationOrder);
- auto rule=makeRule(var);
- someRulActions->modify([&rule, &action, &uuid, creationOrder](vector<T>& rulactions){
- rulactions.push_back({std::move(rule), std::move(action), std::move(uuid), creationOrder});
+ auto rule = makeRule(var);
+ someRulActions->modify([&rule, &action, &uuid, creationOrder, &name](vector<T>& rulactions){
+ rulactions.push_back({std::move(rule), std::move(action), std::move(name), std::move(uuid), creationOrder});
});
}
luaCtx.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr<DNSAction> action, boost::optional<luaruleparams_t> params) {
boost::uuids::uuid uuid;
uint64_t creationOrder;
- parseRuleParams(params, uuid, creationOrder);
+ std::string name;
+ parseRuleParams(params, uuid, name, creationOrder);
- auto rule=makeRule(dnsrule);
- DNSDistRuleAction ra({std::move(rule), action, uuid, creationOrder});
+ auto rule = makeRule(dnsrule);
+ DNSDistRuleAction ra({std::move(rule), action, std::move(name), uuid, creationOrder});
return std::make_shared<DNSDistRuleAction>(ra);
});
return getUniqueID(id);
}
-void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, uint64_t& creationOrder)
+void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder)
{
static uint64_t s_creationOrder = 0;
if (params->count("uuid")) {
uuidStr = boost::get<std::string>((*params)["uuid"]);
}
+ if (params->count("name")) {
+ name = boost::get<std::string>((*params)["name"]);
+ }
}
uuid = makeRuleID(uuidStr);
}
if (showUUIDs) {
- boost::format fmt("%-3d %-38s %9d %9d %-56s %s\n");
- result += (fmt % "#" % "UUID" % "Cr. Order" % "Matches" % "Rule" % "Action").str();
+ boost::format fmt("%-3d %-30s %-38s %9d %9d %-56s %s\n");
+ result += (fmt % "#" % "Name" % "UUID" % "Cr. Order" % "Matches" % "Rule" % "Action").str();
for(const auto& lim : rules) {
- string name = lim.d_rule->toString().substr(0, truncateRuleWidth);
- result += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ string desc = lim.d_rule->toString().substr(0, truncateRuleWidth);
+ result += (fmt % num % lim.d_name % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % desc % lim.d_action->toString()).str();
++num;
}
}
else {
- boost::format fmt("%-3d %9d %-56s %s\n");
- result += (fmt % "#" % "Matches" % "Rule" % "Action").str();
+ boost::format fmt("%-3d %-30s %9d %-56s %s\n");
+ result += (fmt % "#" % "Name" % "Matches" % "Rule" % "Action").str();
for(const auto& lim : rules) {
- string name = lim.d_rule->toString().substr(0, truncateRuleWidth);
- result += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+ string desc = lim.d_rule->toString().substr(0, truncateRuleWidth);
+ result += (fmt % num % lim.d_name % lim.d_rule->d_matches % desc % lim.d_action->toString()).str();
++num;
}
}
setLuaSideEffect();
auto rules = someRulActions->getCopy();
if (auto str = boost::get<std::string>(&id)) {
- const auto uuid = getUniqueID(*str);
- if (rules.erase(std::remove_if(rules.begin(),
- rules.end(),
- [uuid](const T& a) { return a.d_id == uuid; }),
- rules.end()) == rules.end()) {
- g_outputBuffer = "Error: no rule matched\n";
- return;
+ try {
+ const auto uuid = getUniqueID(*str);
+ if (rules.erase(std::remove_if(rules.begin(),
+ rules.end(),
+ [uuid](const T& a) { return a.d_id == uuid; }),
+ rules.end()) == rules.end()) {
+ g_outputBuffer = "Error: no rule matched\n";
+ return;
+ }
+ }
+ catch (const std::runtime_error& e) {
+ /* it was not an UUID, let's see if it was a name instead */
+ if (rules.erase(std::remove_if(rules.begin(),
+ rules.end(),
+ [&str](const T& a) { return a.d_name == *str; }),
+ rules.end()) == rules.end()) {
+ g_outputBuffer = "Error: no rule matched\n";
+ return;
+ }
}
}
else if (auto pos = boost::get<unsigned int>(&id)) {
for (const auto& pair : newruleactions) {
const auto& newruleaction = pair.second;
if (newruleaction->d_action) {
- auto rule=makeRule(newruleaction->d_rule);
- gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_id, newruleaction->d_creationOrder});
+ auto rule = makeRule(newruleaction->d_rule);
+ gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_name, newruleaction->d_id, newruleaction->d_creationOrder});
}
}
});
typedef boost::variant<string, vector<pair<int, string>>, std::shared_ptr<DNSRule>, DNSName, vector<pair<int, DNSName> > > luadnsrule_t;
std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var);
typedef std::unordered_map<std::string, boost::variant<std::string> > luaruleparams_t;
-void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, uint64_t& creationOrder);
+void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder);
typedef NetmaskTree<DynBlock> nmts_t;
{"id", num++},
{"creationOrder", (double)a.d_creationOrder},
{"uuid", boost::uuids::to_string(a.d_id)},
+ {"name", a.d_name},
{"matches", (double)a.d_rule->d_matches},
{"rule", a.d_rule->toString()},
{"action", a.d_action->toString()},
return responseRules;
}
-using namespace json11;
+template<typename T>
+static void addRulesToPrometheusOutput(std::ostringstream& output, GlobalStateHolder<vector<T> >& rules)
+{
+ auto localRules = rules.getLocal();
+ for (const auto& entry : *localRules) {
+ std::string id = !entry.d_name.empty() ? entry.d_name : boost::uuids::to_string(entry.d_id);
+ output << "dnsdist_rule_hits{id=\"" << id << "\"} " << entry.d_rule->d_matches << "\n";
+ }
+}
static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
{
}
}
+ output << "# HELP dnsdist_rule_hits " << "Number of hits of that rule" << "\n";
+ output << "# TYPE dnsdist_rule_hits " << "counter" << "\n";
+ addRulesToPrometheusOutput(output, g_rulactions);
+ addRulesToPrometheusOutput(output, g_resprulactions);
+ addRulesToPrometheusOutput(output, g_cachehitresprulactions);
+ addRulesToPrometheusOutput(output, g_selfansweredresprulactions);
+
output << "# HELP dnsdist_info " << "Info from dnsdist, value is always 1" << "\n";
output << "# TYPE dnsdist_info " << "gauge" << "\n";
output << "dnsdist_info{version=\"" << VERSION << "\"} " << "1" << "\n";
resp.headers["Content-Type"] = "text/plain";
}
+using namespace json11;
+
static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
{
handleCORS(req, resp);
}
Json::array rules;
+ /* unfortunately DNSActions have getStats(),
+ and DNSResponseActions do not. */
auto localRules = g_rulactions.getLocal();
- num=0;
- for(const auto& a : *localRules) {
+ num = 0;
+ for (const auto& a : *localRules) {
Json::object rule{
{"id", num++},
{"creationOrder", (double)a.d_creationOrder},
{
std::shared_ptr<DNSRule> d_rule;
std::shared_ptr<DNSAction> d_action;
+ std::string d_name;
boost::uuids::uuid d_id;
uint64_t d_creationOrder;
};
{
std::shared_ptr<DNSRule> d_rule;
std::shared_ptr<DNSResponseAction> d_action;
+ std::string d_name;
boost::uuids::uuid d_id;
uint64_t d_creationOrder;
};
.. versionchanged:: 1.3.0
Added the optional parameter ``options``.
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
Add a Rule and Action to the existing rules.
:param DNSrule rule: A DNSRule, e.g. an :func:`AllRule` or a compounded bunch of rules using e.g. :func:`AndRule`
Options:
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
.. function:: clearRules()
.. versionchanged:: 1.3.0
Added the optional parameter ``options``.
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
Return a pair of DNS Rule and DNS Action, to be used with :func:`setRules`.
:param Rule rule: A Rule (see `Matching Packets (Selectors)`_)
Options:
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
.. function:: setRules(rules)
.. versionchanged:: 1.3.0
``id`` can now be an UUID.
+ .. versionchanged:: 1.6.0
+ ``id`` can now be a string representing the name of the rule.
+
Remove rule ``id``.
- :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
+ :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
For Rules related to responses:
.. versionchanged:: 1.3.0
Added the optional parameter ``options``.
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
Add a Rule and Action for responses to the existing rules.
:param DNSRule: A DNSRule, e.g. an :func:`AllRule` or a compounded bunch of rules using e.g. :func:`AndRule`
Options:
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
.. function:: mvResponseRule(from, to)
.. versionchanged:: 1.3.0
``id`` can now be an UUID.
+ .. versionchanged:: 1.6.0
+ ``id`` can now be a string representing the name of the rule.
+
Remove response rule ``id``.
- :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
+ :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
.. function:: showResponseRules([options])
.. versionchanged:: 1.3.0
Added the optional parameter ``options``.
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
Add a Rule and ResponseAction for Cache Hits to the existing rules.
:param DNSRule: A DNSRule, e.g. an :func:`AllRule` or a compounded bunch of rules using e.g. :func:`AndRule`
Options:
* ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
.. function:: mvCacheHitResponseRule(from, to)
.. versionchanged:: 1.3.0
``id`` can now be an UUID.
- :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
+ .. versionchanged:: 1.6.0
+ ``id`` can now be a string representing the name of the rule.
+
+ :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
.. function:: showCacheHitResponseRules([options])
.. versionadded:: 1.3.0
+ .. versionchanged:: 1.6.0
+ Added ``name`` to the ``options``.
+
Add a Rule and Action for Self-Answered queries to the existing rules.
:param DNSRule: A DNSRule, e.g. an :func:`AllRule` or a compounded bunch of rules using e.g. :func:`AndRule`
:param action: The action to take
+ :param table options: A table with key: value pairs with options.
+
+ Options:
+
+ * ``uuid``: string - UUID to assign to the new rule. By default a random UUID is generated for each rule.
+ * ``name``: string - Name to assign to the new rule.
.. function:: mvSelfAnsweredResponseRule(from, to)
.. versionadded:: 1.3.0
+ .. versionchanged:: 1.6.0
+ ``id`` can now be a string representing the name of the rule.
+
Remove self answered response rule ``id``.
- :param int id: The UUID of the rule to remove if ``id`` is an UUID, its position otherwise
+ :param int id: The position of the rule to remove if ``id`` is numerical, its UUID or name otherwise
.. function:: showSelfAnsweredResponseRules([options])