libp2p / libp2p/rust-libp2p

AutoNAT v2 can initiate unwanted connections to non-public addresses

Open
#6,610 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.6k
Forks
1.3k
Avg merge
8h 47m
Merged PRs (30d)
19

Description

Summary

An untrusted AutoNAT v2 client can submit a loopback or private IP address and make the server attempt a connection from its own network position. Peer-ID validation prevents the target from completing the dial-back as the requester, but it does not prevent the initial connection attempt.

Expected behavior

The server should reject explicit non-public IP targets with E_DIAL_REFUSED, as recommended by the current AutoNAT v2 specification.

Actual behavior

After applying the required cross-IP data cost, the server passes the selected Multiaddr directly to DialOpts without checking its address class. The existing dial_back_to_non_libp2p test already exercises /ip6/::1/tcp/1000 and observes the connection failure.

Relevant log output
Add this test to `protocols/autonat/tests/autonatv2.rs`:


#[tokio::test]
async fn private_loopback_request_causes_outbound_dial() {
    let (mut server, mut client) = bootstrap().await;
    let addr: Multiaddr = "/ip6/::1/tcp/1000".parse().unwrap();

    client.behaviour_mut().autonat.on_swarm_event(
        FromSwarm::NewExternalAddrCandidate(NewExternalAddrCandidate { addr: &addr }),
    );

    tokio::select! {
        _ = server.wait(|event| match event {
            SwarmEvent::Dialing { connection_id, .. } => Some(connection_id),
            _ => None,
        }) => {}
        _ = client.loop_on_next() => unreachable!(),
    }
}


Run:


cargo test -p libp2p-autonat --test autonatv2 private_loopback_request_causes_outbound_dial -- --exact


The test passes because submitting the loopback candidate causes a new outbound dial.
Possible Solution

Reject explicit loopback, private, link-local, unspecified, and multicast IP addresses before emitting ToSwarm::Dial. DNS addresses need separate handling because their resolved IP is not available while parsing the request.

Version

Confirmed with libp2p-autonat 0.16.0 at commit 850319b. Earlier versions were not assessed.

Would you like to work on fixing this bug?

Maybe

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in protocols/autonat/tests/autonatv2.rs and run the named private_loopback_request_causes_outbound_dial test to reproduce the unwanted dial. Then trace AutoNAT v2 request handling through the point where the selected Multiaddr reaches DialOpts. Done means explicit non-public IP targets are refused with E_DIAL_REFUSED while DNS addresses retain their separate handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.