Probable bug in parse_proxy_proto_header_v2() when using listen-proxy-proto + PROXY v2 + IPv6

We likely found a functional correctness issue in upstream ocserv 1.4.2, in worker-proxyproto.c (line 459), function parse_proxy_proto_header_v2() (TCP6 branch).

In the IPv6 path, sin6_family for our_addr is assigned before sa is redirected to &ws->our_addr. As a result, ws->our_addr may remain AF_UNSPEC while our_addr_len is set to sizeof(struct sockaddr_in6).

This appears only in deployments that use:

  • listen-proxy-proto
  • PROXY protocol v2
  • IPv6 client/frontend addressing

Observed/expected impact:

  • This affects destination/local-side metadata (our_addr, usually frontend VIP/proxy destination), not the client remote IP.
  • occtl show user *username may still show client ip correctly, but local-side address fields (local_dev_ip / Local Device IP) can become empty or incorrect.
  • Script environment field IP_REAL_LOCAL may also be missing/incorrect.

Current code (upstream 1.4.2):

memset(&ws->our_addr, 0, sizeof(ws->our_addr));
sa->sin6_family = AF_INET6;
sa = (void *)&ws->our_addr;
memcpy(&sa->sin6_addr, p + 16, 16);
memcpy(&sa->sin6_port, p + 34, 2);
ws->our_addr_len = sizeof(struct sockaddr_in6);

Suggested fix:

memset(&ws->our_addr, 0, sizeof(ws->our_addr));
sa = (void *)&ws->our_addr;
sa->sin6_family = AF_INET6;
memcpy(&sa->sin6_addr, p + 16, 16);
memcpy(&sa->sin6_port, p + 34, 2);
ws->our_addr_len = sizeof(struct sockaddr_in6);

Note: We have not practically validated this on a live proxy-fronted setup yet, because we currently do not have a test stand with a TLS proxy in front of ocserv.

Edited by Dimitri Papadopoulos Orfanos