Skip to content

Gateway API regression in v1.20.0: wildcard HTTPS listener conflicts with exact TLS passthrough listener on port 443 #47590

Closed

Description

@mkhazamipour

Is there an existing issue for this?

I searched existing issues. The closest ones I found are:

However, none appear to track this exact regression in Cilium v1.20.0 where an HTTPS wildcard listener and a more-specific TLS passthrough listener on the same port are rejected with ProtocolConflict.

What happened?

After upgrading to Cilium v1.20.0 and Gateway API CRDs v1.6.1, a previously working Gateway configuration stopped working.

The Gateway uses:

  • An HTTPS listener with TLS termination for *.example.com on port 443.
  • A more-specific TLS passthrough listener for argocd.example.com on the same port.
  • HTTPRoutes attached to the wildcard HTTPS listener.
  • A TLSRoute attached explicitly to the passthrough listener using sectionName.

Before the upgrade, Cilium routed traffic as expected:

  • argocd.example.com matched the exact TLS listener and was passed through to the Argo CD backend.
  • Other subdomains such as web.example.com matched the wildcard HTTPS listener and were terminated at the Gateway.

After upgrading, Cilium marks both the wildcard HTTPS listener and the exact TLS passthrough listener as conflicted:

message: >-
  Listener conflicts with listener "tls-argocd": same port 443 has
  overlapping HTTPS and TLS passthrough hostnames.
reason: ProtocolConflict
status: "True"
type: Conflicted

The wildcard HTTPS listener then becomes:

reason: Invalid
status: "False"
type: Accepted

As a result, all HTTPRoutes attached to the wildcard HTTPS listener stop working.

Removing the TLS passthrough listener immediately causes the wildcard HTTPS listener to become accepted/programmed again, and all HTTPRoutes start working.

The overall Gateway still reports:

conditions:
- reason: Accepted
  status: "True"
  type: Accepted
- reason: Programmed
  status: "True"
  type: Programmed

This is because the HTTP listeners and the non-overlapping apex HTTPS listener remain valid, while the wildcard HTTPS listener itself is rejected.

What did you expect to happen?

I expected the exact hostname listener to take precedence over the wildcard hostname listener:

  • argocd.example.com:443 → exact TLS/Passthrough listener
  • Other *.example.com:443 hostnames → wildcard HTTPS/Terminate listener
  • example.com:443 → apex HTTPS/Terminate listener

How can we reproduce the issue?

Prerequisites

The following are installed and enabled:

  • Cilium v1.20.0
  • Gateway API CRDs v1.6.1
  • Cilium Gateway API controller
  • TLSRoute support
  • A valid TLS Secret named example-wildcard-cert in gateway-system
  • The backend Services referenced by the Routes

1. Apply the GatewayClass, Gateway and Routes

apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
  name: argocd-tls
  namespace: argocd
spec:
  hostnames:
  - argocd.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: public-gateway
    namespace: gateway-system
    sectionName: tls-argocd
  rules:
  - backendRefs:
    - group: ""
      kind: Service
      name: argocd-server
      port: 443
      weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web
  namespace: web
spec:
  hostnames:
  - web.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: public-gateway
    namespace: gateway-system
    sectionName: https-wildcard
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - group: ""
      kind: Service
      name: web
      port: 80
      weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: pla
  namespace: openldap
spec:
  hostnames:
  - pla.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: public-gateway
    namespace: gateway-system
    sectionName: https-wildcard
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - group: ""
      kind: Service
      name: phpldapadmin
      port: 8080
      weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: keycloak
  namespace: keycloak
spec:
  hostnames:
  - keycloak.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: public-gateway
    namespace: gateway-system
    sectionName: https-wildcard
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - group: ""
      kind: Service
      name: keycloak
      port: 8080
      weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: apex
  namespace: web
spec:
  hostnames:
  - example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: public-gateway
    namespace: gateway-system
    sectionName: https-apex
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - group: ""
      kind: Service
      name: web
      port: 80
      weight: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: gateway-system
spec:
  addresses:
  - type: IPAddress
    value: 162.xxx.xxx.xxx

  gatewayClassName: cilium

  listeners:
  - name: http-wildcard
    hostname: "*.example.com"
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: All

  - name: http-apex
    hostname: example.com
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: All

  - name: https-wildcard
    hostname: "*.example.com"
    port: 443
    protocol: HTTPS
    allowedRoutes:
      namespaces:
        from: All
    tls:
      mode: Terminate
      certificateRefs:
      - group: ""
        kind: Secret
        name: example-wildcard-cert

  - name: https-apex
    hostname: example.com
    port: 443
    protocol: HTTPS
    allowedRoutes:
      namespaces:
        from: All
    tls:
      mode: Terminate
      certificateRefs:
      - group: ""
        kind: Secret
        name: example-wildcard-cert

  - name: tls-rhacs
    hostname: rhacs.example.com
    port: 443
    protocol: TLS
    allowedRoutes:
      namespaces:
        from: All
    tls:
      mode: Passthrough

  - name: tls-argocd
    hostname: argocd.example.com
    port: 443
    protocol: TLS
    allowedRoutes:
      namespaces:
        from: All
    tls:
      mode: Passthrough
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: cilium
spec:
  controllerName: io.cilium/gateway-controller
  description: Cilium GatewayClass
  parametersRef:
    group: cilium.io
    kind: CiliumGatewayClassConfig
    name: cilium-lb-gateway-config
    namespace: gateway-system

