Skip to content

fix(libp2p): quieter dead-listener check#11342

Merged
lidel merged 3 commits into
masterfrom
fix/server-profile-addrfilters-split
Jun 5, 2026
Merged

fix(libp2p): quieter dead-listener check#11342
lidel merged 3 commits into
masterfrom
fix/server-profile-addrfilters-split

Conversation

@lidel

@lidel lidel commented May 29, 2026

Copy link
Copy Markdown
Member

What was broken

The dead-listener check added in #11299 (v0.42) logs an ERROR for every Addresses.Swarm listener whose IP falls inside an Addresses.NoAnnounce or Swarm.AddrFilters CIDR. On a server-profile node with default /ip4/0.0.0.0 and /ip6/:: listens, the wildcards expand to every interface (loopback, Docker bridge 172.17.0.1, ULA fd7d:...), each matching a server-profile CIDR. Result: 20+ ERROR lines at startup describing intentional behavior, drowning the actual signal: an explicit /ip4/127.0.0.1/tcp/.../ws listener fronted by nginx or Caddy that the gater silently RSTs.

How this PR fixes it

Findings route by source and origin:

  • Swarm.AddrFilters + explicit listen in Addresses.Swarm: ERROR. The whole listener is unreachable (the reverse-proxy gotcha).
  • Swarm.AddrFilters + wildcard expansion: DEBUG. Other interfaces still serve.
  • Addresses.NoAnnounce match: DEBUG. Useful when tracing identify or DHT contents.

The v0.42 release notes are updated to describe the routed behavior.

Scope the v0.42 dead-listener ERROR to explicit listens in
Addresses.Swarm: a server-profile node with default `/ip4/0.0.0.0`
and `/ip6/::` listens otherwise logged ERROR for every loopback,
Docker bridge, ULA, or other private interface the wildcard
expanded into, drowning the actual gotcha (a `/ip4/127.0.0.1/tcp/.../ws`
listener fronted by a local reverse proxy).

Log routing:

- AddrFilters + explicit listen: ERROR (whole listener unreachable).
- AddrFilters + wildcard expansion: DEBUG (other interfaces still
  serve).
- NoAnnounce match: DEBUG (operator intent, useful when tracing
  identify or DHT contents).
@lidel lidel mentioned this pull request May 29, 2026
40 tasks
@lidel lidel marked this pull request as ready for review May 29, 2026 20:15
@lidel lidel requested a review from a team as a code owner May 29, 2026 20:15
lidel added 2 commits June 2, 2026 15:43
Explicit-ness keyed on the listener IP alone, so a wildcard listen
expanding onto an interface whose IP was also bound explicitly on
another port (server profile plus a /ip4/127.0.0.1/.../ws reverse
proxy) was logged as a spurious ERROR. Match the full resolved
multiaddr instead: InterfaceListenAddresses echoes a specific-IP
listen verbatim while a wildcard never resolves to itself.
Classify a dead listener as explicit by its bound socket (IP, transport,
port) instead of the full multiaddr string. A listener is reported under a
different multiaddr than its Addresses.Swarm entry once a transport
rewrites trailing components: WebTransport appends /certhash, WebSocket
turns /wss into /tls/ws. The string compare missed these and silently
downgraded the affected explicit listeners from ERROR to DEBUG, hiding the
reverse-proxy gotcha the check exists to surface.

The transport is part of the key because TCP and QUIC share a port number
by default (4001), so a pinned QUIC listener must not promote the same-port
TCP wildcard expansion to ERROR.
@lidel lidel merged commit 26d5ee1 into master Jun 5, 2026
22 checks passed
@lidel lidel deleted the fix/server-profile-addrfilters-split branch June 5, 2026 12:31
lidel added a commit that referenced this pull request Jun 5, 2026
* fix(libp2p): quieter dead-listener check

Scope the v0.42 dead-listener ERROR to explicit listens in
Addresses.Swarm: a server-profile node with default `/ip4/0.0.0.0`
and `/ip6/::` listens otherwise logged ERROR for every loopback,
Docker bridge, ULA, or other private interface the wildcard
expanded into, drowning the actual gotcha (a `/ip4/127.0.0.1/tcp/.../ws`
listener fronted by a local reverse proxy).

Log routing:

- AddrFilters + explicit listen: ERROR (whole listener unreachable).
- AddrFilters + wildcard expansion: DEBUG (other interfaces still
  serve).
- NoAnnounce match: DEBUG (operator intent, useful when tracing
  identify or DHT contents).

* fix(libp2p): match explicit listens by full addr

Explicit-ness keyed on the listener IP alone, so a wildcard listen
expanding onto an interface whose IP was also bound explicitly on
another port (server profile plus a /ip4/127.0.0.1/.../ws reverse
proxy) was logged as a spurious ERROR. Match the full resolved
multiaddr instead: InterfaceListenAddresses echoes a specific-IP
listen verbatim while a wildcard never resolves to itself.

* fix(libp2p): match explicit listens by socket

Classify a dead listener as explicit by its bound socket (IP, transport,
port) instead of the full multiaddr string. A listener is reported under a
different multiaddr than its Addresses.Swarm entry once a transport
rewrites trailing components: WebTransport appends /certhash, WebSocket
turns /wss into /tls/ws. The string compare missed these and silently
downgraded the affected explicit listeners from ERROR to DEBUG, hiding the
reverse-proxy gotcha the check exists to surface.

The transport is part of the key because TCP and QUIC share a port number
by default (4001), so a pinned QUIC listener must not promote the same-port
TCP wildcard expansion to ERROR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants