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: Update connectionManager to allow configuration of incoming and outgoing connection limits #1511

Closed
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
836a5af
doc: Updated docs to seperate max/min incoming and outgoing connectio…
maschad Dec 5, 2022
b8bb367
test: updated tests to check for max/min incoming and outgoing connec…
maschad Dec 5, 2022
d2cad14
feat: Added the configuration capabilities on connection manager to s…
maschad Dec 5, 2022
fd41aa2
test: throws an error for outbound connection beyond limit and added …
maschad Dec 6, 2022
9344798
fix: should not prune a peer that is in the allow list once the conne…
maschad Dec 8, 2022
1899064
docs: update connection manager docs (#1555)
maschad Jan 17, 2023
78c9bbb
chore: update dependanbot config (#1558)
achingbrain Jan 17, 2023
6188a51
chore: remove unused rimraf dep (#1559)
achingbrain Jan 17, 2023
cb245ce
fix: allow reading PeerId from keychain (#1552)
achingbrain Jan 17, 2023
07352f6
fix: allow configuring circuit stream limits (#1542)
mpetrunic Jan 17, 2023
5a5330e
chore: release 0.42.2 (#1551)
github-actions[bot] Jan 18, 2023
b534c8b
fixup! doc: Updated docs to seperate max/min incoming and outgoing co…
maschad Jan 18, 2023
e2810db
fixup! feat: Added the configuration capabilities on connection manag…
maschad Jan 18, 2023
5b2c1f0
doc: Updated docs to seperate max/min incoming and outgoing connectio…
maschad Dec 5, 2022
3f20c93
Merge branch 'master' into feat/seperate-limits-for-connections
maschad Jan 18, 2023
9e75969
fix: updated connection limits to filter for inbound/outbound (#1511)
maschad Jan 23, 2023
c8ebca5
test: updated test for outbound connection limits (#1508)
maschad Jan 24, 2023
1fcbca1
Merge branch 'master' into feat/seperate-limits-for-connections
maschad Feb 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@ const node = await createLibp2p({
streamMuxers: [mplex()],
connectionEncryption: [noise()],
connectionManager: {
maxConnections: Infinity,
maxIncomingConnections: Infinity,
maxOutgoingConnections: Infinity,
minConnections: 0,
pollInterval: 2000,
// The below values will only be taken into account when Metrics are enabled
Expand Down
17 changes: 10 additions & 7 deletions doc/LIMITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ This is important for [DoS](https://en.wikipedia.org/wiki/Denial-of-service_atta

It's possible to limit the total amount of connections a node is able to make (combining incoming and outgoing). When this limit is reached and an attempt to open a new connection is made, existing connections may be closed to make room for the new connection (see [Closing connections][#closing-connections]).

* Note: there currently isn't a way to specify different limits for incoming vs. outgoing. Connection limits are applied across both incoming and outgoing connections combined. There is a backlog item for this [here](https://github.com/libp2p/js-libp2p/issues/1508).

We can also limit the number of connections in a "pending" state. These connections have been opened by a remote peer but peer IDs have yet to be exchanged and/or connection encryption and multiplexing negotiated. Once this limit is hit further connections will be closed unless the remote peer has an address in the [allow list](#allowdeny-lists).

All fields are optional. The default values are defined in [src/connection-manager/index.ts](https://github.com/libp2p/js-libp2p/blob/master/src/connection-manager/index.ts) - please see that file for the current values.
Expand All @@ -33,9 +31,14 @@ All fields are optional. The default values are defined in [src/connection-manag
const node = await createLibp2pNode({
connectionManager: {
/**
* The total number of connections allowed to be open at one time
* The total number of incoming connections allowed to be open at one time
*/
maxConnections: number
maxIncomingConnections: number

/**
* The total number of outgoing connections allowed to be open at one time
*/
maxOutgoingConnections: number

/**
* If the number of open connections goes below this number, the node
Expand Down Expand Up @@ -255,9 +258,9 @@ const node = await createLibp2pNode({
/**
* Once this many connections are open on this listener any further connections
* will be rejected - this will have no effect if it is larger than the value
* configured for the ConnectionManager maxConnections parameter
* configured for the ConnectionManager maxIncomingConnections parameter
*/
maxConnections: number
maxIncomingConnections: number
})
]
})
Expand Down Expand Up @@ -310,7 +313,7 @@ Important details for ascertaining this are:
As a result, the max amount of memory buffered by libp2p is approximately:

```
connectionManager.maxConnections *
(connectionManager.maxOutgoingConnections + connectionManager.maxIncomingConnections) *
(muxer.maxUnprocessedMessageQueueSize
+ (muxer.maxInboundStreams * muxer.maxStreamBufferSize)
+ (muxer.maxOutboundStreams * muxer.maxStreamBufferSize)
Expand Down
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const DefaultConfig: Partial<Libp2pInit> = {
announceFilter: (multiaddrs: Multiaddr[]) => multiaddrs
},
connectionManager: {
maxConnections: 300,
maxIncomingConnections: 300,
maxOutgoingConnections: 300,
Comment on lines +23 to +24
Copy link
Member

@achingbrain achingbrain Jan 17, 2023

Choose a reason for hiding this comment

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

This effectively doubles the number of allowed connections, I'm not sure if that's a good idea. I know this is what #1508 asks for but maybe it needs more thought.

Copy link
Member

Choose a reason for hiding this comment

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

There are valid use cases for expecting mostly incoming connections, it may be a better approach to just always ensure we can make outgoing connections to prevent eclipse attacks?

Copy link
Member Author

Choose a reason for hiding this comment

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

If a consumer has a set of trusted peers and IP addresses, we can actually always have outgoing connections to these trusted peers by adding them to the AllowList (which #1515 consolidates by ensuring they are never pruned), so that should mitigate against eclipse attacks. I know that go-lip2p's resource manager is configured with limits on the number of outgoing and incoming connections

minConnections: 50,
autoDial: true,
autoDialInterval: 10000,
Expand Down
4 changes: 2 additions & 2 deletions src/connection-manager/auto-dialler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface AutoDiallerInit {
enabled?: boolean

/**
* The minimum number of connections to avoid pruning
* The minimum number of incoming connections to avoid pruning
*/
minConnections?: number

Expand Down Expand Up @@ -107,7 +107,7 @@ export class AutoDialler implements Startable {
this.autoDialTimeout.clear()
}

const minConnections = this.options.minConnections
const { minConnections } = this.options

// Already has enough connections
if (this.components.connectionManager.getConnections().length >= minConnections) {
Expand Down
39 changes: 31 additions & 8 deletions src/connection-manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ export interface ConnectionManagerConfig {
/**
* The maximum number of connections libp2p is willing to have before it starts disconnecting. Defaults to `Infinity`
*/
maxConnections: number
maxIncomingConnections: number

/**
* The maximum number of outgoing connections to keep open
*/
maxOutgoingConnections: number

/**
* The minimum number of connections below which libp2p not activate preemptive disconnections. Defaults to `0`.
Expand Down Expand Up @@ -100,7 +105,7 @@ export interface ConnectionManagerConfig {

/**
* A list of multiaddrs that will always be allowed (except if they are in the
* deny list) to open connections to this node even if we've reached maxConnections
* deny list) to open connections to this node even if we've reached maxnOutgoingConnections
*/
allow?: string[]

Expand All @@ -124,7 +129,8 @@ export interface ConnectionManagerConfig {
}

const defaultOptions: Partial<ConnectionManagerConfig> = {
maxConnections: Infinity,
maxIncomingConnections: Infinity,
maxOutgoingConnections: Infinity,
minConnections: 0,
maxEventLoopDelay: Infinity,
pollInterval: 2000,
Expand Down Expand Up @@ -167,8 +173,18 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven

this.opts = mergeOptions.call({ ignoreUndefined: true }, defaultOptions, init)

if (this.opts.maxConnections < this.opts.minConnections) {
throw errCode(new Error('Connection Manager maxConnections must be greater than minConnections'), codes.ERR_INVALID_PARAMETERS)
if (this.opts.maxIncomingConnections < this.opts.minConnections) {
throw errCode(
new Error('Connection Manager maxIncomingConnections must be greater than minConnections'),
codes.ERR_INVALID_PARAMETERS
)
}

if (this.opts.maxOutgoingConnections < this.opts.minConnections) {
maschad marked this conversation as resolved.
Show resolved Hide resolved
throw errCode(
new Error('Connection Manager maxOutgoingConnections must be greater than minConnections'),
codes.ERR_INVALID_PARAMETERS
)
}

log('options: %o', this.opts)
Expand Down Expand Up @@ -427,9 +443,9 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
}

const numConnections = this.getConnections().length
const toPrune = numConnections - this.opts.maxConnections
const toPrune = numConnections - this.opts.maxOutgoingConnections
maschad marked this conversation as resolved.
Show resolved Hide resolved

await this._checkMaxLimit('maxConnections', numConnections, toPrune)
await this._checkMaxLimit('maxOutgoingConnections', numConnections, toPrune)
this.dispatchEvent(new CustomEvent<Connection>('peer:connect', { detail: connection }))
}

Expand Down Expand Up @@ -489,6 +505,13 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
}
}

if ((this.getConnections().length + 1) > this.opts.maxOutgoingConnections) {
maschad marked this conversation as resolved.
Show resolved Hide resolved
throw errCode(
new Error('Connection Manager maxOutgoing connections exceeded'),
codes.ERR_CONNECTION_DENIED
)
}

let timeoutController: TimeoutController | undefined

if (options?.signal == null) {
Expand Down Expand Up @@ -712,7 +735,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
}
}

if (this.getConnections().length < this.opts.maxConnections) {
if (this.getConnections().length < this.opts.maxIncomingConnections) {
this.incomingPendingConnections++

return true
Expand Down
10 changes: 6 additions & 4 deletions test/connection-manager/index.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ describe('Connection Manager', () => {
upgrader,
peerStore
}, {
maxConnections: 1000,
maxIncomingConnections: 1000,
minConnections: 50,
maxOutgoingConnections: 1000,
autoDialInterval: 1000,
inboundUpgradeTimeout: 1000
})
Expand Down Expand Up @@ -97,8 +98,9 @@ describe('Connection Manager', () => {
upgrader,
peerStore
}, {
maxConnections: 1000,
maxIncomingConnections: 1000,
minConnections: 50,
maxOutgoingConnections: 1000,
autoDialInterval: 1000,
inboundUpgradeTimeout: 1000
})
Expand Down Expand Up @@ -233,7 +235,7 @@ describe('libp2p.connections', () => {
},
connectionManager: {
minConnections,
maxConnections: 1
maxIncomingConnections: 1
}
}
})
Expand Down Expand Up @@ -265,7 +267,7 @@ describe('libp2p.connections', () => {
},
connectionManager: {
minConnections,
maxConnections: 1
maxIncomingConnections: 1
}
}
})
Expand Down
Loading