libp2p / libp2p/specs

Rethink autonat v2 amplification attack prevention

Open
#640 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
1.8k
Forks
320
Avg merge
11d 15h
Merged PRs (30d)
1

Description

This features enables the following attack:
- Contact a large number of autonat v2 servers.
- Give them the target's address to connect to
- When requested for data: provide the data slowly:
* The stream timeout is 1 minute
* In the period, with a 1Gbps connection, you can send 60Gb ~= 6GB
* Maximum dial data requirement is 100kB
* So, in theory, you can run this with 60_000 peers in parallel.
* The servers have a random wait of up to 3 seconds precisely for this scenario. So in theory we can have 20k connections a second for 3 seconds to the target.
- We can make a bunch of implementation improvements to reduce the harm here. The simplest ones being: Only wait 10 seconds for the dial data, and wait for 5 seconds before dialing. That would reduce the max new connection rate to 2k / second, which is very manageable.
- The ideal solution is to introduce rate limits for new connections.

  • There's another problem with this feature related to implementation difficulty:
    • The primary use for this feature is to allow both IPv4 and IPv6 addresses to be tested without worrying about whether we have a v4 or a v6 connection. So you can ask a v4 peer to test your v6 address. This requires correctly reporting an error in case the server has no v6 connectivity, which is majority of servers.
    • I'm not sure if the rust implementation correctly handles this case. @umgefahren please correct me if I'm wrong here.
      * See discussion around this comment: https://github.com/umgefahren/rust-libp2p/pull/1#issuecomment-2168354437
    • I'm also not sure if we can rely on other implementations to correctly handle this. They might just make a dial, fail, and report unreachable.
  • If we have to ensure that we check v6 addresses with a v6 peer, it might be better to just disable this feature.

@MarcoPolo @Stebalien @umgefahren thoughts?

Originally posted by @sukunrt in https://github.com/libp2p/specs/pull/538#discussion_r1781405889

Avoiding a cryptographic handshake in the dial back stream will make this attack useless. All you'll get are a couple of packets from the server. Moreover, we want to check reachability for the tuple (IP4/IP6, TCP/UDP), not issues with the transport handshake implementation. For UDP, this can be implemented with a scheme similar to the one used by QUIC with Retry Packet. The server can send a UDP packet with a random 64 bit number which is echoed back by the client. We can design a similar lightweight protocol over TCP.

Contributor guide

No contributing guide indexed for this repository

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 with the autonat v2 discussion in this issue and the linked rust-libp2p pull request comment, then review the design in specs pull request 538. Done means the specification has an agreed approach that addresses amplification, defines reachability checks for IP4/IP6 and TCP/UDP, and explains behavior when the probing peer lacks the required connectivity.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.