Skip to content

Commit fce951a

Browse files
committed
net: fail closed when BlockList peer address is unavailable
When a net.Server is configured with a `blockList`, the peer address is looked up with getpeername() and checked before the connection is accepted. If the peer address cannot be obtained (for example, the connection was reset before getpeername(), causing uv_tcp_getpeername() to return ENOTCONN), the access-control check was silently skipped and the connection proceeded, allowing a blocked peer to reach the application's 'connection' handler (fail open). Fail closed: when a BlockList is configured but the peer address cannot be determined, close the connection instead of bypassing the check. A connection whose peer address cannot be obtained cannot be proven to be allowed, so it must be refused. Refs: #66422 libuv/libuv#5337 Signed-off-by: Matteo Collina <hello@matteocollina.com> Assisted-by: pi
1 parent 96ee81c commit fce951a

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

‎lib/net.js‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2826,7 +2826,10 @@ function onconnection(err, clientHandle) {
28262826
const remoteInfo = { __proto__: null };
28272827
clientHandle.getpeername(remoteInfo);
28282828
const addressType = isIP(remoteInfo.address);
2829-
if (addressType && self.blockList.check(remoteInfo.address, `ipv${addressType}`)) {
2829+
// Fail closed: if a BlockList is configured but the peer address cannot
2830+
// be obtained (e.g. the connection was reset before getpeername()),
2831+
// refuse the connection instead of silently bypassing the access control.
2832+
if (!addressType || self.blockList.check(remoteInfo.address, `ipv${addressType}`)) {
28302833
clientHandle.close();
28312834
return;
28322835
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
const common = require('../common');
3+
const net = require('net');
4+
5+
const blockList = new net.BlockList();
6+
blockList.addCIDR('0.0.0.0/0');
7+
blockList.addCIDR('::/0');
8+
9+
// A connection whose peer address cannot be determined (e.g. it was reset
10+
// before getpeername()) must be rejected when a BlockList is configured,
11+
// rather than being delivered to the application (fail closed).
12+
const server = net.createServer({ blockList }, common.mustNotCall());
13+
14+
server.listen(0, common.mustCall(() => {
15+
const socket = net.connect(server.address().port);
16+
socket.on('error', () => {});
17+
}));
18+
19+
const onconnection = server._handle.onconnection;
20+
server._handle.onconnection = common.mustCall((err, clientHandle) => {
21+
const close = clientHandle.close;
22+
// Simulate the reset-before-getpeername() condition: onconnection() is
23+
// unable to obtain a valid peer address from the accepted connection.
24+
clientHandle.getpeername = function(remoteInfo) {
25+
remoteInfo.address = undefined;
26+
};
27+
clientHandle.close = common.mustCall(() => {
28+
clientHandle.close = close;
29+
close.call(clientHandle);
30+
server.close();
31+
});
32+
onconnection.call(server._handle, err, clientHandle);
33+
});

0 commit comments

Comments
 (0)