Skip to content

net: introduce net.BlockList

This PR introduces the net.BlockList object:

net.BlockList provides an object intended to be used by net APIs to specify rules for disallowing network activity with specific IP addresses. This commit adds the basic mechanism but does not add the specific uses.

For instance:

const blockList = new net.BlockList();
blockList.addAddress('123.123.123.123');
blockList.addAddress('::f8f8', 'ipv6');
blockList.addRange('10.0.0.1', '10.0.0.10');
blockList.addSubnet('123.123.0.0', 16); // subnet 123.123.0.0/16

console.log(blockList.check('123.123.123.123'));   // true!

// IPv6 notation for IPv4 addresses is supported:
console.log(blockList.check('::ffff:123.123.123.123', 'ipv6'));   // true!

While the BlockList can be used on it's own, the intent is for the BlockList object to be passed into existing net APIs. For listen(), the BlockList will be checked as close to the libuv code that accepts the incoming connection as possible. For connect(), it would check as early as possible. These uses have not yet be implemented, however. Those would come in separate PRs.

The QUIC implementation will be the immediate first use of this:

const blockList = new BlockList();
// ... add rules

const sock = net.createQuicSocket({ blockList });
sock.listen();

When listening for new QUIC session requests, any received from blocked IP addresses will be automatically rejected.

The QUIC implementation would also have a setting that would allow misbehaving IP addresses to automatically be added to the configured BlockList (if provided) when a bad behavior threshhold has been reached.

const blockList = new BlockList();
// ... add rules

const sock = net.createQuicSocket({ blockList, autoBlock: true });
sock.listen();

If the QUIC implementation detects, for instance, that a remote IP is misbehaving, after a certain number of detected failures, the remote address would be added automatically to the given blockList if the autoBlock option is true.

The implementation is intentionally not specific to QUIC, however, and may be retrofitted into any of the other net systems.

Some discussion points:

  1. This is a block list only. There are no "allow" rules. So, specifically, it would not be possible to say "block everything except this IP". The reason for that choice is Node.js legacy -- the fact that accept everything has always been the default. I'm not intending to change the default behavior, I want to make it easier to respond to bad behavior as it is detected.

  2. Once an individual rule has been added, there's no way to remove it individually. There's only a single clear() operation that removes all rules. This is for simplicity in the overall API design and implementation. We can always go back and add the ability to remove individual rules later if necessary.

  3. This is implemented at the C++ layer for performance reasons. The overwhelming majority of times this will be used will be with servers, with the check happening as close to libuv as possible. I do not want to incur a JS call cost when performing the check.

  4. The internal implementation is not completed. Right now, this only implements the single address rule. Ranges and subnets are not yet implemented.

  5. For the initial implementation, I'm focusing on just getting it working. I'm sure there will be better ways of implementing the rules internally and those can be incremented on.

  6. There are no JS tests yet, those will come as the implementation continues.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

Merge request reports

Loading