Skip to content
This repository has been archived by the owner on Sep 9, 2022. It is now read-only.

base limits on reservations issued #132

Merged
merged 9 commits into from
Aug 5, 2021
Merged

Conversation

marten-seemann
Copy link
Contributor

... and don't care about reservations that are removed (and fulfilled).

That means a relay won't issue more than 128 reservations per 30 minute interval, no matter how many of them are used. There are further limits per peer, IP and ASN, that all work the same (limiting the number of reservations per 30 minute interval).

Copy link
Contributor

@vyzo vyzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really better?
We record the reservation before we actually error out and don't remove it then. Doesn't this make it easier to DoS us?

Note: the refactoring of all constraints together is nice and very welcome.

@marten-seemann
Copy link
Contributor Author

I'm not sure I understand how this makes us easier to DoS.

Before this PR, we'd send out reservations (up to a certain limit). Once a reservation has been used up, we don't count it towards our limits any more. If it's not used, it's garbage collected after a while. This, as @Stebalien noted, would allow a node to DoS us by repeatedly making a reservation and immediately using it.
With this PR, we continue counting this reservation, even if it's used. After 30 minutes it is garbage collected, no matter if it has been used or not.

A DoS is only possible if the attacker controls multiple IP addresses (the limit per peer ID doesn't provide any DoS protection, as peer IDs are trivial to generate), as we're limiting the number of reservations to MaxReservationsPerIP (default: 4), whereas the total number of reservations is limited to MaxReservations (default: 128). Of course, a DDoS would still be easy to pull off, but this applied to the situation before as well, didn't it?

@vyzo
Copy link
Contributor

vyzo commented Jul 12, 2021

Hrm, you know, this might indeed better than what we have (refactoring aside, which certainly is :)

My concern is that a bunch of peers connect to you, make a reservation each, go over the liimit, and then just disconnect.
That would leave the peer without any reservation slots even though it can serve new peers.

@marten-seemann
Copy link
Contributor Author

My concern is that a bunch of peers connect to you, make a reservation each, go over the liimit, and then just disconnect.
That would leave the peer without any reservation slots even though it can serve new peers.

Hm. I guess that's by design, isn't it? We limit each relay's utilization to values far below what they could handle, if they're running on decent hardware and with a decent connection. We do this so we can justify turning it on by default.

@Stebalien, wdyt?

v2/relay/resources.go Outdated Show resolved Hide resolved
@marten-seemann
Copy link
Contributor Author

@Stebalien Friendly ping.

@Stebalien
Copy link
Member

Hm. I guess that's by design, isn't it? We limit each relay's utilization to values far below what they could handle, if they're running on decent hardware and with a decent connection. We do this so we can justify turning it on by default.

We could oversubscribe by some amount, but that's probably overkill. I'd leave it as-is for now and change it if we notice issues.

@Stebalien
Copy link
Member

It's always possible to give the hydras a high limit...

v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved
v2/relay/constraints.go Outdated Show resolved Hide resolved

func (c *constraints) cleanup(now time.Time) {
c.total = c.cleanupList(c.total, now)
for k, peerReservations := range c.peers {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small optimization: we can return early when nothing has expired (when c.total wasn't updated).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, but I'm not sure if it's worth it. This seems like an easy place to introduce non-obvious bugs in the future.

@marten-seemann marten-seemann merged commit c64849f into circuit-v2 Aug 5, 2021
@vyzo vyzo deleted the rework-limits branch August 5, 2021 19:36
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants