Skip to content

Commit

Permalink
dgram: support blocklist in udp
Browse files Browse the repository at this point in the history
  • Loading branch information
theanarkh committed Nov 30, 2024
1 parent 4cf6fab commit 51c92f2
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
7 changes: 7 additions & 0 deletions doc/api/dgram.md
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,13 @@ changes:
* `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value.
* `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][].
* `signal` {AbortSignal} An AbortSignal that may be used to close a socket.
* `receiveBlockList` {net.BlockList} `receiveBlockList` can be used for discarding
inbound datagram 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.
* `sendBlockList` {net.BlockList} `sendBlockList` can be used for disabling outbound
access to specific IP addresses, IP ranges, or IP subnets.
* `callback` {Function} Attached as a listener for `'message'` events. Optional.
* Returns: {dgram.Socket}

Expand Down
30 changes: 29 additions & 1 deletion lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const {
_createSocketHandle,
newHandle,
} = require('internal/dgram');
const { isIP } = require('internal/net');
const {
isInt32,
validateAbortSignal,
Expand Down Expand Up @@ -104,6 +105,8 @@ function Socket(type, listener) {
let lookup;
let recvBufferSize;
let sendBufferSize;
let receiveBlockList;
let sendBlockList;

let options;
if (type !== null && typeof type === 'object') {
Expand All @@ -112,6 +115,14 @@ function Socket(type, listener) {
lookup = options.lookup;
recvBufferSize = options.recvBufferSize;
sendBufferSize = options.sendBufferSize;
// TODO: validate the params
// https://github.com/nodejs/node/pull/56078
if (options.receiveBlockList) {
receiveBlockList = options.receiveBlockList;
}
if (options.sendBlockList) {
sendBlockList = options.sendBlockList;
}
}

const handle = newHandle(type, lookup);
Expand All @@ -134,6 +145,8 @@ function Socket(type, listener) {
ipv6Only: options?.ipv6Only,
recvBufferSize,
sendBufferSize,
receiveBlockList,
sendBlockList,
};

if (options?.signal !== undefined) {
Expand Down Expand Up @@ -432,7 +445,10 @@ function doConnect(ex, self, ip, address, port, callback) {
const state = self[kStateSymbol];
if (!state.handle)
return;

if (!ex && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) {
// TODO
ex = new ERR_SOCKET_DGRAM_IS_CONNECTED();
}
if (!ex) {
const err = state.handle.connect(ip, port);
if (err) {
Expand Down Expand Up @@ -696,6 +712,14 @@ function doSend(ex, self, ip, list, address, port, callback) {
return;
}

if (port && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) {
if (callback) {
// TODO
process.nextTick(callback, new ERR_SOCKET_DGRAM_IS_CONNECTED());
}
return;
}

const req = new SendWrap();
req.list = list; // Keep reference alive.
req.address = address;
Expand Down Expand Up @@ -944,6 +968,10 @@ function onMessage(nread, handle, buf, rinfo) {
if (nread < 0) {
return self.emit('error', new ErrnoException(nread, 'recvmsg'));
}
if (self[kStateSymbol]?.receiveBlockList?.check(rinfo.address,
rinfo.family?.toLocaleLowerCase())) {
return;
}
rinfo.size = buf.length; // compatibility
self.emit('message', buf, rinfo);
}
Expand Down
49 changes: 49 additions & 0 deletions test/parallel/test-dgram-blocklist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const dgram = require('dgram');
const net = require('net');

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

const connectSocket = dgram.createSocket({ type: 'udp4', sendBlockList: blockList });
connectSocket.connect(9999, common.localhostIPv4, common.mustCall((err) => {
assert.ok(err);
connectSocket.close();
}));
}

{
const blockList = new net.BlockList();
blockList.addAddress(common.localhostIPv4);
const sendSocket = dgram.createSocket({ type: 'udp4', sendBlockList: blockList });
sendSocket.send('hello', 9999, common.localhostIPv4, common.mustCall((err) => {
assert.ok(err);
sendSocket.close();
}));
}

{
const blockList = new net.BlockList();
blockList.addAddress(common.localhostIPv4);
const receiveSocket = dgram.createSocket({ type: 'udp4', receiveBlockList: blockList });
// Hack to close the socket
const check = blockList.check;
blockList.check = function() {
process.nextTick(() => {
receiveSocket.close();
});
return check.apply(this, arguments);
};
receiveSocket.on('message', common.mustNotCall());
receiveSocket.bind(0, common.localhostIPv4, common.mustCall(() => {
const addressInfo = receiveSocket.address();
const client = dgram.createSocket('udp4');
client.send('hello', addressInfo.port, addressInfo.address, common.mustCall((err) => {
assert.ok(!err);
client.close();
}));
}));
}

0 comments on commit 51c92f2

Please sign in to comment.