-
Notifications
You must be signed in to change notification settings - Fork 4
Conversation
Accepts multiaddrs that define who is allowed.
@marten-seemann / @vyzo this is ready to review. Please take a look. Before merging I'll make sure to finish this checkboxed things in the PR description. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is my understanding correct, that we allow two types of addresses to be whitelisted?
/ip{4,6}/<ip>/
/ip{4,6}/<ip>/p2p/<peerid>
But not/p2p/<peerid>
?
We also need to add configurable limits for the newly introduced allowlist scopes, right?
allowedNetworks []*net.IPNet | ||
|
||
// Only the specified peers can use these IPs | ||
allowedPeerByNetwork map[peer.ID][]*net.IPNet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered unifying these into a single map? map[net.IPNet]struct{ allowsAll bool; map[peer.ID]struct{} }
allowsAll
would be set if a multiaddr without /p2p is added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I use net.IPNet as a key? The struct holds two byteslices, so I don't think I can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checked, you can't. That's annoying. You could use net.IPNet.String()
, but not sure if that's nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think so because:
- allow checking is harder. you have to convert between the string and bytes.
- You need to allocate the string on insertion.
- you need to allocate at least once when doing an allowlist check.
- (Depending on check implementation) you lose the quick lookup by peerid. Which may be a pretty common use case.
peer *peerScope | ||
dir network.Direction | ||
usefd bool | ||
isAllowlisted bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: isAllowListed
. Or newAllowlist
instead of newAllowList
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant to call this allowlist
or Allowlist
. Purposely not capitalizing the l. I realize I should change newAllowList
to newAllowlist
to be consistent.
Requesting a review from @vyzo. Can you check how the scopes are getting shifted around? |
Yep! Thank you for reminding me. I just added those with the same limits as the standard scopes.
Correct. I'm not sure what value the |
I agree. I was misled by the |
Friendly ping @vyzo :) |
@MarcoPolo Do you want to include the config changes in this PR, or are you planning to create a follow-up PR for that? |
My plan was after this (see pr description). Since this will work fine without it and the config change is pretty small. And you have some changes around config in #48 in progress. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a public interface and accessor in the rcmgr for the allowlist, plus an allowlist option to initialize.
allowlist.go
Outdated
manet "github.com/multiformats/go-multiaddr/net" | ||
) | ||
|
||
type allowlist struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have an interface type assertion for this, right after the def?
Or is there no public interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to make a public interface for it in extapi, and provide an accessor so that users can modify after initialization.
The RWMutex is a must in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow the reason for a public interface? I thought generally interfaces belonged to the caller.
Interfaces declare the behaviour the caller requires not the behaviour the type will provide. Let callers define an interface that describes the behaviour they expect. The interface belongs to them, the consumer, not you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah is it because we return an interface and we can't have an interface function return this unexported type?
What's the downside of exporting this type then?
Another important consideration here: we should only check the allow list if and only if a regular connection reservation fails. |
I exported the Allowlist type, added an accessor to rcmgr, and added the |
var allowedPeer peer.ID | ||
var isIPV4 bool | ||
|
||
multiaddr.ForEach(ma, func(c multiaddr.Component) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use ma.MultiaddrToIPNet
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not, if we want to extract the p2p
component at the same time, right? We could get that one without iterating again by splitting off the last component though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also need the isIPV4 to save some time below
} | ||
|
||
i := len(ipNetList) | ||
for i > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to use for i, ipnet := range ipNetList
? Do we gain anything from going through the list in reverse order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For swap remove. If we go through in normal order then we would skip an entry after swap remove or do some other messy logic that I think boils down to reverse iterating
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That only applies if you're trying to make multiple deletions from the list. Should be fine if you're break
ing after the first deletion, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah that's true. Although I'm a bit hesitant to change this so that instead of working for N removals it only works for 1 removal and would subtly break if you try to remove more than 1.
And the only reason to make the change is so that we use the syntactic sugar of for ... range
. Is there any other benefit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I'd consider range
more idiomatic (makes it harder to produce out-of-bounds access). No need to change it here.
@marten-seemann anything left? |
This adds the Allowlist to Resource manager. See docs/allowlist.md for the design doc and more details.
This change requires changes to be merged first in go-libp2p-core and go-multiaddr (to support the ipcidr protocol in the multiaddr).
After this is merged, go-libp2p will need to be plumbed with these changes as well.
Before Merge:
ipcidr
After Merge: