Phase 8d: daemon binds a second QuicServer on the tailnet interface #66
@@ -197,6 +197,16 @@ impl ClusterServices {
|
||||
.rpc_lan()
|
||||
.or_else(|| cluster.rpc_tailscale())
|
||||
.context("no RPC bind address (need bind_lan or bind_tailscale)")?;
|
||||
// Phase 8d (2026-07-14): when BOTH LAN and tailnet
|
||||
// addresses are configured, we also bind a second
|
||||
// QuicServer on the tailnet interface. The gossip
|
||||
// layer already publishes `rpc_tailscale` so peers
|
||||
// learn to dial it; without the second bind the
|
||||
// advertised address just refuses connections.
|
||||
let bind_tailnet = match (cluster.rpc_lan(), cluster.rpc_tailscale()) {
|
||||
(Some(lan), Some(ts)) if lan != ts => Some(ts),
|
||||
_ => None,
|
||||
};
|
||||
let outbound_client = crate::cluster::transport::QuicClient::new(
|
||||
"0.0.0.0:0".parse().expect("literal 0.0.0.0:0 parses"),
|
||||
client_identity,
|
||||
@@ -228,6 +238,34 @@ impl ClusterServices {
|
||||
let task = tokio::spawn(async move {
|
||||
accept_forever(server, router_for_accept).await;
|
||||
});
|
||||
// Phase 8d: second bind for the tailnet interface,
|
||||
// when configured. Shares the same identity + router
|
||||
// as the LAN listener — connections from either side
|
||||
// hit the same handlers.
|
||||
if let Some(ts_addr) = bind_tailnet {
|
||||
let ts_identity =
|
||||
NodeIdentity::from_pem_files(&tls.ca_cert, &tls.node_cert, &tls.node_key)
|
||||
.context(
|
||||
"loading node identity for tailnet QUIC server",
|
||||
)?;
|
||||
match QuicServer::bind(ts_addr, ts_identity) {
|
||||
Ok(ts_server) => {
|
||||
tracing::info!(
|
||||
"cluster RPC server also listening on {} (tailnet)",
|
||||
ts_addr
|
||||
);
|
||||
let router_for_ts = router.clone();
|
||||
tokio::spawn(async move {
|
||||
accept_forever(ts_server, router_for_ts).await;
|
||||
});
|
||||
}
|
||||
Err(e) => tracing::warn!(
|
||||
error = %e,
|
||||
addr = %ts_addr,
|
||||
"tailnet RPC bind failed; LAN listener still active"
|
||||
),
|
||||
}
|
||||
}
|
||||
(Some(router), Some(task))
|
||||
}
|
||||
None => {
|
||||
|
||||
Reference in New Issue
Block a user