Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6338 from LiskHQ/6336_validate_address
Browse files Browse the repository at this point in the history
Update node onConnect procedure - Closes #6336
  • Loading branch information
ManuGowda committed Apr 23, 2021
2 parents cd68189 + 414681c commit 89d04b1
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 5 deletions.
3 changes: 3 additions & 0 deletions elements/lisk-p2p/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ export const FORBIDDEN_CONNECTION_REASON = 'Peer is not allowed to connect';
export const EVICTED_PEER_CODE = 4418;
export const DUPLICATE_CONNECTION = 4404;
export const DUPLICATE_CONNECTION_REASON = 'Peer has a duplicate connection';
export const INVALID_CONNECTION_ADDRESS_CODE = 4503;
export const INVALID_CONNECTION_ADDRESS_REASON =
'Peer did not provide a valid address as part of the WebSocket connection';

// Peer info constants
export const INVALID_PEER_INFO_LIST_REASON = 'PeerInfo list has invalid value';
Expand Down
15 changes: 15 additions & 0 deletions elements/lisk-p2p/src/p2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import { EventEmitter } from 'events';
import { codec } from '@liskhq/lisk-codec';
import { getRandomBytes } from '@liskhq/lisk-cryptography';
import { isIPV4 } from '@liskhq/lisk-validator';

