summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Knot.files4
-rw-r--r--distro/pkg/deb/copyright5
-rw-r--r--doc/man/knot.conf.5in16
-rw-r--r--doc/reference.rst16
-rw-r--r--src/contrib/Makefile.inc2
-rw-r--r--src/contrib/proxyv2/proxyv2.c (renamed from src/knot/query/proxyv2.c)124
-rw-r--r--src/contrib/proxyv2/proxyv2.h24
-rw-r--r--src/knot/Makefile.inc8
-rw-r--r--src/knot/conf/base.c3
-rw-r--r--src/knot/conf/base.h1
-rw-r--r--src/knot/conf/schema.c1
-rw-r--r--src/knot/conf/schema.h1
-rw-r--r--src/knot/include/module.h1
-rw-r--r--src/knot/query/proxyv2.h16
-rw-r--r--src/knot/server/proxyv2.c76
-rw-r--r--src/knot/server/proxyv2.h23
-rw-r--r--src/knot/server/udp-handler.c23
-rw-r--r--src/knot/server/xdp-handler.c9
18 files changed, 225 insertions, 128 deletions
diff --git a/Knot.files b/Knot.files
index c5d001513..3484fc8d5 100644
--- a/Knot.files
+++ b/Knot.files
@@ -161,6 +161,8 @@ src/contrib/openbsd/strlcat.h
src/contrib/openbsd/strlcpy.c
src/contrib/openbsd/strlcpy.h
src/contrib/os.h
+src/contrib/proxyv2/proxyv2.c
+src/contrib/proxyv2/proxyv2.h
src/contrib/qp-trie/trie.c
src/contrib/qp-trie/trie.h
src/contrib/semaphore.c
@@ -342,6 +344,8 @@ src/knot/query/requestor.c
src/knot/query/requestor.h
src/knot/server/dthreads.c
src/knot/server/dthreads.h
+src/knot/server/proxyv2.c
+src/knot/server/proxyv2.h
src/knot/server/server.c
src/knot/server/server.h
src/knot/server/tcp-handler.c
diff --git a/distro/pkg/deb/copyright b/distro/pkg/deb/copyright
index 61ec7e81b..7e0f90f92 100644
--- a/distro/pkg/deb/copyright
+++ b/distro/pkg/deb/copyright
@@ -60,6 +60,11 @@ Files: src/contrib/openbsd/strl*
Copyright: 1998 Todd C. Miller <Todd.Miller@courtesan.com>
License: 0BSD
+Files: src/contrib/proxyv2/*
+Copyright: 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+ 2021 Fastly, Inc.
+License: GPL-3+
+
Files: src/contrib/qp-trie/*
Copyright: 2011-2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2018 Tony Finch <dot@dotat.at>
diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in
index d360292da..b154b4d45 100644
--- a/doc/man/knot.conf.5in
+++ b/doc/man/knot.conf.5in
@@ -201,6 +201,7 @@ server:
edns\-client\-subnet: BOOL
answer\-rotation: BOOL
automatic\-acl: BOOL
+ proxy\-allowlist: ADDR[/INT] | ADDR\-ADDR ...
dbus\-event: none | running | zone\-updated | ksk\-submission | dnssec\-invalid ...
listen: ADDR[@INT] ...
.ft P
@@ -443,6 +444,21 @@ If enabled, \fI\%automatic ACL\fP setting of
configured remotes is considered when evaluating authorized operations.
.sp
\fIDefault:\fP off
+.SS proxy\-allowlist
+.sp
+An ordered list of IP addresses, network subnets, or network ranges
+which are allowed as a source address of proxied DNS traffic over UDP.
+The supported proxy protocol is
+\fI\%haproxy PROXY v2\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+TCP is not supported.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
.SS dbus\-event
.sp
Specification of server or zone states which emit a D\-Bus signal on the system
diff --git a/doc/reference.rst b/doc/reference.rst
index 9dacdcb60..fdd84717e 100644
--- a/doc/reference.rst
+++ b/doc/reference.rst
@@ -152,6 +152,7 @@ General options related to the server.
edns-client-subnet: BOOL
answer-rotation: BOOL
automatic-acl: BOOL
+ proxy-allowlist: ADDR[/INT] | ADDR-ADDR ...
dbus-event: none | running | zone-updated | ksk-submission | dnssec-invalid ...
listen: ADDR[@INT] ...
@@ -476,6 +477,21 @@ configured remotes is considered when evaluating authorized operations.
*Default:* off
+.. _server_proxy-allowlist:
+
+proxy-allowlist
+---------------
+
+An ordered list of IP addresses, network subnets, or network ranges
+which are allowed as a source address of proxied DNS traffic over UDP.
+The supported proxy protocol is
+`haproxy PROXY v2 <https://www.haproxy.org/download/2.5/doc/proxy-protocol.txt>`_.
+
+.. NOTE::
+ TCP is not supported.
+
+*Default:* not set
+
.. _server_dbus-event:
dbus-event
diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc
index c0dc0fc7d..6af6e5c29 100644
--- a/src/contrib/Makefile.inc
+++ b/src/contrib/Makefile.inc
@@ -66,6 +66,8 @@ libcontrib_la_SOURCES = \
contrib/openbsd/strlcat.h \
contrib/openbsd/strlcpy.c \
contrib/openbsd/strlcpy.h \
+ contrib/proxyv2/proxyv2.c \
+ contrib/proxyv2/proxyv2.h \
contrib/ucw/array-sort.h \
contrib/ucw/binsearch.h \
contrib/ucw/heap.c \
diff --git a/src/knot/query/proxyv2.c b/src/contrib/proxyv2/proxyv2.c
index 7c50df2c9..fb3e925e9 100644
--- a/src/knot/query/proxyv2.c
+++ b/src/contrib/proxyv2/proxyv2.c
@@ -14,10 +14,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include "knot/query/proxyv2.h"
-
#include <arpa/inet.h>
#include <stdint.h>
+#include <string.h>
+
+#include "contrib/proxyv2/proxyv2.h"
+#include "contrib/sockaddr.h"
+#include "libknot/errcode.h"
/*
* Minimal implementation of the haproxy PROXY v2 protocol.
@@ -61,7 +64,7 @@ struct proxyv2_hdr {
/*
* The number of PROXY v2 payload bytes following this header to skip
- * to reach the proxied packet (i.e., start of the original DNS mesage).
+ * to reach the proxied packet (i.e., start of the original DNS message).
*/
uint16_t len;
};
@@ -99,36 +102,9 @@ _Static_assert(sizeof(struct proxyv2_addr_ipv6) == 36,
"struct proxyv2_addr_ipv6 is correct size");
#endif
-#define S_ADDR_IS_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
-
-int proxyv2_decapsulate(void *base,
- size_t len_base,
- knot_pkt_t **query,
- knotd_qdata_params_t *params,
- struct sockaddr_storage *client,
- knot_mm_t *mm)
+int proxyv2_header_offset(void *base, size_t len_base)
{
/*
- * Check if the query was sent from an IP address authorized to send
- * proxied DNS traffic. This is a hardcoded ACL check for queries
- * originated from 127.0.0.0/8.
- *
- * XXX: This should be a real ACL check.
- */
- int ret = KNOT_EDENIED;
- const struct sockaddr_storage *sock = params->remote;
- if (sock != NULL && sock->ss_family == AF_INET) {
- const struct sockaddr_in *sock4 = (const struct sockaddr_in *) sock;
- if (S_ADDR_IS_LOOPBACK(ntohl(sock4->sin_addr.s_addr))) {
- ret = KNOT_EOK;
- }
- }
- if (ret != KNOT_EOK) {
- /* Failure. */
- return ret;
- }
-
- /*
* Check that 'base' has enough bytes to read the PROXY v2 signature
* and header, and if so whether the PROXY v2 signature is present.
*/
@@ -140,8 +116,7 @@ int proxyv2_decapsulate(void *base,
}
/* Read the PROXY v2 header. */
- struct proxyv2_hdr hdr;
- memcpy(&hdr, base + sizeof(PROXYV2_SIG), sizeof(hdr));
+ struct proxyv2_hdr *hdr = base + sizeof(PROXYV2_SIG);
/*
* Check that this is a version 2, command "PROXY" payload.
@@ -149,7 +124,7 @@ int proxyv2_decapsulate(void *base,
* XXX: The PROXY v2 spec mandates support for the "LOCAL" command
* (byte 0x20).
*/
- if (hdr.ver_cmd != 0x21) {
+ if (hdr->ver_cmd != 0x21) {
/* Failure. */
return KNOT_EMALF;
}
@@ -160,49 +135,32 @@ int proxyv2_decapsulate(void *base,
* PROXY v2 header, and the bytes of variable length PROXY v2 data
* following the PROXY v2 header.
*/
- const size_t offset_dns =
- sizeof(PROXYV2_SIG) +
- sizeof(struct proxyv2_hdr) +
- ntohs(hdr.len);
-
- /*
- * Check if the calculated offset of the original DNS message is
- * actually inside the packet received on the wire, and if so, parse
- * the real DNS query message.
- */
+ const size_t offset_dns = sizeof(PROXYV2_SIG) +
+ sizeof(struct proxyv2_hdr) + ntohs(hdr->len);
if (offset_dns < len_base) {
- /* Free the old, misparsed query message object. */
- knot_pkt_free(*query);
-
- /*
- * Re-parse the query message using the data in the
- * packet following the PROXY v2 payload.
- */
- *query = knot_pkt_new(base + offset_dns,
- len_base - offset_dns,
- mm);
- ret = knot_pkt_parse(*query, 0);
- if (ret != KNOT_EOK) {
- /* Failure. */
- return ret;
- }
+ return offset_dns;
}
+ return KNOT_EMALF;
+}
+
+int proxyv2_addr_store(void *base, size_t len_base, struct sockaddr_storage *ss)
+{
/*
* Calculate the offset of the PROXY v2 address block. This is the data
* immediately following the PROXY v2 header.
*/
- const size_t offset_proxy_addr =
- sizeof(PROXYV2_SIG) + sizeof(struct proxyv2_hdr);
+ const size_t offset_proxy_addr = sizeof(PROXYV2_SIG) +
+ sizeof(struct proxyv2_hdr);
+ struct proxyv2_hdr *hdr = base + sizeof(PROXYV2_SIG);
/*
* Handle proxied UDP-over-IPv4 and UDP-over-IPv6 packets.
- *
- * XXX: What about TCP?
*/
- if (hdr.fam_addr == 0x12) {
+ //TODO What about TCP?
+ if (hdr->fam_addr == 0x12) {
/* This is a proxied UDP-over-IPv4 packet. */
- struct proxyv2_addr_ipv4 addr;
+ struct proxyv2_addr_ipv4 *addr;
/*
* Check that the packet is large enough to contain the IPv4
@@ -210,29 +168,21 @@ int proxyv2_decapsulate(void *base,
*/
if (offset_proxy_addr + sizeof(addr) < len_base) {
/* Read the PROXY v2 address block. */
- memcpy(&addr, base + offset_proxy_addr, sizeof(addr));
+ addr = base + offset_proxy_addr;
/* Copy the client's IPv4 address to the caller. */
- sockaddr_set_raw(client,
- AF_INET,
- &addr.src_addr[0],
- sizeof(addr.src_addr));
+ sockaddr_set_raw(ss, AF_INET, addr->src_addr,
+ sizeof(addr->src_addr));
/* Copy the client's port to the caller. */
- sockaddr_port_set(client, ntohs(addr.src_port));
-
- /* Save the address of the proxy. */
- params->proxy = params->remote;
-
- /* Expose the address of the proxied client. */
- params->remote = client;
+ sockaddr_port_set(ss, ntohs(addr->src_port));
/* Success. */
return KNOT_EOK;
}
- } else if (hdr.fam_addr == 0x22) {
+ } else if (hdr->fam_addr == 0x22) {
/* This is a proxied UDP-over-IPv6 packet. */
- struct proxyv2_addr_ipv6 addr;
+ struct proxyv2_addr_ipv6 *addr;
/*
* Check that the packet is large enough to contain the IPv6
@@ -240,22 +190,14 @@ int proxyv2_decapsulate(void *base,
*/
if (offset_proxy_addr + sizeof(addr) < len_base) {
/* Read the PROXY v2 address block. */
- memcpy(&addr, base + offset_proxy_addr, sizeof(addr));
+ addr = base + offset_proxy_addr;
/* Copy the client's IPv6 address to the caller. */
- sockaddr_set_raw(client,
- AF_INET6,
- &addr.src_addr[0],
- sizeof(addr.src_addr));
+ sockaddr_set_raw(ss, AF_INET6, addr->src_addr,
+ sizeof(addr->src_addr));
/* Copy the client's port to the caller. */
- sockaddr_port_set(client, ntohs(addr.src_port));
-
- /* Save the address of the proxy. */
- params->proxy = params->remote;
-
- /* Expose the address of the proxied client. */
- params->remote = client;
+ sockaddr_port_set(ss, ntohs(addr->src_port));
/* Success. */
return KNOT_EOK;
diff --git a/src/contrib/proxyv2/proxyv2.h b/src/contrib/proxyv2/proxyv2.h
new file mode 100644
index 000000000..677825ec0
--- /dev/null
+++ b/src/contrib/proxyv2/proxyv2.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 2022 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/>.
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <sys/socket.h>
+
+int proxyv2_header_offset(void *base, size_t len_base);
+
+int proxyv2_addr_store(void *base, size_t len_base, struct sockaddr_storage *ss);
diff --git a/src/knot/Makefile.inc b/src/knot/Makefile.inc
index f86d62371..531de466e 100644
--- a/src/knot/Makefile.inc
+++ b/src/knot/Makefile.inc
@@ -115,8 +115,6 @@ libknotd_la_SOURCES = \
knot/query/capture.c \
knot/query/capture.h \
knot/query/layer.h \
- knot/query/proxyv2.c \
- knot/query/proxyv2.h \
knot/query/query.c \
knot/query/query.h \
knot/query/requestor.c \
@@ -135,8 +133,6 @@ libknotd_la_SOURCES = \
knot/common/systemd.h \
knot/common/unreachable.c \
knot/common/unreachable.h \
- knot/server/dthreads.c \
- knot/server/dthreads.h \
knot/journal/journal_basic.c \
knot/journal/journal_basic.h \
knot/journal/journal_metadata.c \
@@ -149,6 +145,10 @@ libknotd_la_SOURCES = \
knot/journal/knot_lmdb.h \
knot/journal/serialization.c \
knot/journal/serialization.h \
+ knot/server/dthreads.c \
+ knot/server/dthreads.h \
+ knot/server/proxyv2.c \
+ knot/server/proxyv2.h \
knot/server/server.c \
knot/server/server.h \
knot/server/tcp-handler.c \
diff --git a/src/knot/conf/base.c b/src/knot/conf/base.c
index f46386920..40997d1e1 100644
--- a/src/knot/conf/base.c
+++ b/src/knot/conf/base.c
@@ -240,6 +240,9 @@ static void init_cache(
val = conf_get(conf, C_SRV, C_AUTO_ACL);
conf->cache.srv_auto_acl = conf_bool(&val);
+
+ val = conf_get(conf, C_SRV, C_PROXY_ALLOWLIST);
+ conf->cache.srv_proxy_enabled = (conf_val_count(&val) > 0);
}
int conf_new(
diff --git a/src/knot/conf/base.h b/src/knot/conf/base.h
index 81b54a5b1..0d32c1bb2 100644
--- a/src/knot/conf/base.h
+++ b/src/knot/conf/base.h
@@ -147,6 +147,7 @@ typedef struct {
bool srv_ecs;
bool srv_ans_rotate;
bool srv_auto_acl;
+ bool srv_proxy_enabled;
} cache;
/*! List of dynamically loaded modules. */
diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c
index ae4cf3222..5f309ff27 100644
--- a/src/knot/conf/schema.c
+++ b/src/knot/conf/schema.c
@@ -236,6 +236,7 @@ static const yp_item_t desc_server[] = {
{ C_ECS, YP_TBOOL, YP_VNONE },
{ C_ANS_ROTATION, YP_TBOOL, YP_VNONE },
{ C_AUTO_ACL, YP_TBOOL, YP_VNONE },
+ { C_PROXY_ALLOWLIST, YP_TNET, YP_VNONE, YP_FMULTI},
{ C_DBUS_EVENT, YP_TOPT, YP_VOPT = { dbus_events, DBUS_EVENT_NONE }, YP_FMULTI },
{ C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI, { check_listen } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h
index 55fb9ea35..3c40594d0 100644
--- a/src/knot/conf/schema.h
+++ b/src/knot/conf/schema.h
@@ -97,6 +97,7 @@
#define C_PIDFILE "\x07""pidfile"
#define C_POLICY "\x06""policy"
#define C_PROPAG_DELAY "\x11""propagation-delay"
+#define C_PROXY_ALLOWLIST "\x0F""proxy-allowlist"
#define C_REFRESH_MAX_INTERVAL "\x14""refresh-max-interval"
#define C_REFRESH_MIN_INTERVAL "\x14""refresh-min-interval"
#define C_REPRO_SIGNING "\x14""reproducible-signing"
diff --git a/src/knot/include/module.h b/src/knot/include/module.h
index 54fd4dab6..423fa7d28 100644
--- a/src/knot/include/module.h
+++ b/src/knot/include/module.h
@@ -400,7 +400,6 @@ typedef enum {
typedef struct {
knotd_query_flag_t flags; /*!< Current query flags. */
const struct sockaddr_storage *remote; /*!< Current remote address. */
- const struct sockaddr_storage *proxy; /*!< Current proxy address. */
int socket; /*!< Current network socket. */
unsigned thread_id; /*!< Current thread id. */
void *server; /*!< Server object private item. */
diff --git a/src/knot/query/proxyv2.h b/src/knot/query/proxyv2.h
deleted file mode 100644
index 62a5597a9..000000000
--- a/src/knot/query/proxyv2.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include <sys/socket.h>
-#include <stddef.h>
-
-#include "libknot/mm_ctx.h"
-#include "libknot/packet/pkt.h"
-#include "knot/include/module.h"
-#include "contrib/sockaddr.h"
-
-int proxyv2_decapsulate(void *base,
- size_t len_base,
- knot_pkt_t **query,
- knotd_qdata_params_t *params,
- struct sockaddr_storage *client,
- knot_mm_t *mm);
diff --git a/src/knot/server/proxyv2.c b/src/knot/server/proxyv2.c
new file mode 100644
index 000000000..1fc2c5adb
--- /dev/null
+++ b/src/knot/server/proxyv2.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2022 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/server/proxyv2.h"
+
+#include "contrib/proxyv2/proxyv2.h"
+#include "knot/conf/conf.h"
+
+int proxyv2_header_strip(knot_pkt_t **query,
+ const struct sockaddr_storage *remote,
+ struct sockaddr_storage *new_remote)
+{
+ conf_t *pconf = conf();
+ if (!pconf->cache.srv_proxy_enabled) {
+ return KNOT_EDENIED;
+ }
+
+ uint8_t *pkt = (*query)->wire;
+ size_t pkt_len = (*query)->max_size;
+
+ int offset = proxyv2_header_offset(pkt, pkt_len);
+ if (offset <= 0) {
+ return KNOT_EMALF;
+ }
+
+ /*
+ * Check if the query was sent from an IP address authorized to send
+ * proxied DNS traffic.
+ */
+ conf_val_t whitelist_val = conf_get(pconf, C_SRV, C_PROXY_ALLOWLIST);
+ if (!conf_addr_range_match(&whitelist_val, remote)) {
+ return KNOT_EDENIED;
+ }
+
+ /*
+ * Re-parse the query message using the data in the
+ * packet following the PROXY v2 payload.
+ */
+ knot_pkt_t *q = knot_pkt_new(pkt + offset, pkt_len - offset, &(*query)->mm);
+
+ /*
+ * Check if the calculated offset of the original DNS message is
+ * actually inside the packet received on the wire, and if so, parse
+ * the real DNS query message.
+ */
+ int ret = knot_pkt_parse(q, 0);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ /*
+ * Store the provided remote address.
+ */
+ ret = proxyv2_addr_store(pkt, pkt_len, new_remote);
+ if (ret != KNOT_EOK && q->parsed > 0) {
+ return ret;
+ }
+
+ knot_pkt_free(*query);
+ *query = q;
+
+ return KNOT_EOK;
+}
diff --git a/src/knot/server/proxyv2.h b/src/knot/server/proxyv2.h
new file mode 100644
index 000000000..5cb12512c
--- /dev/null
+++ b/src/knot/server/proxyv2.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2022 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/>.
+ */
+
+#pragma once
+
+#include "libknot/packet/pkt.h"
+
+int proxyv2_header_strip(knot_pkt_t **query,
+ const struct sockaddr_storage *remote,
+ struct sockaddr_storage *new_remote);
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 933064004..f5d8a7e41 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2022 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
@@ -37,7 +37,7 @@
#include "knot/common/fdset.h"
#include "knot/nameserver/process_query.h"
#include "knot/query/layer.h"
-#include "knot/query/proxyv2.h"
+#include "knot/server/proxyv2.h"
#include "knot/server/server.h"
#include "knot/server/udp-handler.h"
#include "knot/server/xdp-handler.h"
@@ -85,19 +85,12 @@ static void udp_handle(udp_context_t *udp, int fd, struct sockaddr_storage *ss,
/* Input packet. */
int ret = knot_pkt_parse(query, 0);
- if (ret != KNOT_EOK && query->parsed > 0) { // parsing failed (e.g. 2x OPT)
- /*
- * DNS parsing failed, try re-parsing with a PROXY v2 header.
- * XXX: This behavior should probably be controlled by a config
- * option.
- */
- ret = proxyv2_decapsulate(rx->iov_base, rx->iov_len,
- &query, &params, &proxied_remote,
- udp->layer.mm);
-
- if (ret != KNOT_EOK && query->parsed > 0) {
- // artificially decreasing "parsed" leads to FORMERR
- query->parsed--;
+ if (ret != KNOT_EOK && query->parsed > 0) {
+ ret = proxyv2_header_strip(&query, params.remote, &proxied_remote);
+ if (ret == KNOT_EOK) {
+ params.remote = &proxied_remote;
+ } else {
+ query->parsed--; // artificially decreasing "parsed" leads to FORMERR
}
}
knot_layer_consume(&udp->layer, query);
diff --git a/src/knot/server/xdp-handler.c b/src/knot/server/xdp-handler.c
index 05acbc5b9..29e085373 100644
--- a/src/knot/server/xdp-handler.c
+++ b/src/knot/server/xdp-handler.c
@@ -22,6 +22,7 @@
#include "knot/server/xdp-handler.h"
#include "knot/common/log.h"
+#include "knot/server/proxyv2.h"
#include "knot/server/server.h"
#include "contrib/sockaddr.h"
#include "contrib/time.h"
@@ -136,13 +137,19 @@ static void handle_init(knotd_qdata_params_t *params, knot_layer_t *layer,
KNOTD_QUERY_FLAG_NO_IXFR |
KNOTD_QUERY_FLAG_LIMIT_SIZE;
}
+ struct sockaddr_storage proxied_remote;
knot_layer_begin(layer, params);
knot_pkt_t *query = knot_pkt_new(payload->iov_base, payload->iov_len, layer->mm);
int ret = knot_pkt_parse(query, 0);
if (ret != KNOT_EOK && query->parsed > 0) { // parsing failed (e.g. 2x OPT)
- query->parsed--; // artificially decreasing "parsed" leads to FORMERR
+ ret = proxyv2_header_strip(&query, params->remote, &proxied_remote);
+ if (ret == KNOT_EOK) {
+ params->remote = &proxied_remote;
+ } else {
+ query->parsed--; // artificially decreasing "parsed" leads to FORMERR
+ }
}
knot_layer_consume(layer, query);
}