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/api/v1alpha1/tunnelbinding_types.go b/api/v1alpha1/tunnelbinding_types.go index 763fa387..b3a4fb52 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,omitempty"` + // NoTlsVerify disables TLS verification for this service. // Only useful if the protocol is HTTPS. // +kubebuilder:validation:Optional 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. diff --git a/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_clustertunnels.yaml index b44fc2af..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 @@ -312,6 +316,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_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 diff --git a/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml b/config/crd/bases/networking.cfargotunnel.com_tunnels.yaml index 26f6f241..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 @@ -312,6 +316,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/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. 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, }}, 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,