]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/proxyv2: fix client TCP/TLS + merge state structs
authorOto Šťáva <oto.stava@nic.cz>
Wed, 31 Jul 2024 12:16:33 +0000 (14:16 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Wed, 7 Aug 2024 08:36:00 +0000 (10:36 +0200)
Firstly, this adds a missing assignment of `comm->proxy`, which would
cause the resolver not to know that a client asked via TCP/TLS, if the
proxy also asked via TCP/TLS.

Secondly, it merges `struct pl_proxyv2_sess_data` and
`struct pl_proxyv2_iter_data` into a single `struct pl_proxyv2_state`,
since they were practically the same. And it adds a bit of documentation
to the struct.

daemon/proxyv2.c
daemon/proxyv2.test/kresd_config.j2

index 31eeb624867744c2f27d886d79cb5b5f5d55a8e6..4bdd59132e5df6f5b794d50ae34c2c458ff8f38e 100644 (file)
@@ -310,10 +310,13 @@ static inline bool proxy_header_present(const void* buf, const ssize_t nread)
 }
 
 
-struct pl_proxyv2_dgram_iter_data {
+struct pl_proxyv2_state {
        struct protolayer_data h;
+       /** Storage for data parsed from PROXY header. */
        struct proxy_result proxy;
-       bool has_proxy;
+       /** Stream/TCP: Some data has already arrived and we are not expecting
+        * PROXY header anymore. */
+       bool had_data : 1;
 };
 
 static enum protolayer_iter_cb_result pl_proxyv2_dgram_unwrap(
@@ -326,7 +329,7 @@ static enum protolayer_iter_cb_result pl_proxyv2_dgram_unwrap(
        }
 
        struct session2 *s = ctx->session;
-       struct pl_proxyv2_dgram_iter_data *udp = iter_data;
+       struct pl_proxyv2_state *proxy_state = iter_data;
 
        char *data = ctx->payload.buffer.buf;
        ssize_t data_len = ctx->payload.buffer.len;
@@ -338,7 +341,7 @@ static enum protolayer_iter_cb_result pl_proxyv2_dgram_unwrap(
                        return protolayer_break(ctx, kr_error(EPERM));
                }
 
-               ssize_t trimmed = proxy_process_header(&udp->proxy, data, data_len);
+               ssize_t trimmed = proxy_process_header(&proxy_state->proxy, data, data_len);
                if (trimmed == KNOT_EMALF) {
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= ignoring malformed PROXYv2 UDP "
@@ -355,12 +358,10 @@ static enum protolayer_iter_cb_result pl_proxyv2_dgram_unwrap(
                        return protolayer_break(ctx, kr_error(EINVAL));
                }
 
-               if (udp->proxy.command == PROXY2_CMD_PROXY && udp->proxy.family != AF_UNSPEC) {
-                       udp->has_proxy = true;
-
-                       comm->src_addr = &udp->proxy.src_addr.ip;
-                       comm->dst_addr = &udp->proxy.dst_addr.ip;
-                       comm->proxy = &udp->proxy;
+               if (proxy_state->proxy.command == PROXY2_CMD_PROXY && proxy_state->proxy.family != AF_UNSPEC) {
+                       comm->src_addr = &proxy_state->proxy.src_addr.ip;
+                       comm->dst_addr = &proxy_state->proxy.dst_addr.ip;
+                       comm->proxy = &proxy_state->proxy;
 
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= UDP query from '%s'\n",
@@ -377,19 +378,11 @@ static enum protolayer_iter_cb_result pl_proxyv2_dgram_unwrap(
        return protolayer_continue(ctx);
 }
 
-
-struct pl_proxyv2_stream_sess_data {
-       struct protolayer_data h;
-       struct proxy_result proxy;
-       bool had_data : 1;
-       bool has_proxy : 1;
-};
-
 static enum protolayer_iter_cb_result pl_proxyv2_stream_unwrap(
                void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
 {
        struct session2 *s = ctx->session;
-       struct pl_proxyv2_stream_sess_data *tcp = sess_data;
+       struct pl_proxyv2_state *proxy_state = sess_data;
        struct sockaddr *peer = session2_get_peer(s);
 
        if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)) {
@@ -400,7 +393,7 @@ static enum protolayer_iter_cb_result pl_proxyv2_stream_unwrap(
        char *data = wire_buf_data(ctx->payload.wire_buf); /* layer's or session's wirebuf */
        ssize_t data_len = wire_buf_data_length(ctx->payload.wire_buf);
        struct comm_info *comm = ctx->comm;
-       if (!s->outgoing && !tcp->had_data && proxy_header_present(data, data_len)) {
+       if (!s->outgoing && !proxy_state->had_data && proxy_header_present(data, data_len)) {
                if (!proxy_allowed(comm->src_addr)) {
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= connection to '%s': PROXYv2 not allowed "
@@ -411,7 +404,7 @@ static enum protolayer_iter_cb_result pl_proxyv2_stream_unwrap(
                        return protolayer_break(ctx, kr_error(ECONNRESET));
                }
 
-               ssize_t trimmed = proxy_process_header(&tcp->proxy, data, data_len);
+               ssize_t trimmed = proxy_process_header(&proxy_state->proxy, data, data_len);
                if (trimmed < 0) {
                        if (kr_log_is_debug(IO, NULL)) {
                                if (trimmed == KNOT_EMALF) {
@@ -431,9 +424,10 @@ static enum protolayer_iter_cb_result pl_proxyv2_stream_unwrap(
                        return protolayer_break(ctx, kr_error(ECONNRESET));
                }
 
-               if (tcp->proxy.command != PROXY2_CMD_LOCAL && tcp->proxy.family != AF_UNSPEC) {
-                       comm->src_addr = &tcp->proxy.src_addr.ip;
-                       comm->dst_addr = &tcp->proxy.dst_addr.ip;
+               if (proxy_state->proxy.command != PROXY2_CMD_LOCAL && proxy_state->proxy.family != AF_UNSPEC) {
+                       comm->src_addr = &proxy_state->proxy.src_addr.ip;
+                       comm->dst_addr = &proxy_state->proxy.dst_addr.ip;
+                       comm->proxy = &proxy_state->proxy;
 
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= TCP stream from '%s'\n",
@@ -446,7 +440,7 @@ static enum protolayer_iter_cb_result pl_proxyv2_stream_unwrap(
                wire_buf_trim(ctx->payload.wire_buf, trimmed);
        }
 
-       tcp->had_data = true;
+       proxy_state->had_data = true;
        return protolayer_continue(ctx);
 }
 
@@ -454,12 +448,12 @@ __attribute__((constructor))
 static void proxy_protolayers_init(void)
 {
        protolayer_globals[PROTOLAYER_TYPE_PROXYV2_DGRAM] = (struct protolayer_globals){
-               .iter_size = sizeof(struct pl_proxyv2_dgram_iter_data),
+               .iter_size = sizeof(struct pl_proxyv2_state),
                .unwrap = pl_proxyv2_dgram_unwrap,
        };
 
        protolayer_globals[PROTOLAYER_TYPE_PROXYV2_STREAM] = (struct protolayer_globals){
-               .sess_size = sizeof(struct pl_proxyv2_stream_sess_data),
+               .sess_size = sizeof(struct pl_proxyv2_state),
                .unwrap = pl_proxyv2_stream_unwrap,
        };
 }
index e7cbf63a8022704087803fd12df45a4215e46846..8023d4095ac06ef46348643d82f5925e901cb409 100644 (file)
@@ -2,7 +2,6 @@
 {% raw %}
 modules.load('view < policy')
 view:addr("127.127.0.0", policy.suffix(policy.DENY_MSG("addr 127.127.0.0 matched com"),{"\3com\0"}))
--- policy.add(policy.all(policy.FORWARD('1.2.3.4')))
 
 -- make sure DNSSEC is turned off for tests
 trust_anchors.remove('.')