Skip to content

MINOR: gate: add accept-proxy option for the listener binds - #29

Open
loliee wants to merge 1 commit into
haproxytech:devfrom
mediapart:accept-proxy-dev
Open

MINOR: gate: add accept-proxy option for the listener binds#29
loliee wants to merge 1 commit into
haproxytech:devfrom
mediapart:accept-proxy-dev

Conversation

@loliee

@loliee loliee commented Sep 3, 2026

Copy link
Copy Markdown

This is the patch I mentioned in #28. Behind a load balancer that proxies
the TCP connection (Octavia on OVHcloud in our case), HAProxy only sees the
load balancer's address, and the PROXY protocol that fixes it needs
accept-proxy on the binds, which the controller never sets.

Description

This PR add a new controller option, off by default, done like the existing ones in
k8s/gate/options:

  • opt.AcceptProxy() sets HaproxyParams.AcceptProxy
  • the hug binary exposes it as --accept-proxy, wired like --disable-ipv4,
    so it can be passed with controller.extraArgs in the chart
  • bindParams() carries it into models.BindParams.AcceptProxy, which
    client-native already serializes as accept-proxy
  • a unit test next to frontends_test.go, and documentation/controller-options.*
    regenerated

Tests

  • go test ./k8s/gate/haproxy/ -run TestBindParamsAcceptProxy passes,
    task format, task generate and task lint leave the tree clean
  • On OVHcloud Managed Kubernetes, with loadbalancer.openstack.org/proxy-protocol: "v2"
    on the Service and --accept-proxy in controller.extraArgs: the generated
    haproxy.cfg shows accept-proxy on the hug_http_80 and hug_https_443
    binds, and %ci in the access log is the real client IP, both for external
    clients and for connections that hairpin through the load balancer from
    inside the cluster
  • Without the flag the same annotation makes every HTTPS connection fail on the
    header bytes, and without the annotation the flag makes every connection get
    rejected, as expected
  • A tcpSocket readiness probe keeps working: a connection closed without data
    is not a PROXY protocol error, and option dontlognull keeps it out of the logs

Behind a load balancer that proxies the TCP connection, HAProxy sees the
load balancer's address as the client, whatever the Service's external
traffic policy says. Such load balancers hand the real address over with
the PROXY protocol, which needs accept-proxy on the bind, and the
controller only ever sets ssl and crt-list on its binds.

Add the --accept-proxy controller flag, off by default. When set, every
bind of a frontend generated from a Gateway listener gets accept-proxy:
HTTP, HTTPS and TLS passthrough alike, since they all sit behind the
same load balancer. The stats frontend is left alone: probes and
scrapers reach the pod directly, without the header.

A global flag rather than a per-Gateway setting: whether the header is
sent is a property of the load balancer in front of the controller's
Service, shared by every listener published on it, and the Gateway API
has no standard field for it. Cilium exposes it the same way; others
use a policy resource of their own.

The unit test covers the three protocol categories with the flag on and
off; the options documentation is regenerated.

Signed-off-by: Maxime Loliée <maxime.loliee@mediapart.fr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant