From 0e157d748ac45b876772f4e8db95831d8c15e6d9 Mon Sep 17 00:00:00 2001 From: Philipp Kolberg Date: Thu, 27 Feb 2025 00:44:38 +0100 Subject: [PATCH 1/2] MINOR: refactor quic configuration --- pkg/handler/quic.go | 170 +++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/pkg/handler/quic.go b/pkg/handler/quic.go index 01322cc5..0d0fb939 100644 --- a/pkg/handler/quic.go +++ b/pkg/handler/quic.go @@ -29,82 +29,101 @@ type Quic struct { IPv6 bool } -func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) { - var errs utils.Errors - defer func() { - err = errs.Result() - }() - var bindv4Present, bindv6Present bool - binds, errBindsGet := h.FrontendBindsGet(h.FrontHTTPS) - if errBindsGet != nil { - errs.Add(errBindsGet) +func (q *Quic) enableQuic(h haproxy.HAProxy) (err error) { + var binds []models.Bind + var bindIPv4Exists, bindIPv6Exists bool + + err = q.altSvcRule(h) + if err != nil { return } - for _, bind := range binds { - bindv4Present = bindv4Present || bind.Name == QUIC4BIND - bindv6Present = bindv6Present || bind.Name == QUIC6BIND + existingBinds, err := h.FrontendBindsGet(h.FrontHTTPS) + if err != nil { + return } - ipv4Func := func() { - if bindv4Present { - return + if q.IPv4 || q.IPv6 { + for _, existingBind := range existingBinds { + if existingBind.Name == QUIC4BIND { + bindIPv4Exists = true + } + if existingBind.Name == QUIC6BIND { + bindIPv6Exists = true + } } + } - errFrontendBindCreate := h.FrontendBindCreate(h.FrontHTTPS, models.Bind{ - Address: func() (addr string) { - addr = "quic4@" + q.AddrIPv4 - return - }(), - Port: utils.PtrInt64(q.QuicBindPort), + addBind := func(addr string, bindName string, v4v6 bool) { + binds = append(binds, models.Bind{ + Address: addr, + Port: utils.PtrInt64(q.QuicBindPort), BindParams: models.BindParams{ - Name: QUIC4BIND, + Name: bindName, Ssl: true, SslCertificate: q.CertDir, Alpn: "h3", + V4v6: v4v6, }, }) - errs.Add(errFrontendBindCreate) - instance.ReloadIf(errFrontendBindCreate == nil, "quic binding v4 created") } - ipv6Func := func() { - if bindv6Present { - return - } - errFrontendBindCreate := h.FrontendBindCreate(h.FrontHTTPS, models.Bind{ - Address: func() (addr string) { - addr = "quic6@" + q.AddrIPv6 - return - }(), - Port: utils.PtrInt64(q.QuicBindPort), - BindParams: models.BindParams{ - Name: QUIC6BIND, - Ssl: true, - SslCertificate: q.CertDir, - Alpn: "h3", - }, - }) - errs.Add(errFrontendBindCreate) - instance.ReloadIf(errFrontendBindCreate == nil, "quic binding v6 created") + if q.IPv4 && !bindIPv4Exists { + addBind("quic4@"+q.AddrIPv4, QUIC4BIND, false) + } + if q.IPv6 && !bindIPv6Exists { + addBind("quic6@"+q.AddrIPv6, QUIC6BIND, true) } - ipv4DeleteFunc := func() { - if !bindv4Present { - return + for _, bind := range binds { + err = h.FrontendBindCreate(h.FrontHTTPS, bind) + if err != nil { + return err } - errFrontendBindDelete := h.FrontendBindDelete(h.FrontHTTPS, QUIC4BIND) - errs.Add(errFrontendBindDelete) - instance.ReloadIf(errFrontendBindDelete == nil, "quic binding v4 removed") } - ipv6DeleteFunc := func() { - if !bindv6Present { - return + if len(binds) > 0 { + instance.Reload("QUIC enabled") + } + return +} + +func (q *Quic) disableQuic(h haproxy.HAProxy) (err error) { + errors := utils.Errors{} + if q.IPv6 { + errors.Add(h.FrontendBindDelete(h.FrontHTTPS, QUIC6BIND)) + } + if q.IPv4 { + errors.Add(h.FrontendBindDelete(h.FrontHTTPS, QUIC4BIND)) + } + err = errors.Result() + if err == nil { + instance.Reload("QUIC disabled") + } + return +} + +func (q *Quic) altSvcRule(h haproxy.HAProxy) (err error) { + errors := utils.Errors{} + logger.Debug("quic redirect rule to be created") + errors.Add(h.AddRule(h.FrontHTTPS, rules.RequestRedirectQuic{}, false)) + logger.Debug("quic set header rule to be created") + errors.Add(h.AddRule(h.FrontHTTPS, rules.SetHdr{ + HdrName: "alt-svc", + Response: true, + HdrFormat: fmt.Sprintf("\"h3=\\\":%d\\\"; ma="+q.MaxAge+"\"", q.QuicAnnouncePort), + }, false)) + return errors.Result() +} + +func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) { + sslOffloadEnabled := h.FrontendSSLOffloadEnabled(h.FrontHTTPS) + if !sslOffloadEnabled { + logger.Warning("quic requires SSL offload to be enabled") + if err := q.disableQuic(h); err != nil { + return err } - errFrontendBindDelete := h.FrontendBindDelete(h.FrontHTTPS, QUIC6BIND) - errs.Add(errFrontendBindDelete) - instance.ReloadIf(errFrontendBindDelete == nil, "quic binding v6 removed") + return nil } maxAge := common.GetValue("quic-alt-svc-max-age", k.ConfigMaps.Main.Annotations) @@ -116,38 +135,25 @@ func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) nsSslCertificateAnn, nameSslCertificateAnn, err := common.GetK8sPath("ssl-certificate", k.ConfigMaps.Main.Annotations) if err != nil || (nameSslCertificateAnn == "") { - errs.Add(err) - ipv4Func = ipv4DeleteFunc - ipv6Func = ipv6DeleteFunc - } else { - namespaceSslCertificate := k.Namespaces[nsSslCertificateAnn] - var sslSecret *store.Secret - if namespaceSslCertificate != nil { - sslSecret = namespaceSslCertificate.Secret[nameSslCertificateAnn] - } - - if sslSecret == nil || sslSecret.Status == store.DELETED { - ipv4Func = ipv4DeleteFunc - ipv6Func = ipv6DeleteFunc - } else { - logger.Debug("quic redirect rule to be created") - errs.Add(h.AddRule(h.FrontHTTPS, rules.RequestRedirectQuic{}, false)) - logger.Debug("quic set header rule to be created") - errs.Add(h.AddRule(h.FrontHTTPS, rules.SetHdr{ - HdrName: "alt-svc", - Response: true, - HdrFormat: fmt.Sprintf("\"h3=\\\":%d\\\";ma="+maxAge+";\"", q.QuicAnnouncePort), - }, false)) + if err := q.disableQuic(h); err != nil { + return err } + return nil } - if q.IPv4 { - ipv4Func() + namespaceSslCertificate := k.Namespaces[nsSslCertificateAnn] + var sslSecret *store.Secret + if namespaceSslCertificate != nil { + sslSecret = namespaceSslCertificate.Secret[nameSslCertificateAnn] } - if q.IPv6 { - ipv6Func() + if sslSecret == nil || sslSecret.Status == store.DELETED { + logger.Warning("quic requires valid and existing ssl-certificate") + if err := q.disableQuic(h); err != nil { + return err + } + return nil } - return + return q.enableQuic(h) } From 846d295ee38309814a230b57f31f8563467fad94 Mon Sep 17 00:00:00 2001 From: Philipp Kolberg Date: Fri, 14 Mar 2025 23:58:56 +0100 Subject: [PATCH 2/2] MINOR: Fix aspell error for quic --- .aspell.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.aspell.yml b/.aspell.yml index fdbf10ee..9341ae54 100644 --- a/.aspell.yml +++ b/.aspell.yml @@ -38,3 +38,4 @@ allowed: - optim - prometheus - configmaps + - quic