chengxilo opened a new issue, #3890:
URL: https://github.com/apache/iggy/issues/3890

   ### Bug description
   
   ## Summary
   
   A server whose TCP listener binds a wildcard reports that wildcard as its 
own client-facing address in `GetClusterMetadata`. The Go SDK collects roster 
addresses into its reconnect candidate ring, so `0.0.0.0:8090` becomes a dial 
target.
   
   ## Reproduction
   
   The shipped BDD compose file already reproduces it. In 
`bdd/docker-compose.server.yml`.
   
   
https://github.com/apache/iggy/blob/7c0fd68421aa610897fdbc7331f1cb22848fb386/bdd/docker-compose.server.yml#L32
   
   
https://github.com/apache/iggy/blob/7c0fd68421aa610897fdbc7331f1cb22848fb386/bdd/docker-compose.server.yml#L67
   
   Confirmed directly by varying only the bind address on one binary:
   
   | Bind | Client dialed | Reported IP |
   | ---- | ------------- | ----------- |
   | `127.0.0.1:8090` | `127.0.0.1:8090` | `127.0.0.1` (usable) |
   | `0.0.0.0:8190` | `127.0.0.1:8190` | `0.0.0.0` (not usable) |
   
   With the cluster disabled, `ClusterRoster::cluster_metadata` reports 
`self_ip`, which is assigned the bind address verbatim:
   
   ```rust
   // core/server/src/bootstrap.rs:1719
   self_ip: topology.client_listen_addr.ip().to_string(),
   ```
   
   ## What the Go SDK does with it
   
   1. Every sign-in runs leader settlement: `settleOnLeader` 
(`foreign/go/client/tcp/tcp_session_management.go:69`).
   2. `clusterAddresses` (`foreign/go/internal/util/leader_aware.go:126`) 
collects an address for every healthy node, unconditionally.
   3. Those land in `knownServerAddresses` 
(`foreign/go/client/tcp/tcp_session_management.go:212`).
   4. `connectionCandidates` (`foreign/go/client/tcp/tcp_core.go:998`) appends 
them to the configured addresses, and `Connect` rotates through the result on 
every retry (`tcp_core.go:924`).
   
   Result for the reproduction above: `["iggy-server:8090", "0.0.0.0:8090"]`.
   
   
   ## Root cause
   
   The advertised-address mechanism already exists and is complete for roster 
nodes: `ClusterNodeConfig.advertised_address` plus the client-CIDR-scoped 
`advertised_addresses` selectors 
(`core/configs/src/server_config/cluster.rs:369-377`), with strict boot 
validation (`cluster.rs:978-1042`) and cross-node endpoint conflict detection 
(`cluster.rs:1357`).
   
   `self_metadata()` (`cluster_meta.rs:134`) does not participate in any of it. 
It is a parallel path that substitutes the bind address, manufacturing an 
addressthe server does not actually know.
   
   ## Proposed fix
   
   Publish only dialable address
   
   A concrete bind IP is an interface the operator named, so it is reported 
as-is and that path is unchanged. An unspecified one carries no client-facing
   information, so the node publishes no address at all.
   
   Nothing is invented to fill the gap. The self node is the one node whose 
address a client never needs told: it is already connected to it, and with a 
single-node roster there is nowhere to fail over to. Empty is already a value 
the wire carries, via `ClusterRoster::disabled()` (`cluster_meta.rs:80`), so no 
protocol change is involved. 
   
   ### Affected area / component
   
   _No response_
   
   ### Deployment
   
   None
   
   ### Versions
   
   _No response_
   
   ### Hardware / environment
   
   _No response_
   
   ### Sample code
   
   _No response_
   
   ### Logs
   
   _No response_
   
   ### Iggy server config
   
   _No response_
   
   ### Reproduction
   
   _No response_
   
   ### Contribution
   
   - [ ] I'm willing to submit a pull request to fix this bug
   
   ### Good first issue
   
   - [ ] I think this could be a good first issue for a new contributor


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