From 200bdb294870dd2aa15a14c970a7e2d3b3299cd3 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:02:19 +0800 Subject: [PATCH 1/9] Add new options to TunnelBinding --- api/v1alpha1/tunnelbinding_types.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/api/v1alpha1/tunnelbinding_types.go b/api/v1alpha1/tunnelbinding_types.go index 763fa387..285d4e46 100644 --- a/api/v1alpha1/tunnelbinding_types.go +++ b/api/v1alpha1/tunnelbinding_types.go @@ -61,6 +61,23 @@ type TunnelBindingSubjectSpec struct { // +kubebuilder:validation:Optional CaPool string `json:"caPool,omitempty"` + // MatchSNIToHost causes cloudflared to automatically set the Server Name Indication (SNI) during the TLS + // handshake to the hostname of the incoming request. Origin must be configured as https. Defaults to false. + // +kubebuilder:validation:Optional + // +kubebuilder:default:=false + MatchSNIToHost bool `json:"matchSNItoHost"` + + // OriginServerName informs cloudflared what hostname it should expect from your origin server's TLS certificate. + // Only useful if the protocol is HTTPS. If not specified, defaults to the service URL. + // +kubebuilder:validation:Optional + OriginServerName string `json:"originServerName,omitempty"` + + // TlsTimeout configures the maximum time (in seconds) to wait for TLS handshake with the origin. + // Only useful if the protocol is HTTPS. Default is 10 seconds. + // +kubebuilder:validation:Optional + // +kubebuilder:default:=10 + TlsTimeout uint `json:"tlsTimeout"` + // NoTlsVerify disables TLS verification for this service. // Only useful if the protocol is HTTPS. // +kubebuilder:validation:Optional From da8d266af347f833b0652b8354bc901bd47bc75c Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:16:34 +0800 Subject: [PATCH 2/9] Omit empty tls timeout to default to seconds --- api/v1alpha1/tunnelbinding_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1alpha1/tunnelbinding_types.go b/api/v1alpha1/tunnelbinding_types.go index 285d4e46..b3a4fb52 100644 --- a/api/v1alpha1/tunnelbinding_types.go +++ b/api/v1alpha1/tunnelbinding_types.go @@ -76,7 +76,7 @@ type TunnelBindingSubjectSpec struct { // Only useful if the protocol is HTTPS. Default is 10 seconds. // +kubebuilder:validation:Optional // +kubebuilder:default:=10 - TlsTimeout uint `json:"tlsTimeout"` + TlsTimeout uint `json:"tlsTimeout,omitempty"` // NoTlsVerify disables TLS verification for this service. // Only useful if the protocol is HTTPS. From 90a6b3042417a5a7b9f61d6be69343b866282674 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:16:58 +0800 Subject: [PATCH 3/9] Add MatchSNItoHost to CF origin configuration --- internal/clients/cf/configuration.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/clients/cf/configuration.go b/internal/clients/cf/configuration.go index 2129f488..9b19f8b0 100644 --- a/internal/clients/cf/configuration.go +++ b/internal/clients/cf/configuration.go @@ -54,6 +54,9 @@ type OriginRequestConfig struct { // Will allow any certificate from the origin to be accepted. // Note: The connection from your machine to Cloudflare's Edge is still encrypted. NoTLSVerify *bool `yaml:"noTLSVerify,omitempty"` + // When true, cloudflared will automatically set the Server Name Indication (SNI) during the TLS handshake + // to the hostname of the incoming request. + MatchSNItoHost *bool `yaml:"matchSNItoHost,omitempty"` // Attempt to connect to origin using HTTP2. Origin must be configured as https. Http2Origin *bool `yaml:"http2Origin,omitempty"` // Disables chunked transfer encoding. From 642d2789e35849c8a80d5f2b23da0e037dff6261 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:17:14 +0800 Subject: [PATCH 4/9] Update reconciliation loop to apply the new settings --- internal/controller/tunnelbinding_controller.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/internal/controller/tunnelbinding_controller.go b/internal/controller/tunnelbinding_controller.go index 4a38c500..8505e80a 100644 --- a/internal/controller/tunnelbinding_controller.go +++ b/internal/controller/tunnelbinding_controller.go @@ -583,8 +583,14 @@ func (r *TunnelBindingReconciler) configureCloudflareDaemon() error { } else { targetService = binding.Status.Services[i].Target } + + tlsTimeout := new(time.Duration) + *tlsTimeout = time.Duration(subject.Spec.TlsTimeout) * time.Second + originRequest := cf.OriginRequestConfig{} + originRequest.TLSTimeout = tlsTimeout originRequest.NoTLSVerify = &subject.Spec.NoTlsVerify + originRequest.MatchSNItoHost = &subject.Spec.MatchSNIToHost originRequest.Http2Origin = &subject.Spec.Http2Origin originRequest.ProxyAddress = &subject.Spec.ProxyAddress originRequest.ProxyPort = &subject.Spec.ProxyPort @@ -593,6 +599,9 @@ func (r *TunnelBindingReconciler) configureCloudflareDaemon() error { caPath := fmt.Sprintf("/etc/cloudflared/certs/%s", caPool) originRequest.CAPool = &caPath } + if subject.Spec.OriginServerName != "" { + originRequest.OriginServerName = &subject.Spec.OriginServerName + } finalIngresses = append(finalIngresses, cf.UnvalidatedIngressRule{ Hostname: binding.Status.Services[i].Hostname, From 51c357a36e723bc85ef2d943b5a3285c5c463cb3 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:23:41 +0800 Subject: [PATCH 5/9] Update TunnelBinding CRD to accept new options --- ...working.cfargotunnel.com_tunnelbindings.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/config/crd/bases/networking.cfargotunnel.com_tunnelbindings.yaml b/config/crd/bases/networking.cfargotunnel.com_tunnelbindings.yaml index f03e13ee..6a5a31c6 100644 --- a/config/crd/bases/networking.cfargotunnel.com_tunnelbindings.yaml +++ b/config/crd/bases/networking.cfargotunnel.com_tunnelbindings.yaml @@ -138,6 +138,23 @@ spec: Target specified where the tunnel should proxy to. Defaults to the form of ://..svc: type: string + originServerName: + description: |- + OriginServerName informs cloudflared what hostname it should expect from your origin server's TLS certificate. + Only useful if the protocol is HTTPS. If not specified, defaults to the service URL. + type: string + matchSNItoHost: + default: false + description: |- + When true, cloudflared will automatically set the Server Name Indication (SNI) + during the TLS handshake to the hostname of the incoming request. + type: boolean + tlsTimeout: + default: 10 + description: |- + TlsTimeout configures the TLS handshake timeout in seconds. + minimum: 0 + type: integer type: object required: - name From 22c9271c7d8989b0501f1149222be275be56c1e9 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:45:41 +0800 Subject: [PATCH 6/9] Add warp routing option to tunnel spec --- api/v1alpha2/tunnel_types.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/v1alpha2/tunnel_types.go b/api/v1alpha2/tunnel_types.go index 8cf505eb..b238c3d4 100644 --- a/api/v1alpha2/tunnel_types.go +++ b/api/v1alpha2/tunnel_types.go @@ -90,6 +90,11 @@ type TunnelSpec struct { // +kubebuilder:default:="{}" DeployPatch string `json:"deployPatch,omitempty"` + // Whether to enable warp routing for the tunnel. + // +kubebuilder:validation:Optional + // +kubebuilder:default:=false + WarpRouting bool `json:"warpRouting,omitempty"` + // +kubebuilder:default:=false // +kubebuilder:validation:Optional // NoTlsVerify disables origin TLS certificate checks when the endpoint is HTTPS. From c1bd7d188730fd8db611d849f087f2b1a4c71ff1 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:48:20 +0800 Subject: [PATCH 7/9] Add warp routing option to crds --- .../crd/bases/networking.cfargotunnel.com_clustertunnels.yaml | 4 ++++ config/crd/bases/networking.cfargotunnel.com_tunnels.yaml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml index b44fc2af..87943e79 100644 --- a/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml +++ b/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml @@ -312,6 +312,10 @@ spec: Deployment patch for the cloudflared deployment. Follows https://kubernetes.io/docs/reference/kubectl/generated/kubectl_patch/ type: string + warpRouting: + default: false + description: Whether to enable warp routing for the tunnel. + type: boolean existingTunnel: description: |- Existing tunnel object. diff --git a/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml index 26f6f241..6d53116e 100644 --- a/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml +++ b/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml @@ -312,6 +312,10 @@ spec: Deployment patch for the cloudflared deployment. Follows https://kubernetes.io/docs/reference/kubectl/generated/kubectl_patch/ type: string + warpRouting: + default: false + description: Whether to enable warp routing for the tunnel. + type: boolean existingTunnel: description: |- Existing tunnel object. From fa6de8036a89900639bcac7d9919711f8ab8b771 Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:54:13 +0800 Subject: [PATCH 8/9] Add warp routing reconciliation --- internal/controller/generic_tunnel_reconciler.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/controller/generic_tunnel_reconciler.go b/internal/controller/generic_tunnel_reconciler.go index 496f9979..372a6728 100644 --- a/internal/controller/generic_tunnel_reconciler.go +++ b/internal/controller/generic_tunnel_reconciler.go @@ -275,11 +275,12 @@ func createManagedResources(r GenericTunnelReconciler) (ctrl.Result, error) { // configMapForTunnel returns a tunnel ConfigMap object func configMapForTunnel(r GenericTunnelReconciler) *corev1.ConfigMap { ls := labelsForTunnel(r.GetTunnel()) - noTlsVerify := r.GetTunnel().GetSpec().NoTlsVerify + spec := r.GetTunnel().GetSpec() + noTlsVerify := spec.NoTlsVerify originRequest := cf.OriginRequestConfig{ NoTLSVerify: &noTlsVerify, } - if r.GetTunnel().GetSpec().OriginCaPool != "" { + if spec.OriginCaPool != "" { defaultCaPool := "/etc/cloudflared/certs/tls.crt" originRequest.CAPool = &defaultCaPool } @@ -289,6 +290,7 @@ func configMapForTunnel(r GenericTunnelReconciler) *corev1.ConfigMap { Metrics: "0.0.0.0:2000", NoAutoUpdate: true, OriginRequest: originRequest, + WarpRouting: cf.WarpRoutingConfig{Enabled: spec.WarpRouting}, Ingress: []cf.UnvalidatedIngressRule{{ Service: r.GetTunnel().GetSpec().FallbackTarget, }}, From 84fb0bb6d76415c77e3754f1e39f4bb28867552a Mon Sep 17 00:00:00 2001 From: Jacob Andersen <19645494+jacobsandersen@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:09:45 +0800 Subject: [PATCH 9/9] add conversion support & configure v1alpha1 crds --- api/v1alpha1/tunnel_conversion.go | 2 ++ api/v1alpha1/tunnel_types.go | 5 +++++ .../bases/networking.cfargotunnel.com_clustertunnels.yaml | 4 ++++ config/crd/bases/networking.cfargotunnel.com_tunnels.yaml | 4 ++++ 4 files changed, 15 insertions(+) diff --git a/api/v1alpha1/tunnel_conversion.go b/api/v1alpha1/tunnel_conversion.go index 662e1582..2376ee23 100644 --- a/api/v1alpha1/tunnel_conversion.go +++ b/api/v1alpha1/tunnel_conversion.go @@ -90,6 +90,7 @@ func (src TunnelSpec) ConvertTo(dst *v1alpha2.TunnelSpec) error { dst.Protocol = src.Protocol dst.OriginCaPool = src.OriginCaPool dst.NoTlsVerify = src.NoTlsVerify + dst.WarpRouting = src.WarpRouting patch := &V1alpha1Tov1alpha2Patch{} @@ -176,6 +177,7 @@ func (dst *TunnelSpec) ConvertFrom(src v1alpha2.TunnelSpec) error { dst.Protocol = src.Protocol dst.OriginCaPool = src.OriginCaPool dst.NoTlsVerify = src.NoTlsVerify + dst.WarpRouting = src.WarpRouting patch := &V1alpha1Tov1alpha2Patch{} if err := yaml.Unmarshal([]byte(src.DeployPatch), patch); err != nil { diff --git a/api/v1alpha1/tunnel_types.go b/api/v1alpha1/tunnel_types.go index 09459314..0f9d7c49 100644 --- a/api/v1alpha1/tunnel_types.go +++ b/api/v1alpha1/tunnel_types.go @@ -101,6 +101,11 @@ type TunnelSpec struct { // NoTlsVerify disables origin TLS certificate checks when the endpoint is HTTPS. NoTlsVerify bool `json:"noTlsVerify,omitempty"` + // Whether to enable warp routing for the tunnel. + // +kubebuilder:validation:Optional + // +kubebuilder:default:=false + WarpRouting bool `json:"warpRouting,omitempty"` + // +kubebuilder:validation:Optional // OriginCaPool speficies the secret with tls.crt (and other certs as needed to be referred in the service annotation) of the Root CA to be trusted when sending traffic to HTTPS endpoints OriginCaPool string `json:"originCaPool,omitempty"` diff --git a/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml index 87943e79..19972572 100644 --- a/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml +++ b/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml @@ -137,6 +137,10 @@ spec: description: NoTlsVerify disables origin TLS certificate checks when the endpoint is HTTPS. type: boolean + warpRouting: + default: false + description: Whether to enable warp routing for the tunnel. + type: boolean nodeSelectors: additionalProperties: type: string diff --git a/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml index 6d53116e..4f007bb8 100644 --- a/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml +++ b/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml @@ -137,6 +137,10 @@ spec: description: NoTlsVerify disables origin TLS certificate checks when the endpoint is HTTPS. type: boolean + warpRouting: + default: false + description: Whether to enable warp routing for the tunnel. + type: boolean nodeSelectors: additionalProperties: type: string