Skip to content

Commit

Permalink
net: support blocklist for net.Server
Browse files Browse the repository at this point in the history
  • Loading branch information
theanarkh committed Nov 30, 2024
1 parent 4cf6fab commit 1bb4c67
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
5 changes: 5 additions & 0 deletions doc/api/net.md
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,11 @@ changes:
**Default:** `false`.
* `pauseOnConnect` {boolean} Indicates whether the socket should be
paused on incoming connections. **Default:** `false`.
* `blocklist` {net.BlockList} `blocklist` can be used for disabling inbound
access to specific IP addresses, IP ranges, or IP subnets. This does not
work if the server is behind a reverse proxy, NAT, etc. because the address
checked against the blocklist is the address of the proxy, or the one
specified by the NAT.

* `connectionListener` {Function} Automatically set as a listener for the
[`'connection'`][] event.
Expand Down
17 changes: 16 additions & 1 deletion lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,13 @@ function Server(options, connectionListener) {
this.keepAlive = Boolean(options.keepAlive);
this.keepAliveInitialDelay = ~~(options.keepAliveInitialDelay / 1000);
this.highWaterMark = options.highWaterMark ?? getDefaultHighWaterMark();
if (options.blocklist) {
// TODO: use BlockList.isBlockList (https://github.com/nodejs/node/pull/56078)
if (!(options.blocklist instanceof module.exports.BlockList)) {
throw new ERR_INVALID_ARG_TYPE('options.blocklist', 'net.BlockList', options.blocklist);
}
this.blocklist = options.blocklist;
}
}
ObjectSetPrototypeOf(Server.prototype, EventEmitter.prototype);
ObjectSetPrototypeOf(Server, EventEmitter);
Expand Down Expand Up @@ -2239,7 +2246,15 @@ function onconnection(err, clientHandle) {
clientHandle.close();
return;
}

if (self.blocklist && typeof clientHandle.getpeername === 'function') {
const remoteInfo = { __proto__: null };
clientHandle.getpeername(remoteInfo);
const addressType = isIP(remoteInfo.address);
if (addressType && self.blocklist.check(remoteInfo.address, `ipv${addressType}`)) {
clientHandle.close();
return;
}
}
const socket = new Socket({
handle: clientHandle,
allowHalfOpen: self.allowHalfOpen,
Expand Down
19 changes: 19 additions & 0 deletions test/parallel/test-net-server-blocklist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';
const common = require('../common');
const net = require('net');

const blocklist = new net.BlockList();
blocklist.addAddress(common.localhostIPv4);

const server = net.createServer({ blocklist }, common.mustNotCall());
server.listen(0, common.localhostIPv4, common.mustCall(() => {
const adddress = server.address();
const socket = net.connect({
localAddress: common.localhostIPv4,
host: adddress.address,
port: adddress.port
});
socket.on('close', common.mustCall(() => {
server.close();
}));
}));

0 comments on commit 1bb4c67

Please sign in to comment.