[Openvpn-devel,v2,1/2] port-share: Normalize IPv4-mapped IPv6 addresses

Message ID b16cab79-188f-41a3-af32-f944a387400f@gmx.de
State New
Headers show
Series [Openvpn-devel,v2,1/2] port-share: Normalize IPv4-mapped IPv6 addresses | expand

Commit Message

corubba Dec. 16, 2024, 12:22 p.m. UTC
Before passing IPv4-mapped IPv6 addresses to the proxy journal,
translate them to plain IPv4 addresses. Whether the connection was
accepted by OpenVPN on a "dual stack" socket is of no importance to the
proxy receiver.

Signed-off-by: Corubba Smith <corubba@gmx.de>
---
 src/openvpn/ps.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

--
2.47.1

Comments

Gert Doering Dec. 25, 2024, 4:21 p.m. UTC | #1
Hi,

On Mon, Dec 16, 2024 at 01:22:38PM +0100, corubba via Openvpn-devel wrote:
> Before passing IPv4-mapped IPv6 addresses to the proxy journal,
> translate them to plain IPv4 addresses. Whether the connection was
> accepted by OpenVPN on a "dual stack" socket is of no importance to the
> proxy receiver.
> 
> Signed-off-by: Corubba Smith <corubba@gmx.de>

I'm fine with the idea, but I do not like the implementation with 
"yet another localized sockaddr manipulation function" - we already
have similar code in socket.c/setenv_sockaddr(), so maybe we need
to make this a more general thing.

print_openvpn_sockaddr() is just a wrapper around print_sockaddr_ex(),
which takes flags.  So we could introduce something like a PS_NO_V4MAPPED
(naming is hard :-) ) which would then do "this" inside print_sockaddr_ex().

It's not fully straightforward, though (it operates on a pointer passed
to it, so we'd need to have a local sockaddr_in for "unmapped v4" then).

Mmmmh, need to think more about this.

gert
Gert Doering Dec. 26, 2024, 1 p.m. UTC | #2
Hi,

On Wed, Dec 25, 2024 at 05:21:35PM +0100, Gert Doering wrote:
> I'm fine with the idea, but I do not like the implementation with 
> "yet another localized sockaddr manipulation function" - we already
> have similar code in socket.c/setenv_sockaddr(), so maybe we need
> to make this a more general thing.

I now see that it's not *that* easy, as transform_mapped_v4_sockaddr()
is also used by part 2/3 of the series... so maybe we'll just take 1/3
as it is, and see if we can overhaul the whole handling of v4-mapped
addresses in a more coordinated way later.

gert
corubba Dec. 26, 2024, 8:28 p.m. UTC | #3
Hi,

On 26.12.24 14:00, Gert Doering wrote:
> On Wed, Dec 25, 2024 at 05:21:35PM +0100, Gert Doering wrote:
>> I'm fine with the idea, but I do not like the implementation with
>> "yet another localized sockaddr manipulation function" - we already
>> have similar code in socket.c/setenv_sockaddr(), so maybe we need
>> to make this a more general thing.
>
> I now see that it's not *that* easy, as transform_mapped_v4_sockaddr()
> is also used by part 2/3 of the series... so maybe we'll just take 1/3
> as it is, and see if we can overhaul the whole handling of v4-mapped
> addresses in a more coordinated way later.

I actually had initially implemented it in socket.c, but reverted it to
a local and simpler implementation because I was sure to otherwise break
stuff with it. I dug it up again and refined it a bit, feel free to have
a look at the attached patch and form an opinion. But please consider it
still WIP, it is not intended as a v3 of the original patch.


Best regards
--
Corubba

Patch

diff --git a/src/openvpn/ps.c b/src/openvpn/ps.c
index 06bf91a8..36ea63b8 100644
--- a/src/openvpn/ps.c
+++ b/src/openvpn/ps.c
@@ -330,6 +330,22 @@  proxy_list_housekeeping(struct proxy_connection **list)
     }
 }

+/*
+ * In-place transformation of an openvpn_sockaddr with an IPv4-mapped IPv6
+ * address to one with a plain IPv4 address. No-op otherwise.
+ */
+static void
+transform_mapped_v4_sockaddr(struct openvpn_sockaddr *sock)
+{
+    if (sock->addr.sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sock->addr.in6.sin6_addr))
+    {
+        sock->addr.in4.sin_family = AF_INET;
+        /* sin_port and sin6_port are the same already */
+        memcpy(&sock->addr.in4.sin_addr, &sock->addr.in6.sin6_addr.s6_addr[12], 4);
+        memset(&sock->addr.in4 + 1, 0, sizeof(sock->addr) - sizeof(sock->addr.in4));
+    }
+}
+
 /*
  * Record IP/port of client in filesystem, so that server receiving
  * the proxy can determine true client origin.
@@ -349,6 +365,8 @@  journal_add(const char *journal_dir, struct proxy_connection *pc, struct proxy_c
     if (!getpeername(pc->sd, (struct sockaddr *) &from.addr.sa, &slen)
         && !getsockname(cp->sd, (struct sockaddr *) &to.addr.sa, &dlen))
     {
+        transform_mapped_v4_sockaddr(&from);
+        transform_mapped_v4_sockaddr(&to);
         const char *f = print_openvpn_sockaddr(&from, &gc);
         const char *t = print_openvpn_sockaddr(&to, &gc);
         fnlen =  strlen(journal_dir) + strlen(t) + 2;