Skip to content

Commit bacfe6d

Browse files
theanarkhruyadorno
authored andcommitted
net: support blocklist in net.connect
PR-URL: #56075 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]>
1 parent c4a97d8 commit bacfe6d

File tree

5 files changed

+99
-2
lines changed

5 files changed

+99
-2
lines changed

‎doc/api/errors.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,12 @@ An attempt was made to open an IPC communication channel with a synchronously
21662166
forked Node.js process. See the documentation for the [`child_process`][] module
21672167
for more information.
21682168

2169+
<aid="ERR_IP_BLOCKED"></a>
2170+
2171+
### `ERR_IP_BLOCKED`
2172+
2173+
IP is blocked by `net.BlockList`.
2174+
21692175
<aid="ERR_LOADER_CHAIN_INCOMPLETE"></a>
21702176

21712177
### `ERR_LOADER_CHAIN_INCOMPLETE`

‎doc/api/net.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,8 @@ For TCP connections, available `options` are:
10891089
*`noDelay`{boolean} If set to `true`, it disables the use of Nagle's algorithm
10901090
immediately after the socket is established. **Default:**`false`.
10911091
*`port`{number} Required. Port the socket should connect to.
1092+
*`blockList`{net.BlockList} `blockList` can be used for disabling outbound
1093+
access to specific IP addresses, IP ranges, or IP subnets.
10921094

10931095
For [IPC][] connections, available `options` are:
10941096

‎lib/internal/errors.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,9 @@ E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed', Error);
15551555
E('ERR_IPC_DISCONNECTED','IPC channel is already disconnected',Error);
15561556
E('ERR_IPC_ONE_PIPE','Child process can have only one IPC pipe',Error);
15571557
E('ERR_IPC_SYNC_FORK','IPC cannot be used with synchronous forks',Error);
1558+
E('ERR_IP_BLOCKED',function(ip){
1559+
return`IP(${ip}) is blocked by net.BlockList`;
1560+
},Error);
15581561
E(
15591562
'ERR_LOADER_CHAIN_INCOMPLETE',
15601563
'"%s" did not call the next hook in its chain and did not'+

‎lib/net.js‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ const{
103103
ERR_INVALID_FD_TYPE,
104104
ERR_INVALID_HANDLE_TYPE,
105105
ERR_INVALID_IP_ADDRESS,
106+
ERR_IP_BLOCKED,
106107
ERR_MISSING_ARGS,
107108
ERR_SERVER_ALREADY_LISTEN,
108109
ERR_SERVER_NOT_RUNNING,
@@ -510,6 +511,12 @@ function Socket(options){
510511
// Used after `.destroy()`
511512
this[kBytesRead]=0;
512513
this[kBytesWritten]=0;
514+
if(options.blockList){
515+
if(!module.exports.BlockList.isBlockList(options.blockList)){
516+
thrownewERR_INVALID_ARG_TYPE('options.blockList','net.BlockList',options.blockList);
517+
}
518+
this.blockList=options.blockList;
519+
}
513520
}
514521
ObjectSetPrototypeOf(Socket.prototype,stream.Duplex.prototype);
515522
ObjectSetPrototypeOf(Socket,stream.Duplex);
@@ -1073,6 +1080,10 @@ function internalConnect(
10731080
self.emit('connectionAttempt',address,port,addressType);
10741081

10751082
if(addressType===6||addressType===4){
1083+
if(self.blockList?.check(address,`ipv${addressType}`)){
1084+
self.destroy(newERR_IP_BLOCKED(address));
1085+
return;
1086+
}
10761087
constreq=newTCPConnectWrap();
10771088
req.oncomplete=afterConnect;
10781089
req.address=address;
@@ -1162,6 +1173,14 @@ function internalConnectMultiple(context, canceled){
11621173
}
11631174
}
11641175

1176+
if(self.blockList?.check(address,`ipv${addressType}`)){
1177+
constex=newERR_IP_BLOCKED(address);
1178+
ArrayPrototypePush(context.errors,ex);
1179+
self.emit('connectionAttemptFailed',address,port,addressType,ex);
1180+
internalConnectMultiple(context);
1181+
return;
1182+
}
1183+
11651184
debug('connect/multiple: attempting to connect to %s:%d (addressType: %d)',address,port,addressType);
11661185
self.emit('connectionAttempt',address,port,addressType);
11671186

@@ -1792,8 +1811,7 @@ function Server(options, connectionListener){
17921811
this.keepAliveInitialDelay=~~(options.keepAliveInitialDelay/1000);
17931812
this.highWaterMark=options.highWaterMark??getDefaultHighWaterMark();
17941813
if(options.blockList){
1795-
// TODO: use BlockList.isBlockList (https://github.com/nodejs/node/pull/56078)
1796-
if(!(options.blockListinstanceofmodule.exports.BlockList)){
1814+
if(!module.exports.BlockList.isBlockList(options.blockList)){
17971815
thrownewERR_INVALID_ARG_TYPE('options.blockList','net.BlockList',options.blockList);
17981816
}
17991817
this.blockList=options.blockList;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constnet=require('net');
5+
constassert=require('assert');
6+
7+
constblockList=newnet.BlockList();
8+
blockList.addAddress('127.0.0.1');
9+
blockList.addAddress('127.0.0.2');
10+
11+
functioncheck(err){
12+
assert.ok(err.code==='ERR_IP_BLOCKED',err);
13+
}
14+
15+
// Connect without calling dns.lookup
16+
{
17+
constsocket=net.connect({
18+
port: 9999,
19+
host: '127.0.0.1',
20+
blockList,
21+
});
22+
socket.on('error',common.mustCall(check));
23+
}
24+
25+
// Connect with single IP returned by dns.lookup
26+
{
27+
constsocket=net.connect({
28+
port: 9999,
29+
host: 'localhost',
30+
blockList,
31+
lookup: function(_,__,cb){
32+
cb(null,'127.0.0.1',4);
33+
},
34+
autoSelectFamily: false,
35+
});
36+
37+
socket.on('error',common.mustCall(check));
38+
}
39+
40+
// Connect with autoSelectFamily and single IP
41+
{
42+
constsocket=net.connect({
43+
port: 9999,
44+
host: 'localhost',
45+
blockList,
46+
lookup: function(_,__,cb){
47+
cb(null,[{address: '127.0.0.1',family: 4}]);
48+
},
49+
autoSelectFamily: true,
50+
});
51+
52+
socket.on('error',common.mustCall(check));
53+
}
54+
55+
// Connect with autoSelectFamily and multiple IPs
56+
{
57+
constsocket=net.connect({
58+
port: 9999,
59+
host: 'localhost',
60+
blockList,
61+
lookup: function(_,__,cb){
62+
cb(null,[{address: '127.0.0.1',family: 4},{address: '127.0.0.2',family: 4}]);
63+
},
64+
autoSelectFamily: true,
65+
});
66+
67+
socket.on('error',common.mustCall(check));
68+
}

0 commit comments

Comments
(0)