The TLSRoute explicitly attaches to the tls-argocd listener using:

sectionName: tls-argocd

Each HTTPRoute explicitly attaches to either https-wildcard or https-apex.

2. Check the Gateway status

kubectl -n gateway-system get gateway public-gateway \
  -o jsonpath='{range .status.listeners[*]}{.name}{"\tattachedRoutes="}{.attachedRoutes}{"\t"}{range .conditions[*]}{.type}{"="}{.status}{"/"}{.reason}{"  "}{end}{"\n"}{end}'

Observed result:

http-wildcard    attachedRoutes=0    ResolvedRefs=True/ResolvedRefs  Accepted=True/Accepted  Programmed=True/Programmed
http-apex        attachedRoutes=0    ResolvedRefs=True/ResolvedRefs  Accepted=True/Accepted  Programmed=True/Programmed
https-wildcard   attachedRoutes=3    Conflicted=True/ProtocolConflict  Accepted=False/Invalid  Programmed=False/Pending
https-apex       attachedRoutes=1    ResolvedRefs=True/ResolvedRefs  Accepted=True/Accepted  Programmed=True/Programmed
tls-argocd       attachedRoutes=1    Conflicted=True/ProtocolConflict  Accepted=False/Invalid  Programmed=False/Pending

The relevant observed status is:

status:
  addresses:
  - type: IPAddress
    value: 162.xxx.xxx.xxx

  conditions:
  - message: Gateway successfully scheduled
    reason: Accepted
    status: "True"
    type: Accepted
  - message: Gateway Programmed
    reason: Programmed
    status: "True"
    type: Programmed

  listeners:
  - name: https-wildcard
    attachedRoutes: 3
    supportedKinds:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
    conditions:
    - message: >-
        Listener conflicts with listener "tls-argocd": same port 443 has
        overlapping HTTPS and TLS passthrough hostnames.
      reason: ProtocolConflict
      status: "True"
      type: Conflicted
    - message: >-
        Listener not valid. Listener conflicts with listener "tls-argocd":
        same port 443 has overlapping HTTPS and TLS passthrough hostnames.
      reason: Invalid
      status: "False"
      type: Accepted
    - message: Address not ready yet
      reason: Pending
      status: "False"
      type: Programmed

  - name: https-apex
    attachedRoutes: 1
    supportedKinds:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
    conditions:
    - message: Resolved Refs
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    - message: Listener Accepted
      reason: Accepted
      status: "True"
      type: Accepted
    - message: Listener Programmed
      reason: Programmed
      status: "True"
      type: Programmed

  - name: tls-argocd
    attachedRoutes: 1
    supportedKinds:
    - group: gateway.networking.k8s.io
      kind: TLSRoute
    conditions:
    - message: >-
        Listener conflicts with listener "https-wildcard": same port 443
        has overlapping HTTPS and TLS passthrough hostnames.
      reason: ProtocolConflict
      status: "True"
      type: Conflicted
    - message: >-
        Listener not valid. Listener conflicts with listener
        "https-wildcard": same port 443 has overlapping HTTPS and TLS
        passthrough hostnames.
      reason: Invalid
      status: "False"
      type: Accepted
    - message: Address not ready yet
      reason: Pending
      status: "False"
      type: Programmed

The overall Gateway is still reported as Accepted=True and Programmed=True, even though the https-wildcard listener serving three HTTPRoutes is rejected.

3. Test the routes

The three routes attached to https-wildcard fail:

curl -vk --resolve web.example.com:443:162.xxx.xxx.xxx \
  https://web.example.com/

curl -vk --resolve pla.example.com:443:162.xxx.xxx.xxx \
  https://pla.example.com/

curl -vk --resolve keycloak.example.com:443:162.xxx.xxx.xxx \
  https://keycloak.example.com/

The apex route is attached to the independent https-apex listener and continues working:

curl -vk --resolve example.com:443:162.xxx.xxx.xxx \
  https://example.com/

4. Remove the TLS passthrough listeners

Remove tls-argocd and tls-rhacs from the Gateway while leaving the HTTPS listeners unchanged:

kubectl -n gateway-system edit gateway public-gateway

Remove:

- name: tls-rhacs
  hostname: rhacs.example.com
  port: 443
  protocol: TLS
  tls:
    mode: Passthrough
  allowedRoutes:
    namespaces:
      from: All

- name: tls-argocd
  hostname: argocd.example.com
  port: 443
  protocol: TLS
  tls:
    mode: Passthrough
  allowedRoutes:
    namespaces:
      from: All

After reconciliation, check the status again:

