AlinsRan opened a new pull request, #2882:
URL: https://github.com/apache/apisix-ingress-controller/pull/2882

   ## What this does
   
   APISIX's stream proxy can now forward a TLS stream to the upstream untouched 
while still picking that upstream from the SNI, which it prereads from the 
`ClientHello` rather than learning from a handshake it performed itself 
(apache/apisix#13912). A stream listen opts in per port:
   
   ```yaml
   apisix:
     stream_proxy:
       tcp:
         - addr: 9110
           tls: true              # terminate (unchanged)
         - addr: 9120
           tls_passthrough: true  # pass everything through
   ```
   
   That is exactly what Gateway API asks of a listener in `Passthrough` mode, 
and it is the one thing the stream subsystem could not do before: routing by 
SNI implied terminating.
   
   So a `Passthrough` listener behaved as `Terminate`. The translator never 
looked at `tls.mode`, the gateway decrypted a stream the backend was supposed 
to own, and the handshake failed against a certificate the gateway does not 
have.
   
   - `TranslateTLSRoute` reads the `tls.mode` of the listeners the route 
attached to and sets `tls_passthrough` on the stream routes bound to a 
`Passthrough` port. The TLSRoute reconciler populates `tctx.Listeners` for 
that, which the TCPRoute and UDPRoute ones already did.
   - Every matched listener on a port has to agree. A physical stream listen is 
either terminating or prereading, never both, so listeners that disagree fall 
back to terminating rather than to a guess. Within one Gateway such a port is 
already `ProtocolConflict` and attaches no routes at all, so this only concerns 
a port two different Gateways disagree about.
   
   ## Two adjacent defects fixed in the same code
   
   Both are pre-existing; passthrough is what made them worth fixing now.
   
   1. **Multiple hostnames collapsed onto one stream route.** The per-hostname 
loop built `ComposeStreamRouteName(ns, name, ruleIndex, "TLS")` — no hostname 
in the key — so N hostnames produced N StreamRoutes sharing one name, hence one 
id, and only the last survived the sync. One StreamRoute now carries them all: 
`sni` for a single hostname, `snis` beyond that. Never both — APISIX rejects a 
stream route carrying both (`not: {required: ["sni", "snis"]}`), and keeping 
`sni` for the single case means the common path still works against any APISIX 
version.
   2. **No `server_port` isolation.** TLSRoute did not go through 
`buildL4StreamRoutes`, so several listener ports fell onto one portless 
StreamRoute that matched every connection on every stream listen — the 
TCPRoute/UDPRoute side of this was #2802. TLSRoute now uses the same per-port 
fan-out, gated by the same `listener_port_match_mode`, so behaviour with the 
shipped default (`off`) is unchanged.
   
   Also: a TLSRoute with **no** hostnames used to produce no StreamRoute at all 
— attached, but unserved. It now falls back to the matched listener hostnames 
and, failing those, to the catch-all `*`.
   
   ## Conformance
   
   The four TLSRoute tests pinned to `mode: Passthrough` are no longer skipped:
   
   - `TLSRouteSimpleSameNamespace`
   - `TLSRouteHostnameIntersection`
   - `TLSRouteInvalidBackendRefNonexistent`
   - `TLSRouteInvalidBackendRefUnknownKind`
   
   `TLSRoute` is a CORE feature of the GATEWAY-TLS profile, so nothing is added 
to `SUPPORTED_EXTENDED_FEATURES`.
   
   Their Gateway listener is fixed at port 443, and the suite dials the Gateway 
address there. One port cannot serve both HTTP-over-TLS and an untouched 
stream, so the conformance data plane points its 443 service port at APISIX's 
stream `tls_passthrough` listen instead of its HTTP ssl listen 
(`DeployDataplaneOptions.ServiceHTTPSTargetPort`). The HTTPRoute tests that 
would want HTTP-over-TLS on 443 — `HTTPRouteHTTPSListener`, 
`HTTPRouteRedirectPortAndScheme` — are already skipped for unrelated SAN 
reasons. The e2e data plane keeps 443 on the HTTP ssl listen and exposes the 
passthrough listen on 9120 of its own.
   
   `TLSRouteModeMixed` is deliberately **not** claimed. Claiming it would 
require relaxing `portsWithConflictingTLSMode` and making the provisional 
`TLSRouteMixedTerminationSameNamespace` pass on a mixed listen; that is a 
follow-up.
   
   ## Tests
   
   - `internal/adc/translator/tlsroute_test.go` — the mode of each port drives 
`tls_passthrough` (passthrough, terminate, omitted-mode, per-port, disagreeing 
listeners, portless, no listener); `sni` vs `snis`; the hostname fallbacks; 
per-port fan-out producing distinct ids.
   - `test/e2e/gatewayapi/tlsroute.go` — a `Passthrough` listener on 9120 in 
front of the e2e nginx, with the client verifying the served chain against the 
**backend's** CA. The gateway holds no certificate for a Passthrough listener 
(it takes no `certificateRefs`), so a chain that validates there can only have 
come from the backend — which is what passthrough means.
   
   `make lint` and `make test` are clean; `make generate manifests` produces no 
drift.
   
   ## Dependencies and verification status
   
   - **Requires api7/adc#618.** ADC's `streamRouteSchema` is a `z.strictObject` 
and its Rust `StreamRoute` is `deny_unknown_fields`, so 
`tls_passthrough`/`snis` are rejected until that lands. `tls_passthrough` is 
only emitted for a `Passthrough` listener and `snis` only for more than one 
hostname, so a Terminate-only single-hostname setup — everything that works 
today — serializes byte-identically and is unaffected by the ADC version.
   - `Makefile`'s `CONFORMANCE_DATAPLANE_VERSION` (3.17.0) predates 
apache/apisix#13912, so a **release** conformance report has to wait for the 
first APISIX release carrying it. A dev run picks it up from `apisix:dev` 
already; a comment now records that.
   - The conformance suite has not been run end to end yet — it needs both the 
ADC change and an `apisix:dev` carrying #13912. The 443 remapping above is 
reasoned from the conformance manifests (no non-skipped test in the enabled 
profiles sends HTTPS traffic to 443), not yet observed.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to