AlinsRan opened a new pull request, #13911:
URL: https://github.com/apache/apisix/pull/13911

   ### Description
   
   ### Why
   
   Gateway API `TLSRoute.hostnames` is a **list** of SNI names, but the stream 
router can only
   express one SNI per route: `stream_route.sni` is a single string and
   `apisix/stream/router/ip_port.lua` does `route.sni:reverse()`. An ingress 
controller therefore has
   to fan a multi-hostname `TLSRoute` out into N `stream_routes`, which 
duplicates the plugins and the
   traffic-split state once per SNI.
   
   `service.hosts` already exists and uses the same `host_def_pat` as 
`stream_route.sni`, so it can
   already hold exactly the values `sni` can, wildcards included. It was simply 
never consulted by the
   stream router.
   
   ### What
   
   `create_router()` now registers one radixtree path per SNI instead of one 
per route, and takes the
   SNI list from:
   
   1. `stream_route.sni`, when it is set;
   2. otherwise the `hosts` of the service the route references.
   
   This mirrors the host precedence the HTTP router already implements in
   `apisix/http/router/radixtree_host_uri.lua`.
   
   Two details worth calling out:
   
   * A bare `*` host means "no SNI restriction": the route stays in the 
address-matched set, exactly
     as a route without `sni` does today. Reversed into the radixtree it would 
only ever match a
     literal `*`.
   * The service hosts are lowercased when the router is built, because 
`apisix/ssl.lua`'s
     `server_name()` returns a lowercased SNI — `apisix/router.lua` already 
does the same for the
     `hosts` of an HTTP route.
   
   ### Backward compatibility
   
   **This is a behavior change.** Today a `stream_route` that has no `sni` and 
whose `service_id`
   points at a service that has `hosts` matches *every* SNI on the port; 
afterwards it matches only
   those hosts. Sharing one service between HTTP routes and stream routes is 
unusual but possible, so
   such a deployment will see stream connections whose SNI is outside the 
service's `hosts` stop
   matching that route.
   
   ### Tests
   
   `t/stream-node/service-hosts.t` covers:
   
   * a multi-host service matched on each of its hosts, and not matched on a 
host it does not carry;
   * `stream_route.sni` taking precedence over the hosts of the service;
   * a wildcard host (`*.test.com`);
   * a bare `*` host falling through to the address-matched routes;
   * a mixed-case host (`Mixed.TEST.com`) matched by a lowercase SNI.
   
   The TLS requests are issued from inside the same nginx instance that 
performs the setup, so the
   SNI router is only exercised once the stream subsystem has synced the 
configuration from etcd —
   unlike `--- stream_tls_request`, which restarts nginx and then races the 
etcd sync in
   `ssl_client_hello_by_lua`.
   
   ### Related
   
   The same change is applied to the API7 enterprise gateway in 
api7/api7-ee-3-gateway#2199 (private
   repository); the two `apisix/stream/router/ip_port.lua` files are kept 
identical for this feature.
   
   ### Checklist
   
   - [x] I have explained the need for this PR and the problem it solves
   - [x] I have explained the changes or the new features added to this PR
   - [x] I have added tests corresponding to this change
   - [x] I have updated the documentation to reflect this change
   - [ ] I have verified that this change is backward compatible — see the 
"Backward compatibility"
         section above; a stream route with no `sni` whose service carries 
`hosts` becomes restricted
         to those hosts.
   


-- 
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