Skip to content
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

feat: deny incoming connections and add allow/deny lists #1398

Merged
merged 8 commits into from
Oct 6, 2022

Conversation

achingbrain
Copy link
Member

@achingbrain achingbrain commented Sep 30, 2022

When we reach our connection limit, deny incoming connections before the peer ids are exchanged instead of accepting them and trying to apply the limits after the exchange.

Adds a allow and deny lists of multiaddr prefixes to ensure we can always accept connections from a given network host even when we have reached out connection limit.

Outgoing behaviour remains the same, that is, you can exceed the limit while opening new connections and the connection manager will try to close 'low value' connections after the new connection has been made.

Depends on:

When we reach our connection limit, deny incoming connections before
the peer ids are exchanged instead of accepting them and trying to
apply the limits after the exchange.

Adds a allow and deny lists of multiaddr prefixes to ensure we can
always accept connections from a given network host even when we have
reached out connection limit.
const connections = this.getConnections()

if (connections.length <= this.opts.minConnections || toPrune < 1) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this handled elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

The method prunes the passed number of connections, previously it only did so if we were over the connection limit. We initiate pruning for a number of reasons - if the event loop is lagging too much or we are sending or receiving too much traffic for example - pruning in these cases would have done nothing if we weren't over the connection limit.

@@ -152,6 +164,8 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
private readonly startupReconnectTimeout: number
private connectOnStartupController?: TimeoutController
private readonly dialTimeout: number
private readonly allow: Multiaddr[]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it make sense to use a Set here?

Copy link
Member Author

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 we call .some on it in order to see if the connecting peer's multiaddr is prefixed by anything in the allow list - to do that with a Set we'd have to convert it to an array first.

We could have a separate function that iterates over the Set with a for..of doing the check that returns early, but .some is a one-liner that does the same thing so there seems little benefit?


if (this.getConnections().length < this.opts.maxConnections) {
return
if (maConn.remoteAddr.isThinWaistAddress()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this just checking ip{4,6} + {tcp,udp}? Where does this name come from?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is this just checking ip{4,6} + {tcp,udp}

Yes.

Where does this name come from?

I'm actually not sure. I think it refers to just IP + port, no other protocol information - https://www.oilshell.org/cross-ref.html?tag=narrow-waist#narrow-waist

}

log('maxConnections exceeded')
return false
Copy link
Collaborator

Choose a reason for hiding this comment

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

The caller no longer knows why this connection wasn't accepted. Probably okay, but maybe better to return an error?

Copy link
Member Author

Choose a reason for hiding this comment

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

It logs why the connection was accepted - it's for incoming connections only so it's really just informational for anyone watching the logs.

More idiomatic to throw than return an error but after the conversation here I changed it to return a boolean instead.

src/connection-manager/index.ts Outdated Show resolved Hide resolved
src/connection-manager/index.ts Outdated Show resolved Hide resolved
src/connection-manager/index.ts Outdated Show resolved Hide resolved
src/connection-manager/index.ts Outdated Show resolved Hide resolved
test/connection-manager/index.spec.ts Show resolved Hide resolved
achingbrain added a commit that referenced this pull request Oct 5, 2022
mpetrunic pushed a commit that referenced this pull request Oct 5, 2022
@@ -31,7 +32,8 @@ const defaultOptions: Partial<ConnectionManagerInit> = {
maxEventLoopDelay: Infinity,
pollInterval: 2000,
autoDialInterval: 10000,
movingAverageInterval: 60000
movingAverageInterval: 60000,
inboundConnectionThreshold: 5
Copy link
Member Author

Choose a reason for hiding this comment

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

This will deny any host not in the allow list that tries to open more than 5x connections a second. I plucked the number out of thin air, is it reasonable?

@achingbrain achingbrain merged commit c185ef5 into master Oct 6, 2022
@achingbrain achingbrain deleted the feat/deny-incoming-connections branch October 6, 2022 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants