Struggling to get sniStrict working in my environment

Hi,

I am trying to activate / configure the sniStrict option to prevent answering a request to a host / domain that is not configured in my ingressroute rules with the traefik default self-signed certificate.

I want to close down any communcation that I did not explicitly configure.

My environment and my configs look like:

  • k3s cluster, but with disabled default traefik ingress deployment and built-in loadbalancer servicelb
  • metallb as loadbalancer instead
  • traefik deployed via helmchart
  • additional configuration of ingressroutes, etc. (see below)

helmchart for deployment of traefik instance:

apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  labels:
    app.kubernetes.io/name: traefik-customer
    app.kubernetes.io/version: 2.11.20.1
  name: traefik-customer
  namespace: kube-system 
spec:
  chart: https://%{KUBERNETES_API}%/static/charts/traefik-27.0.201+up27.0.2.tgz
  set:
    global.systemDefaultRegistry: ""
  valuesContent: |-
    globalArguments:
      - "--global.checknewversion=false"
    rbac:
      enabled: true
    logs:
      general:
        level: INFO
      access:
        enabled: false    
    ingressClass:
      isDefaultClass: false
    ports:
      web:
        redirectTo: 
          port: websecure
      websecure:
        tls:
          enabled: true
    podAnnotations:
      prometheus.io/port: "8082"
      prometheus.io/scrape: "true"
    providers:
      kubernetesIngress:
        publishedService:
          enabled: true
        ingressClass: traefik-customer
      kubernetesCRD:
        enabled: true
        allowCrossNamespace: false
        allowExternalNameServices: false
        allowEmptyServices: false
        ingressClass: traefik-customer
    priorityClassName: "system-cluster-critical"
    image:
      name: "rancher/mirrored-library-traefik"
      tag: "2.11.20"
    tolerations:
    - key: "CriticalAddonsOnly"
      operator: "Exists"
    - key: "node-role.kubernetes.io/control-plane"
      operator: "Exists"
      effect: "NoSchedule"
    - key: "node-role.kubernetes.io/master"
      operator: "Exists"
      effect: "NoSchedule"
    service:
      ipFamilyPolicy: "PreferDualStack"
      annotations:
        metallb.universe.tf/loadBalancerIPs: <loadbalancerIP>
      spec:
        externalTrafficPolicy: Local
        allocateLoadBalancerNodePorts: false
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-traefik-customer-access
  namespace: kube-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/instance: traefik-customer-kube-system
  ingress:
    - from:
      - ipBlock:
          cidr: <customer network>
  policyTypes:
  - Ingress

ingressroute configuration:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: customer-ingressroute
  namespace: default
  annotations:
    kubernetes.io/ingress.class: traefik-customer
  labels:
    app.kubernetes.io/name: traefik-customer
    app.kubernetes.io/version: 1.0.0.7
spec:
  routes:
  - kind: Rule
    match: Host("www.customer.com")
    services:
    - name: customerapp
      port: 3000
  tls:
    secretName: customer-tls
    options:
      name: enforcetls13
      namespace: default

tls options configuration:

apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
  name: enforcetls13
  namespace: default
spec:
  minVersion: VersionTLS13
  sniStrict: true

when I connect to the configured Host("www.customer.com") I get the certificate configured and the connection is established as it should be

when I connect to an url, that does not match any configuration, e. g. with

curl -vk https://server.customer.com --resolve server.customer.com:443:<loadbalancerIP>

I get a reply with the default certifcate

* Added server.customer.com:443:<loadbalancerIP> to DNS cache
* Rebuilt URL to: https://server.customer.com/
* Hostname server.customer.com was found in DNS cache
*   Trying <loadbalancerIP>...
* TCP_NODELAY set
* Connected to server.customer.com (<loadbalancerIP>) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=TRAEFIK DEFAULT CERT
*  start date: Jul 18 12:52:55 2025 GMT
*  expire date: Jul 18 12:52:55 2026 GMT
*  issuer: CN=TRAEFIK DEFAULT CERT
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* Using Stream ID: 1 (easy handle 0x55d723922710)
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> GET / HTTP/2
> Host: server.customer.com
> User-Agent: curl/7.61.1
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/2 404 
< content-type: text/plain; charset=utf-8
< x-content-type-options: nosniff
< content-length: 19
< date: Fri, 18 Jul 2025 12:53:10 GMT
< 
* TLSv1.3 (IN), TLS app data, [no content] (0):
404 page not found
* Connection #0 to host server.customer.com left intact

what am I doing wrong ?

any help would be very much appreciated...
thank you