@@ -29,82 +29,101 @@ type Quic struct {
2929 IPv6 bool
3030}
3131
32- func (q * Quic ) Update (k store.K8s , h haproxy.HAProxy , a annotations.Annotations ) (err error ) {
33- var errs utils.Errors
34- defer func () {
35- err = errs .Result ()
36- }()
37- var bindv4Present , bindv6Present bool
38- binds , errBindsGet := h .FrontendBindsGet (h .FrontHTTPS )
39- if errBindsGet != nil {
40- errs .Add (errBindsGet )
32+ func (q * Quic ) enableQuic (h haproxy.HAProxy ) (err error ) {
33+ var binds []models.Bind
34+ var bindIPv4Exists , bindIPv6Exists bool
35+
36+ err = q .altSvcRule (h )
37+ if err != nil {
4138 return
4239 }
4340
44- for _ , bind := range binds {
45- bindv4Present = bindv4Present || bind . Name == QUIC4BIND
46- bindv6Present = bindv6Present || bind . Name == QUIC6BIND
41+ existingBinds , err := h . FrontendBindsGet ( h . FrontHTTPS )
42+ if err != nil {
43+ return
4744 }
4845
49- ipv4Func := func () {
50- if bindv4Present {
51- return
46+ if q .IPv4 || q .IPv6 {
47+ for _ , existingBind := range existingBinds {
48+ if existingBind .Name == QUIC4BIND {
49+ bindIPv4Exists = true
50+ }
51+ if existingBind .Name == QUIC6BIND {
52+ bindIPv6Exists = true
53+ }
5254 }
55+ }
5356
54- errFrontendBindCreate := h .FrontendBindCreate (h .FrontHTTPS , models.Bind {
55- Address : func () (addr string ) {
56- addr = "quic4@" + q .AddrIPv4
57- return
58- }(),
59- Port : utils .PtrInt64 (q .QuicBindPort ),
57+ addBind := func (addr string , bindName string , v4v6 bool ) {
58+ binds = append (binds , models.Bind {
59+ Address : addr ,
60+ Port : utils .PtrInt64 (q .QuicBindPort ),
6061 BindParams : models.BindParams {
61- Name : QUIC4BIND ,
62+ Name : bindName ,
6263 Ssl : true ,
6364 SslCertificate : q .CertDir ,
6465 Alpn : "h3" ,
66+ V4v6 : v4v6 ,
6567 },
6668 })
67- errs .Add (errFrontendBindCreate )
68- instance .ReloadIf (errFrontendBindCreate == nil , "quic binding v4 created" )
6969 }
7070
71- ipv6Func := func () {
72- if bindv6Present {
73- return
74- }
75- errFrontendBindCreate := h .FrontendBindCreate (h .FrontHTTPS , models.Bind {
76- Address : func () (addr string ) {
77- addr = "quic6@" + q .AddrIPv6
78- return
79- }(),
80- Port : utils .PtrInt64 (q .QuicBindPort ),
81- BindParams : models.BindParams {
82- Name : QUIC6BIND ,
83- Ssl : true ,
84- SslCertificate : q .CertDir ,
85- Alpn : "h3" ,
86- },
87- })
88- errs .Add (errFrontendBindCreate )
89- instance .ReloadIf (errFrontendBindCreate == nil , "quic binding v6 created" )
71+ if q .IPv4 && ! bindIPv4Exists {
72+ addBind ("quic4@" + q .AddrIPv4 , QUIC4BIND , false )
73+ }
74+ if q .IPv6 && ! bindIPv6Exists {
75+ addBind ("quic6@" + q .AddrIPv6 , QUIC6BIND , true )
9076 }
9177
92- ipv4DeleteFunc := func () {
93- if ! bindv4Present {
94- return
78+ for _ , bind := range binds {
79+ err = h .FrontendBindCreate (h .FrontHTTPS , bind )
80+ if err != nil {
81+ return err
9582 }
96- errFrontendBindDelete := h .FrontendBindDelete (h .FrontHTTPS , QUIC4BIND )
97- errs .Add (errFrontendBindDelete )
98- instance .ReloadIf (errFrontendBindDelete == nil , "quic binding v4 removed" )
9983 }
10084
101- ipv6DeleteFunc := func () {
102- if ! bindv6Present {
103- return
85+ if len (binds ) > 0 {
86+ instance .Reload ("QUIC enabled" )
87+ }
88+ return
89+ }
90+
91+ func (q * Quic ) disableQuic (h haproxy.HAProxy ) (err error ) {
92+ errors := utils.Errors {}
93+ if q .IPv6 {
94+ errors .Add (h .FrontendBindDelete (h .FrontHTTPS , QUIC6BIND ))
95+ }
96+ if q .IPv4 {
97+ errors .Add (h .FrontendBindDelete (h .FrontHTTPS , QUIC4BIND ))
98+ }
99+ err = errors .Result ()
100+ if err == nil {
101+ instance .Reload ("QUIC disabled" )
102+ }
103+ return
104+ }
105+
106+ func (q * Quic ) altSvcRule (h haproxy.HAProxy ) (err error ) {
107+ errors := utils.Errors {}
108+ logger .Debug ("quic redirect rule to be created" )
109+ errors .Add (h .AddRule (h .FrontHTTPS , rules.RequestRedirectQuic {}, false ))
110+ logger .Debug ("quic set header rule to be created" )
111+ errors .Add (h .AddRule (h .FrontHTTPS , rules.SetHdr {
112+ HdrName : "alt-svc" ,
113+ Response : true ,
114+ HdrFormat : fmt .Sprintf ("\" h3=\\ \" :%d\\ \" ; ma=" + q .MaxAge + "\" " , q .QuicAnnouncePort ),
115+ }, false ))
116+ return errors .Result ()
117+ }
118+
119+ func (q * Quic ) Update (k store.K8s , h haproxy.HAProxy , a annotations.Annotations ) (err error ) {
120+ sslOffloadEnabled := h .FrontendSSLOffloadEnabled (h .FrontHTTPS )
121+ if ! sslOffloadEnabled {
122+ logger .Warning ("quic requires SSL offload to be enabled" )
123+ if err := q .disableQuic (h ); err != nil {
124+ return err
104125 }
105- errFrontendBindDelete := h .FrontendBindDelete (h .FrontHTTPS , QUIC6BIND )
106- errs .Add (errFrontendBindDelete )
107- instance .ReloadIf (errFrontendBindDelete == nil , "quic binding v6 removed" )
126+ return nil
108127 }
109128
110129 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)
116135
117136 nsSslCertificateAnn , nameSslCertificateAnn , err := common .GetK8sPath ("ssl-certificate" , k .ConfigMaps .Main .Annotations )
118137 if err != nil || (nameSslCertificateAnn == "" ) {
119- errs .Add (err )
120- ipv4Func = ipv4DeleteFunc
121- ipv6Func = ipv6DeleteFunc
122- } else {
123- namespaceSslCertificate := k .Namespaces [nsSslCertificateAnn ]
124- var sslSecret * store.Secret
125- if namespaceSslCertificate != nil {
126- sslSecret = namespaceSslCertificate .Secret [nameSslCertificateAnn ]
127- }
128-
129- if sslSecret == nil || sslSecret .Status == store .DELETED {
130- ipv4Func = ipv4DeleteFunc
131- ipv6Func = ipv6DeleteFunc
132- } else {
133- logger .Debug ("quic redirect rule to be created" )
134- errs .Add (h .AddRule (h .FrontHTTPS , rules.RequestRedirectQuic {}, false ))
135- logger .Debug ("quic set header rule to be created" )
136- errs .Add (h .AddRule (h .FrontHTTPS , rules.SetHdr {
137- HdrName : "alt-svc" ,
138- Response : true ,
139- HdrFormat : fmt .Sprintf ("\" h3=\\ \" :%d\\ \" ;ma=" + maxAge + ";\" " , q .QuicAnnouncePort ),
140- }, false ))
138+ if err := q .disableQuic (h ); err != nil {
139+ return err
141140 }
141+ return nil
142142 }
143143
144- if q .IPv4 {
145- ipv4Func ()
144+ namespaceSslCertificate := k .Namespaces [nsSslCertificateAnn ]
145+ var sslSecret * store.Secret
146+ if namespaceSslCertificate != nil {
147+ sslSecret = namespaceSslCertificate .Secret [nameSslCertificateAnn ]
146148 }
147149
148- if q .IPv6 {
149- ipv6Func ()
150+ if sslSecret == nil || sslSecret .Status == store .DELETED {
151+ logger .Warning ("quic requires valid and existing ssl-certificate" )
152+ if err := q .disableQuic (h ); err != nil {
153+ return err
154+ }
155+ return nil
150156 }
151157
152- return
158+ return q . enableQuic ( h )
153159}
0 commit comments