summaryrefslogtreecommitdiffstats
path: root/src/knot/modules/queryacl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:24:08 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:24:08 +0000
commitf449f278dd3c70e479a035f50a9bb817a9b433ba (patch)
tree8ca2bfb785dda9bb4d573acdf9b42aea9cd51383 /src/knot/modules/queryacl
parentInitial commit. (diff)
downloadknot-upstream.tar.xz
knot-upstream.zip
Adding upstream version 3.2.6.upstream/3.2.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/knot/modules/queryacl')
-rw-r--r--src/knot/modules/queryacl/Makefile.inc12
-rw-r--r--src/knot/modules/queryacl/queryacl.c93
-rw-r--r--src/knot/modules/queryacl/queryacl.rst70
3 files changed, 175 insertions, 0 deletions
diff --git a/src/knot/modules/queryacl/Makefile.inc b/src/knot/modules/queryacl/Makefile.inc
new file mode 100644
index 0000000..25dcc38
--- /dev/null
+++ b/src/knot/modules/queryacl/Makefile.inc
@@ -0,0 +1,12 @@
+knot_modules_queryacl_la_SOURCES = knot/modules/queryacl/queryacl.c
+EXTRA_DIST += knot/modules/queryacl/queryacl.rst
+
+if STATIC_MODULE_queryacl
+libknotd_la_SOURCES += $(knot_modules_queryacl_la_SOURCES)
+endif
+
+if SHARED_MODULE_queryacl
+knot_modules_queryacl_la_LDFLAGS = $(KNOTD_MOD_LDFLAGS)
+knot_modules_queryacl_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS)
+pkglib_LTLIBRARIES += knot/modules/queryacl.la
+endif
diff --git a/src/knot/modules/queryacl/queryacl.c b/src/knot/modules/queryacl/queryacl.c
new file mode 100644
index 0000000..e787083
--- /dev/null
+++ b/src/knot/modules/queryacl/queryacl.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "knot/include/module.h"
+#include "contrib/sockaddr.h"
+
+#define MOD_ADDRESS "\x07""address"
+#define MOD_INTERFACE "\x09""interface"
+
+const yp_item_t queryacl_conf[] = {
+ { MOD_ADDRESS, YP_TNET, YP_VNONE, YP_FMULTI },
+ { MOD_INTERFACE, YP_TNET, YP_VNONE, YP_FMULTI },
+ { NULL }
+};
+
+typedef struct {
+ knotd_conf_t allow_addr;
+ knotd_conf_t allow_iface;
+} queryacl_ctx_t;
+
+static knotd_state_t queryacl_process(knotd_state_t state, knot_pkt_t *pkt,
+ knotd_qdata_t *qdata, knotd_mod_t *mod)
+{
+ assert(pkt && qdata && mod);
+
+ queryacl_ctx_t *ctx = knotd_mod_ctx(mod);
+
+ // Continue only for regular queries.
+ if (qdata->type != KNOTD_QUERY_TYPE_NORMAL) {
+ return state;
+ }
+
+ if (ctx->allow_addr.count > 0) {
+ const struct sockaddr_storage *addr = knotd_qdata_remote_addr(qdata);
+ if (!knotd_conf_addr_range_match(&ctx->allow_addr, addr)) {
+ qdata->rcode = KNOT_RCODE_NOTAUTH;
+ return KNOTD_STATE_FAIL;
+ }
+ }
+
+ if (ctx->allow_iface.count > 0) {
+ struct sockaddr_storage buff;
+ const struct sockaddr_storage *addr = knotd_qdata_local_addr(qdata, &buff);
+ if (!knotd_conf_addr_range_match(&ctx->allow_iface, addr)) {
+ qdata->rcode = KNOT_RCODE_NOTAUTH;
+ return KNOTD_STATE_FAIL;
+ }
+ }
+
+ return state;
+}
+
+int queryacl_load(knotd_mod_t *mod)
+{
+ // Create module context.
+ queryacl_ctx_t *ctx = calloc(1, sizeof(queryacl_ctx_t));
+ if (ctx == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ ctx->allow_addr = knotd_conf_mod(mod, MOD_ADDRESS);
+ ctx->allow_iface = knotd_conf_mod(mod, MOD_INTERFACE);
+
+ knotd_mod_ctx_set(mod, ctx);
+
+ return knotd_mod_hook(mod, KNOTD_STAGE_BEGIN, queryacl_process);
+}
+
+void queryacl_unload(knotd_mod_t *mod)
+{
+ queryacl_ctx_t *ctx = knotd_mod_ctx(mod);
+ if (ctx != NULL) {
+ knotd_conf_free(&ctx->allow_addr);
+ knotd_conf_free(&ctx->allow_iface);
+ }
+ free(ctx);
+}
+
+KNOTD_MOD_API(queryacl, KNOTD_MOD_FLAG_SCOPE_ANY,
+ queryacl_load, queryacl_unload, queryacl_conf, NULL);
diff --git a/src/knot/modules/queryacl/queryacl.rst b/src/knot/modules/queryacl/queryacl.rst
new file mode 100644
index 0000000..1a402f6
--- /dev/null
+++ b/src/knot/modules/queryacl/queryacl.rst
@@ -0,0 +1,70 @@
+.. _mod-queryacl:
+
+``queryacl`` — Limit queries by remote address or target interface
+==================================================================
+
+This module provides a simple way to whitelist incoming queries
+according to the query's source address or target interface.
+It can be used e.g. to create a restricted-access subzone with delegations from the corresponding public zone.
+The module may be enabled both globally and per-zone.
+
+.. NOTE::
+ The module limits only regular queries. Notify, transfer and update are handled by :ref:`ACL<ACL>`.
+
+Example
+-------
+
+::
+
+ mod-queryacl:
+ - id: default
+ address: [192.0.2.73-192.0.2.90, 203.0.113.0/24]
+ interface: 198.51.100
+
+ zone:
+ - domain: example.com
+ module: mod-queryacl/default
+
+Module reference
+----------------
+
+::
+
+ mod-queryacl:
+ - id: STR
+ address: ADDR[/INT] | ADDR-ADDR ...
+ interface: ADDR[/INT] | ADDR-ADDR ...
+
+.. _mod-queryacl_id:
+
+id
+..
+
+A module identifier.
+
+.. _mod-queryacl_address:
+
+address
+.......
+
+An optional list of allowed ranges and/or subnets for query's source address.
+If the query's address does not fall into any
+of the configured ranges, NOTAUTH rcode is returned.
+
+*Default:* not set
+
+.. _mod-queryacl_interface:
+
+interface
+.........
+
+An optional list of allowed ranges and/or subnets for query's target interface.
+If the interface does not fall into any
+of the configured ranges, NOTAUTH rcode is returned. Note that every interface
+used has to be configured in :ref:`listen<server_listen>`.
+
+.. NOTE::
+ Don't use values *0.0.0.0* and *::0*. These values are redundant and don't
+ work as expected.
+
+*Default:* not set