Skip to content

Commit 11d6f96

Browse files
fix(agent-tunnel): bind QUIC sockets dual-stack
Both the gateway listener and the agent client socket previously bound to 0.0.0.0 (IPv4 only). When the agent's DNS resolution for the gateway endpoint returns an IPv6 address first — the default for `localhost` on modern Windows/Linux, and common for any name with a AAAA record — quinn refuses to send to that peer over a v4 socket and the tunnel never connects. Bind to `[::]` instead so both ends accept v4 and v6.
1 parent b939be2 commit 11d6f96

2 files changed

Lines changed: 8 additions & 2 deletions

File tree

devolutions-agent/src/tunnel.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,11 @@ async fn run_single_connection(
337337

338338
// -- Connect --
339339

340+
// Bind to the IPv6 unspecified address so the client socket is dual-stack.
341+
// A v4-only socket (0.0.0.0:0) cannot reach a peer resolved to an IPv6 address,
342+
// which is the default `localhost`/AAAA-record case on modern systems.
340343
let mut endpoint =
341-
quinn::Endpoint::client("0.0.0.0:0".parse().context("parse bind address")?).context("create QUIC endpoint")?;
344+
quinn::Endpoint::client("[::]:0".parse().context("parse bind address")?).context("create QUIC endpoint")?;
342345
endpoint.set_default_client_config(client_config);
343346

344347
let connection = endpoint

devolutions-gateway/src/service.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,10 @@ async fn spawn_tasks(conf_handle: ConfHandle) -> anyhow::Result<Tasks> {
283283
let ca_manager = agent_tunnel::cert::CaManager::load_or_generate(&data_dir)
284284
.context("failed to initialize agent tunnel CA")?;
285285

286-
let listen_addr = std::net::SocketAddr::from((std::net::Ipv4Addr::UNSPECIFIED, conf.agent_tunnel.listen_port));
286+
// Bind to the IPv6 unspecified address so the listener is dual-stack and
287+
// accepts both IPv4 and IPv6 agent connections (matters when an agent's DNS
288+
// resolution returns an IPv6 address for the configured gateway endpoint).
289+
let listen_addr = std::net::SocketAddr::from((std::net::Ipv6Addr::UNSPECIFIED, conf.agent_tunnel.listen_port));
287290

288291
let (listener, handle) =
289292
agent_tunnel::AgentTunnelListener::bind(listen_addr, Arc::clone(&ca_manager), hostname)

0 commit comments

Comments
 (0)