-
Notifications
You must be signed in to change notification settings - Fork 473
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: connection gater #987
Changes from all commits
6769f5b
5de5be0
723be76
d9aceda
0b33489
8b96b31
24d81f3
1929fd1
737181b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
'use strict' | ||
|
||
const debug = require('debug') | ||
const all = require('it-all') | ||
const filter = require('it-filter') | ||
const log = Object.assign(debug('libp2p:dialer'), { | ||
error: debug('libp2p:dialer:err') | ||
}) | ||
|
@@ -29,12 +31,14 @@ const { | |
* @typedef {import('../peer-store')} PeerStore | ||
* @typedef {import('../peer-store/address-book').Address} Address | ||
* @typedef {import('../transport-manager')} TransportManager | ||
* @typedef {import('../connection-manager')} ConnectionManager | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} DialerProperties | ||
* @property {PeerStore} peerStore | ||
* @property {TransportManager} transportManager | ||
* @property {ConnectionManager} connectionManager | ||
* | ||
* @typedef {(addr:Multiaddr) => Promise<string[]>} Resolver | ||
* | ||
|
@@ -65,13 +69,15 @@ class Dialer { | |
constructor ({ | ||
transportManager, | ||
peerStore, | ||
connectionManager, | ||
addressSorter = publicAddressesFirst, | ||
maxParallelDials = MAX_PARALLEL_DIALS, | ||
maxAddrsToDial = MAX_ADDRS_TO_DIAL, | ||
dialTimeout = DIAL_TIMEOUT, | ||
maxDialsPerPeer = MAX_PER_PEER_DIALS, | ||
resolvers = {} | ||
}) { | ||
this.connectionManager = connectionManager | ||
this.transportManager = transportManager | ||
this.peerStore = peerStore | ||
this.addressSorter = addressSorter | ||
|
@@ -118,6 +124,10 @@ class Dialer { | |
* @returns {Promise<Connection>} | ||
*/ | ||
async connectToPeer (peer, options = {}) { | ||
const { id } = getPeer(peer) | ||
if (this.connectionManager && await this.connectionManager.gater.interceptPeerDial(id)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a case when |
||
throw errCode(new Error('The dial request is blocked by gater.interceptPeerDial'), codes.ERR_PEER_DIAL_INTERCEPTED) | ||
} | ||
const dialTarget = await this._createCancellableDialTarget(peer) | ||
|
||
if (!dialTarget.addrs.length) { | ||
|
@@ -180,10 +190,12 @@ class Dialer { | |
const { id, multiaddrs } = getPeer(peer) | ||
|
||
if (multiaddrs) { | ||
this.peerStore.addressBook.add(id, multiaddrs) | ||
const filteredMultiaddrs = await all(filter(multiaddrs, async (multiaddr) => !(this.connectionManager && await this.connectionManager.gater.interceptAddrDial(id, multiaddr)))) | ||
this.peerStore.addressBook.add(id, filteredMultiaddrs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the gater be called here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To prevent malicious multiaddrs from adding to addressBook |
||
} | ||
|
||
let knownAddrs = this.peerStore.addressBook.getMultiaddrsForPeer(id, this.addressSorter) || [] | ||
knownAddrs = await all(filter(knownAddrs, async (multiaddr) => !(this.connectionManager && await this.connectionManager.gater.interceptAddrDial(id, multiaddr)))) | ||
|
||
// If received a multiaddr to dial, it should be the first to use | ||
// But, if we know other multiaddrs for the peer, we should try them too. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ class Upgrader { | |
/** | ||
* @param {object} options | ||
* @param {PeerId} options.localPeer | ||
* @param {import('./connection-manager')} options.connectionManager | ||
* @param {import('./metrics')} [options.metrics] | ||
* @param {Map<string, Crypto>} [options.cryptos] | ||
* @param {Map<string, MuxerFactory>} [options.muxers] | ||
|
@@ -45,11 +46,13 @@ class Upgrader { | |
constructor ({ | ||
localPeer, | ||
metrics, | ||
connectionManager, | ||
cryptos = new Map(), | ||
muxers = new Map(), | ||
onConnectionEnd = () => {}, | ||
onConnection = () => {} | ||
}) { | ||
this.connectionManager = connectionManager | ||
this.localPeer = localPeer | ||
this.metrics = metrics | ||
this.cryptos = cryptos | ||
|
@@ -77,6 +80,10 @@ class Upgrader { | |
let setPeer | ||
let proxyPeer | ||
|
||
if (await this.connectionManager.gater.interceptAccept(maConn)) { | ||
throw errCode(new Error('The multiaddr connection is blocked by gater.interceptAccept'), codes.ERR_CONNECTION_INTERCEPTED) | ||
} | ||
|
||
if (this.metrics) { | ||
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy()) | ||
const idString = (Math.random() * 1e9).toString(36) + Date.now() | ||
|
@@ -100,6 +107,10 @@ class Upgrader { | |
protocol: cryptoProtocol | ||
} = await this._encryptInbound(this.localPeer, protectedConn, this.cryptos)) | ||
|
||
if (await this.connectionManager.gater.interceptSecured('inbound', remotePeer, encryptedConn)) { | ||
throw errCode(new Error('The multiaddr connection is blocked by gater.interceptSecured'), codes.ERR_CONNECTION_INTERCEPTED) | ||
} | ||
|
||
// Multiplex the connection | ||
if (this.muxers.size) { | ||
({ stream: upgradedConn, Muxer } = await this._multiplexInbound(encryptedConn, this.muxers)) | ||
|
@@ -112,6 +123,10 @@ class Upgrader { | |
throw err | ||
} | ||
|
||
if (await this.connectionManager.gater.interceptUpgraded(upgradedConn)) { | ||
throw errCode(new Error('The multiaddr connection is blocked by gater.interceptUpgraded'), codes.ERR_CONNECTION_INTERCEPTED) | ||
} | ||
|
||
if (this.metrics) { | ||
this.metrics.updatePlaceholder(proxyPeer, remotePeer) | ||
setPeer(remotePeer) | ||
|
@@ -175,6 +190,10 @@ class Upgrader { | |
protocol: cryptoProtocol | ||
} = await this._encryptOutbound(this.localPeer, protectedConn, remotePeerId, this.cryptos)) | ||
|
||
if (await this.connectionManager.gater.interceptSecured('outbound', remotePeer, encryptedConn)) { | ||
throw errCode(new Error('The multiaddr connection is blocked by gater.interceptSecured'), codes.ERR_CONNECTION_INTERCEPTED) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// Multiplex the connection | ||
if (this.muxers.size) { | ||
({ stream: upgradedConn, Muxer } = await this._multiplexOutbound(encryptedConn, this.muxers)) | ||
|
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.
It may be nice to have the comments from https://github.com/libp2p/go-libp2p-core/blob/master/connmgr/gater.go#L11-L43 included here or wherever is most appropriate