kubectl -n gateway-system get gateway public-gateway \
  -o jsonpath='{range .status.listeners[*]}{.name}{"\tattachedRoutes="}{.attachedRoutes}{"\t"}{range .conditions[*]}{.type}{"="}{.status}{"/"}{.reason}{"  "}{end}{"\n"}{end}'

The https-wildcard listener becomes:

https-wildcard    attachedRoutes=3    ResolvedRefs=True/ResolvedRefs  Accepted=True/Accepted  Programmed=True/Programmed

All three wildcard HTTPRoutes immediately start working again.

5. Re-add only the Argo CD passthrough listener

Re-add:

- name: tls-argocd
  hostname: argocd.example.com
  port: 443
  protocol: TLS
  tls:
    mode: Passthrough
  allowedRoutes:
    namespaces:
      from: All

The conflict immediately returns:

https-wildcard    Conflicted=True/ProtocolConflict  Accepted=False/Invalid  Programmed=False/Pending
tls-argocd        Conflicted=True/ProtocolConflict  Accepted=False/Invalid  Programmed=False/Pending

The three HTTPRoutes attached to https-wildcard become unavailable again.

This demonstrates that the failure is caused specifically by combining:

HTTPS/Terminate  *.example.com:443
TLS/Passthrough  argocd.example.com:443

The same design worked on 1.20.0-rc.1 before upgrading to Cilium v1.20.0 with Gateway API v1.6.1.

Cilium Version

1.20.0

Kernel Version

7.0.0-27-generic #27-Ubuntu SMP PREEMPT_DYNAMIC Thu Jun 18 19:13:49 UTC 2026 x86_64 GNU/Linux

Kubernetes Version

1.36.2

Regression

1.20.0-rc.1

Sysdump

No response

Relevant log output

Anything else?

root@kubernetes-master-1:~# cat cilium.yaml
certgen:
  generateCA: true

ipam:
  mode: "cluster-pool"

hubble:
  enabled: true
  relay:
    enabled: true
  ui:
    enabled: true
    frontend:
      server:
        ipv6:
          enabled: false
  metrics:
    enabled:
      - dns
      - drop
      - tcp
      - flow
      - port-distribution
      - icmp
      - http
      - kafka
      - l7-proxy
      - l7-requests
    enableOpenMetrics: true

l2announcements:
  enabled: true

bpf:
  masquerade: true

pmtuDiscovery:
  enabled: true

egressGateway:
  enabled: true

tunnelProtocol: geneve

gatewayAPI:
  enabled: true
  enableAppProtocol: true
  enableAlpn: true
  gatewayClass:
    create: 'false'

prometheus:
  metricsService: true
  enabled: true

k8sClientRateLimit:
  burst: 20
  qps: 10

k8sServiceHost: "172.20.0.5"
k8sServicePort: "6443"
kubeProxyReplacement: true

Cilium Users Document

  • Are you a user of Cilium? Please add yourself to the Users doc

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

  1. added
    kind/bugThis is a bug in the Cilium logic.
    needs/triageThis issue requires triaging to establish severity and affected area.
    kind/community-reportThis was reported by a user in the Cilium community, eg via Slack.
    on Jul 29, 2026
  2. mkhazamipour commented on Jul 29, 2026

    @mkhazamipour
    Author

    After further testing, I no longer believe this is a regression.

    I tested the same configuration with v1.20.0-rc.1. The Gateway status already reported the overlapping HTTPS termination and TLS passthrough listeners as:

    Conflicted=True/ProtocolConflict
    Accepted=False/Invalid
    Programmed=False/Pending
    

    However, the routes still worked because the rejected listeners were incorrectly translated into the Envoy configuration. This appears to be the behavior described in #46917 and subsequently fixed by #47306.

    Therefore, the configuration only worked accidentally in previous versions despite already being considered invalid. The final v1.20.0 correctly enforces the listener status by excluding conflicted listeners from the Envoy configuration.

    For this use case, the correct alternatives appear to be:

    1. Use two separate Gateways with different IP addresses: one for HTTPS termination and another for TLS passthrough.
    2. Terminate TLS at the Gateway and use HTTPRoute/GRPCRoute with BackendTLSPolicy when encrypted traffic to the backend is required.

    Based on this, I do not think the current v1.20.0 behavior is a bug.

  3. added
    kind/questionFrequently asked questions & answers. This issue will be linked from the documentation's FAQ.
    and removed
    kind/bugThis is a bug in the Cilium logic.
    needs/triageThis issue requires triaging to establish severity and affected area.
    on Jul 31, 2026
  4. self-assigned this
    on Aug 3, 2026
  5. asauber commented on Aug 3, 2026

    @asauber
    Member

    As you mentioned, this issue was fixed with #47306 (and other cases were fixed by #47457).

    Since you no longer thingk that the behavior is unexpected, I will close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

feature/k8s-gateway-apikind/community-reportThis was reported by a user in the Cilium community, eg via Slack.kind/questionFrequently asked questions & answers. This issue will be linked from the documentation's FAQ.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions