From b5fa236f5a14fea42450f7575c57c28512f3d060 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Oto=20=C5=A0=C5=A5=C3=A1va?= Date: Wed, 31 Jul 2024 14:16:33 +0200 Subject: [PATCH] daemon/proxyv2: fix client TCP/TLS + merge state structs 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 | 48 +++++++++++++---------------- daemon/proxyv2.test/kresd_config.j2 | 1 - 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/daemon/proxyv2.c b/daemon/proxyv2.c index 31eeb6248..4bdd59132 100644 --- a/daemon/proxyv2.c +++ b/daemon/proxyv2.c @@ -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, }; } diff --git a/daemon/proxyv2.test/kresd_config.j2 b/daemon/proxyv2.test/kresd_config.j2 index e7cbf63a8..8023d4095 100644 --- a/daemon/proxyv2.test/kresd_config.j2 +++ b/daemon/proxyv2.test/kresd_config.j2 @@ -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('.') -- 2.47.3