-
Notifications
You must be signed in to change notification settings - Fork 274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: allow AutoNAT to dial all IP addresses, without risking amplification attacks #536
Comments
What benefits do we get by allowing this? Some preliminary thoughts, This scheme makes amplification attacks difficult but allows for generating large transient load on a target. The way to do this would be to open streams with a lot of autonat servers. give them the ip of the target and then slowly send them 10-100kb of requested data such that all of them get this data at the same time. However, this would necessarily be transient since the attacker would not have the resources to execute this for a long time. |
Another workaround i can think of is that the attacker uses identify to launch an attack on a target. |
I have the same question. In other words, in which scenario would the local node want a remote node want to probe a different IP than the one the local node is observed as? In the case where the local node has multiple public facing interfaces? Do we have that use-case anywhere today?
I don't think this is correct. The "peers" don't actively probe a peer's IP addresses based on the peer's identify payload. Instead the peer (here the "attacker") initiates the AutoNAT process, potentially including the additional anti-amplification payload. |
I wasn't clear here. I merged two streams of thought one related to having address pipeline here and one related to autonat v2 allowing you to test reachability on a single address. My assumption here is that with autonat v2, nodes will try to verify reachability on all externally observed addresses. When nodes receive a new observed address in identify, they will try to test its public reachability. The scenario I describe is this.
The attacker can repeat this scheme for other peers that connect to it. |
I do see the benefits now for this case. If a node has multiple interfaces this does decouple testing addresses via autonat from the interface we dialled the autonat server to. Without this feature we have to ensure that we make a connection to the autonat server using the same interface that we are interested in testing. |
Good question, @sukunrt and @mxinden! Two network interfaces would definitely be a use case, as would NATs that use multiple IP addresses for their mappings. I'm wondering if we should quantify how many times we're asked to dial addresses that don't match the observed address of the connection we receive the request on. This could probably be added as a simple log statement in the AutoNAT server implementation, logging Another use case for this would be Kubo's
@sukunrt is right, at least for go-libp2p. We have this component called "observed address manager" that lives alongside Identify, and discovers new addresses (once reaching a certain threshold). Don't you have something like that in rust-libp2p, @mxinden? How do you discover your public addresses then? |
That's possible, but I'd argue that this attack is not very interesting. First of all, the attacker needs to connect to B to tell it the address of T. This means he has to complete one libp2p handshake, to get S to initiate one handshake to T. So there's no amplification here. At the very best, the attacker can hope to achieve some bunching here, temporarily overloading T (since an Identify message is smaller than a libp2p handshake). We could also harden Identify and disregard addresses that we only see on inbound connections (we already keep track of the directionality in the observed address manager today). That would make it even harder to pull of this attack, since you'd somehow need to convince B to connect to A first. |
I think your argument is sound. I'm sorry if this is a very basic question but what was the reason for disallowing this in the first place? I have not read the STUN RFC closely so I might be missing something here but it seems to me like https://www.rfc-editor.org/rfc/rfc5389#section-16.2.1 is about the case where a malicious or compromised STUN server is replying to STUN requests with ip address of the target.
this section talks about ip spoofing https://www.rfc-editor.org/rfc/rfc8489#section-16.1.2 to get the stun server to send a response to a target.
This seems fine for our case since autonat doesn't send any payload to the address it is verifying. In fact I think the older version of the STUN RFC allowed sending responses to a different address from the one the request was received on |
All I can think of is that the attacker could do all the handshakes in advance, and then fire of all the AutoNAT requests at once. I'm not convinced this is actually a problem though. This was introduced in #369. @mxinden, what made you think that this is necessary? |
@mxinden, friendly ping. |
There is an issue with asking a ip4 peer to dial an ip6 address. The peer might not be able to dial the ip6 address. My isp is completely ip4 and when I dial a ip6 address, the error I receive from the networking stack is one way to fix this is to only ask for ip4 dials on a ip4 connection and ip6 dials on a ip6 connection. |
Below A is the attacker, T the target and S the AutoNAT server.
In AutoNATv1 (i.e. current AutoNAT) I see two amplification mechanisms:
Relevant section in the AutoNAT v1 specification:
https://github.com/libp2p/specs/tree/master/autonat Does this better explain the reasoning for #369? |
These are valid cases. Thanks @mxinden. We definitely cannot remove this restriction without introducing the scheme suggested. The suggested scheme is resistant to both these attacks.
A will need to send data that is costlier than a handshake
In Autonat v2 S will only dial one address. The attack I proposed is also easily handled by a smart client implementation.
Even if the attacker repeatedly uses identify push to get amplification, the addresses suggested by the attacker A will be lower priority addresses for peer B and B will not pay the cost of verifying these addresses. See this comment for a client implementation resistant to such attacks. #539 (comment) |
@marten-seemann talked with @sukunrt and this has been rolled into the larger autonat spec. are we good to close this? |
Should we keep this open until the spec is merged? Not a strong preference, but technically this issue isn’t resolved until that point. |
Our AutoNAT spec currently says:
The intention is to prevent an amplification attack against a target, and was designed with the properties of the STUN protocol in mind.
This is not the only way to prevent amplification attacks though. We can also just make the attack expensive enough such that it becomes unattractive. For example, we could require the requester to send a non-trivial amount of data, on the order of 10-100 kB. This would make AutoNAT completely uninteresting for an amplification attack, since a libp2p handshake is a lot smaller than 10 kB, and thus no amplification can be achieved.
On the other hand, for the AutoNAT server, receiving 10-100 kB is cheap enough to process that we're not placing a too large burden on the server. To further lighten the load on the server, this could be designed as a "retry" mechanism (borrowing QUIC terminology here): Only if the IP address doesn't match would the server request the client to send this additional data.
Obviously, as this is a new design, this would need to be incorporated into AutoNAT v2 (#503).
@sukunrt Thoughts?
The text was updated successfully, but these errors were encountered: