Skip to content

Commit 4e55fe8

Browse files
authored
fix: ignore observed IPv6 addresses that are not global unicast (#2873)
Only add public IPv4 or global unicast IPv6 addresses to the list of observed external addresses.
1 parent b5a2d3e commit 4e55fe8

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

packages/protocol-identify/src/identify.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys'
44
import { InvalidMessageError, UnsupportedProtocolError, serviceCapabilities, setMaxListeners } from '@libp2p/interface'
55
import { peerIdFromCID } from '@libp2p/peer-id'
66
import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
7+
import { isGlobalUnicast } from '@libp2p/utils/multiaddr/is-global-unicast'
78
import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
89
import { protocols } from '@multiformats/multiaddr'
9-
import { IP_OR_DOMAIN } from '@multiformats/multiaddr-matcher'
10+
import { IP_OR_DOMAIN, TCP } from '@multiformats/multiaddr-matcher'
1011
import { pbStream } from 'it-protobuf-stream'
1112
import {
1213
MULTICODEC_IDENTIFY_PROTOCOL_NAME,
@@ -18,6 +19,8 @@ import type { Identify as IdentifyInterface, IdentifyComponents, IdentifyInit }
1819
import type { IdentifyResult, AbortOptions, Connection, Stream, Startable } from '@libp2p/interface'
1920
import type { IncomingStreamData } from '@libp2p/interface-internal'
2021

22+
const CODEC_IP6 = 0x29
23+
2124
export class Identify extends AbstractIdentify implements Startable, IdentifyInterface {
2225
constructor (components: IdentifyComponents, init: IdentifyInit = {}) {
2326
super(components, {
@@ -105,22 +108,45 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
105108
}
106109

107110
// Get the observedAddr if there is one
108-
const cleanObservedAddr = getCleanMultiaddr(observedAddr)
111+
this.maybeAddObservedAddress(observedAddr)
109112

110113
this.log('identify completed for peer %p and protocols %o', id, protocols)
111114

112-
if (cleanObservedAddr != null) {
113-
this.log('our observed address was %a', cleanObservedAddr)
115+
return consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
116+
}
114117

115-
if (isPrivate(cleanObservedAddr)) {
116-
this.log('our observed address was private')
117-
} else if (this.addressManager.getObservedAddrs().length < (this.maxObservedAddresses ?? Infinity)) {
118-
this.log('storing our observed address')
119-
this.addressManager.addObservedAddr(cleanObservedAddr)
120-
}
118+
private maybeAddObservedAddress (observedAddr: Uint8Array | undefined): void {
119+
// Get the observedAddr if there is one
120+
const cleanObservedAddr = getCleanMultiaddr(observedAddr)
121+
122+
if (cleanObservedAddr == null) {
123+
return
121124
}
122125

123-
return consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
126+
this.log.trace('our observed address was %a', cleanObservedAddr)
127+
128+
if (isPrivate(cleanObservedAddr)) {
129+
this.log.trace('our observed address was private')
130+
return
131+
}
132+
133+
const tuples = cleanObservedAddr.stringTuples()
134+
135+
if (tuples[0][0] === CODEC_IP6 && !isGlobalUnicast(cleanObservedAddr)) {
136+
this.log.trace('our observed address was IPv6 but not a global unicast address')
137+
return
138+
}
139+
140+
if (TCP.exactMatch(cleanObservedAddr)) {
141+
// TODO: because socket dials can't use the same local port as the TCP
142+
// listener, many unique observed addresses are reported so ignore all
143+
// TCP addresses until https://github.com/libp2p/js-libp2p/issues/2620
144+
// is resolved
145+
return
146+
}
147+
148+
this.log.trace('storing the observed address')
149+
this.addressManager.addObservedAddr(cleanObservedAddr)
124150
}
125151

126152
/**

packages/protocol-identify/test/index.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,4 +373,28 @@ describe('identify', () => {
373373

374374
expect(result.observedAddr).to.be.undefined()
375375
})
376+
377+
it('should ignore observed non global unicast IPv6 addresses', async () => {
378+
identify = new Identify(components)
379+
380+
await start(identify)
381+
382+
const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
383+
384+
const message: IdentifyMessage = {
385+
protocolVersion: 'protocol version',
386+
agentVersion: 'agent version',
387+
listenAddrs: [multiaddr('/ip4/127.0.0.1/tcp/1234').bytes],
388+
protocols: ['protocols'],
389+
publicKey: publicKeyToProtobuf(remotePeer.publicKey),
390+
observedAddr: multiaddr('/ip6/fe80::2892:aef3:af04:735a%en').bytes
391+
}
392+
393+
const connection = identifyConnection(remotePeer, message)
394+
395+
// run identify
396+
await identify.identify(connection)
397+
398+
expect(components.addressManager.addObservedAddr.called).to.be.false()
399+
})
376400
})

0 commit comments

Comments
 (0)