import {
DEFAULT_BAN_TIME,
Expand Down Expand Up @@ -43,6 +44,9 @@ import {
DUPLICATE_CONNECTION_REASON,
INCOMPATIBLE_PEER_CODE,
INCOMPATIBLE_PEER_UNKNOWN_REASON,
INVALID_CONNECTION_URL_REASON,
INVALID_CONNECTION_ADDRESS_CODE,
INVALID_CONNECTION_ADDRESS_REASON,
DEFAULT_PEER_STATUS_MESSAGE_RATE,
} from './constants';
import { PeerInboundDuplicateConnectionError } from './errors';
Expand Down Expand Up @@ -398,6 +402,17 @@ export class P2P extends EventEmitter {
};

this._handleInboundPeerConnect = (incomingPeerConnection: IncomingPeerConnection): void => {
if (!isIPV4(incomingPeerConnection.socket.remoteAddress)) {
incomingPeerConnection.socket.disconnect(
INVALID_CONNECTION_ADDRESS_CODE,
INVALID_CONNECTION_ADDRESS_REASON,
);

this.emit(EVENT_FAILED_TO_ADD_INBOUND_PEER, INVALID_CONNECTION_URL_REASON);

return;
}

try {
this._peerPool.addInboundPeer(
incomingPeerConnection.peerInfo,
Expand Down
18 changes: 17 additions & 1 deletion elements/lisk-p2p/src/utils/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* Removal or modification of this copyright notice is prohibited.
*/

import { isIPV4 } from '@liskhq/lisk-validator';
import {
ConnectionKind,
DEFAULT_PRODUCTIVITY,
Expand Down Expand Up @@ -103,6 +103,10 @@ export const sanitizePeerLists = (

const fixedPeers = lists.fixedPeers
.filter(peerInfo => {
if (!isIPV4(peerInfo.ipAddress)) {
return false;
}

if (peerInfo.ipAddress === nodeInfo.ipAddress) {
return false;
}
Expand All @@ -124,6 +128,10 @@ export const sanitizePeerLists = (

const seedPeers = lists.seedPeers
.filter(peerInfo => {
if (!isIPV4(peerInfo.ipAddress)) {
return false;
}

if (peerInfo.ipAddress === nodeInfo.ipAddress) {
return false;
}
Expand All @@ -149,6 +157,10 @@ export const sanitizePeerLists = (

const whitelisted = lists.whitelisted
.filter(peerInfo => {
if (!isIPV4(peerInfo.ipAddress)) {
return false;
}

if (peerInfo.ipAddress === nodeInfo.ipAddress) {
return false;
}
Expand Down Expand Up @@ -180,6 +192,10 @@ export const sanitizePeerLists = (
});

const previousPeers = lists.previousPeers.filter(peerInfo => {
if (!isIPV4(peerInfo.ipAddress)) {
return false;
}

if (peerInfo.ipAddress === nodeInfo.ipAddress) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions elements/lisk-p2p/src/utils/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import { isIP, isPort, validator } from '@liskhq/lisk-validator';
import { isIPV4, isPort, validator } from '@liskhq/lisk-validator';
import {
INCOMPATIBLE_NETWORK_REASON,
INCOMPATIBLE_PROTOCOL_VERSION_REASON,
Expand Down Expand Up @@ -87,7 +87,7 @@ export const validatePeerCompatibility = (
};

export const validatePeerAddress = (ipAddress: string, port: number): boolean => {
if (!isIP(ipAddress) || !isPort(port.toString())) {
if (!isIPV4(ipAddress) || !isPort(port.toString())) {
return false;
}

Expand Down
79 changes: 79 additions & 0 deletions elements/lisk-p2p/test/integration/sanitize_peer_lists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright © 2021 Lisk Foundation
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
* no part of this software, including this file, may be copied, modified,
* propagated, or distributed except according to the terms contained in the
* LICENSE file.
*
* Removal or modification of this copyright notice is prohibited.
*
*/

import { isIPV4 } from '@liskhq/lisk-validator';
import { P2P } from '../../src/index';
import { wait } from '../utils/helpers';
import { createNetwork, destroyNetwork } from '../utils/network_setup';

describe('Sanitize peer lists on load', () => {
const initPeerInfoList = (qty: number) => {
const peerInfos: any[] = [];
for (let i = 1; i <= qty; i += 1) {
peerInfos.push({
peerId: `200:db8:85a3:8d3:1319:8a2e:370:7348:${5000 + (i % 40000)}`,
ipAddress: '200:db8:85a3:8d3:1319:8a2e:370:7348',
port: 5000 + (i % 40000),
});
}

return peerInfos;
};

describe('Address validation', () => {
let p2pNodeList: ReadonlyArray<P2P> = [];

beforeAll(async () => {
// To capture all the initial events set network creation time to minimum 1 ms
const customConfig = () => ({
rateCalculationInterval: 100,
previousPeers: initPeerInfoList(200),
});

p2pNodeList = await createNetwork({
networkDiscoveryWaitTime: 0,
customConfig,
networkSize: 4,
});

await Promise.all(p2pNodeList.map(async p2p => p2p.start()));

await wait(1000);
});

afterAll(async () => {
await destroyNetwork(p2pNodeList);
await wait(200);
});

it('should not contain invalid addresses in any of its peer list', () => {
for (const p2p of p2pNodeList) {
const { allPeers } = p2p['_peerBook'];

// eslint-disable-next-line @typescript-eslint/require-array-sort-compare
const allPeerAddresses = allPeers.map(peerInfo => peerInfo.ipAddress).sort();
// eslint-disable-next-line @typescript-eslint/require-array-sort-compare
const connectedPeerAddresses = p2p
.getConnectedPeers()
.map(peerInfo => peerInfo.ipAddress)
.sort();

expect(
[...allPeerAddresses, ...connectedPeerAddresses].filter(ipAddress => !isIPV4(ipAddress)),
).toHaveLength(0);
}
});
});
});
4 changes: 2 additions & 2 deletions elements/lisk-p2p/test/unit/utils/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ describe('utils/validate', () => {
expect(validatePeerAddress(peer.ipAddress, peer.port)).toBe(true);
});

it('should return true for correct IPv6', () => {
it('should return false for correct IPv6', () => {
const peer = {
ipAddress: '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
port: 4001,
};

expect(validatePeerAddress(peer.ipAddress, peer.port)).toBe(true);
expect(validatePeerAddress(peer.ipAddress, peer.port)).toBe(false);
});

it('should return false for incorrect ipAddress', () => {
Expand Down

0 comments on commit 89d04b1

Please sign in to comment.