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.

Ref: https://github.com/nodejs/node/issues/66422
Ref: https://github.com/libuv/libuv/pull/5337

Signed-off-by: Matteo Collina <hello@matteocollina.com>
Assisted-by: pi
PR-URL: https://github.com/nodejs/node/pull/66640
Refs: https://github.com/nodejs/node/issues/66422
Refs: https://github.com/libuv/libuv/pull/5337
Reviewed-By: Tim Perry <pimterry@gmail.com>
This commit is contained in:
Matteo Collina authored and GitHub committed 2026-10-17 09:45:08 +00:00
1 parent b5b07a0772
commit 269cab6320
2 files changed
+37 -1

No files matched your search

+4 -1
View File
@@ -2935,7 +2935,10 @@ function onconnection(err, clientHandle) {
const remoteInfo = { __proto__: null };
clientHandle.getpeername(remoteInfo);
const addressType = isIP(remoteInfo.address);
if (addressType && self.blockList.check(remoteInfo.address, `ipv${addressType}`)) {
// Fail closed: if a BlockList is configured but the peer address cannot
// be obtained (e.g. the connection was reset before getpeername()),
// refuse the connection instead of silently bypassing the access control.
if (!addressType || self.blockList.check(remoteInfo.address, `ipv${addressType}`)) {
clientHandle.close();
return;
}
@@ -0,0 +1,33 @@
'use strict';
const common = require('../common');
const net = require('net');
const blockList = new net.BlockList();
blockList.addCIDR('0.0.0.0/0');
blockList.addCIDR('::/0');
// A connection whose peer address cannot be determined (e.g. it was reset
// before getpeername()) must be rejected when a BlockList is configured,
// rather than being delivered to the application (fail closed).
const server = net.createServer({ blockList }, common.mustNotCall());
server.listen(0, common.mustCall(() => {
const socket = net.connect(server.address().port);
socket.on('error', () => {});
}));
const onconnection = server._handle.onconnection;
server._handle.onconnection = common.mustCall((err, clientHandle) => {
const close = clientHandle.close;
// Simulate the reset-before-getpeername() condition: onconnection() is
// unable to obtain a valid peer address from the accepted connection.
clientHandle.getpeername = function(remoteInfo) {
remoteInfo.address = undefined;
};
clientHandle.close = common.mustCall(() => {
clientHandle.close = close;
close.call(clientHandle);
server.close();
});
onconnection.call(server._handle, err, clientHandle);
});