| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -957,6 +957,13 @@ changes: | |||
| 957 | 957 | * `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value. | |
| 958 | 958 | * `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][]. | |
| 959 | 959 | * `signal` {AbortSignal} An AbortSignal that may be used to close a socket. | |
| 960 | + * `receiveBlockList` {net.BlockList} `receiveBlockList` can be used for discarding | ||
| 961 | + inbound datagram to specific IP addresses, IP ranges, or IP subnets. This does not | ||
| 962 | + work if the server is behind a reverse proxy, NAT, etc. because the address | ||
| 963 | + checked against the blocklist is the address of the proxy, or the one | ||
| 964 | + specified by the NAT. | ||
| 965 | + * `sendBlockList` {net.BlockList} `sendBlockList` can be used for disabling outbound | ||
| 966 | + access to specific IP addresses, IP ranges, or IP subnets. | ||
| 960 | 967 | * `callback` {Function} Attached as a listener for `'message'` events. Optional. | |
| 961 | 968 | * Returns: {dgram.Socket} | |
| 962 | 969 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,6 +41,7 @@ const { | |||
| 41 | 41 | ERR_BUFFER_OUT_OF_BOUNDS, | |
| 42 | 42 | ERR_INVALID_ARG_TYPE, | |
| 43 | 43 | ERR_INVALID_FD_TYPE, | |
| 44 | + ERR_IP_BLOCKED, | ||
| 44 | 45 | ERR_MISSING_ARGS, | |
| 45 | 46 | ERR_SOCKET_ALREADY_BOUND, | |
| 46 | 47 | ERR_SOCKET_BAD_BUFFER_SIZE, | |
@@ -55,6 +56,7 @@ const { | |||
| 55 | 56 | _createSocketHandle, | |
| 56 | 57 | newHandle, | |
| 57 | 58 | } = require('internal/dgram'); | |
| 59 | + const { isIP } = require('internal/net'); | ||
| 58 | 60 | const { | |
| 59 | 61 | isInt32, | |
| 60 | 62 | validateAbortSignal, | |
@@ -99,12 +101,18 @@ let _cluster = null; | |||
| 99 | 101 | function lazyLoadCluster() { | |
| 100 | 102 | return _cluster ??= require('cluster'); | |
| 101 | 103 | } | |
| 104 | + let _blockList = null; | ||
| 105 | + function lazyLoadBlockList() { | ||
| 106 | + return _blockList ??= require('internal/blocklist').BlockList; | ||
| 107 | + } | ||
| 102 | 108 | ||
| 103 | 109 | function Socket(type, listener) { | |
| 104 | 110 | FunctionPrototypeCall(EventEmitter, this); | |
| 105 | 111 | let lookup; | |
| 106 | 112 | let recvBufferSize; | |
| 107 | 113 | let sendBufferSize; | |
| 114 | + let receiveBlockList; | ||
| 115 | + let sendBlockList; | ||
| 108 | 116 | ||
| 109 | 117 | let options; | |
| 110 | 118 | if (type !== null && typeof type === 'object') { | |
@@ -119,6 +127,18 @@ function Socket(type, listener) { | |||
| 119 | 127 | } | |
| 120 | 128 | recvBufferSize = options.recvBufferSize; | |
| 121 | 129 | sendBufferSize = options.sendBufferSize; | |
| 130 | + if (options.receiveBlockList) { | ||
| 131 | + if (!lazyLoadBlockList().isBlockList(options.receiveBlockList)) { | ||
| 132 | + throw new ERR_INVALID_ARG_TYPE('options.receiveBlockList', 'net.BlockList', options.receiveBlockList); | ||
| 133 | + } | ||
| 134 | + receiveBlockList = options.receiveBlockList; | ||
| 135 | + } | ||
| 136 | + if (options.sendBlockList) { | ||
| 137 | + if (!lazyLoadBlockList().isBlockList(options.sendBlockList)) { | ||
| 138 | + throw new ERR_INVALID_ARG_TYPE('options.sendBlockList', 'net.BlockList', options.sendBlockList); | ||
| 139 | + } | ||
| 140 | + sendBlockList = options.sendBlockList; | ||
| 141 | + } | ||
| 122 | 142 | } | |
| 123 | 143 | ||
| 124 | 144 | const handle = newHandle(type, lookup); | |
@@ -141,6 +161,8 @@ function Socket(type, listener) { | |||
| 141 | 161 | ipv6Only: options?.ipv6Only, | |
| 142 | 162 | recvBufferSize, | |
| 143 | 163 | sendBufferSize, | |
| 164 | + receiveBlockList, | ||
| 165 | + sendBlockList, | ||
| 144 | 166 | }; | |
| 145 | 167 | ||
| 146 | 168 | if (options?.signal !== undefined) { | |
@@ -439,7 +461,9 @@ function doConnect(ex, self, ip, address, port, callback) { | |||
| 439 | 461 | const state = self[kStateSymbol]; | |
| 440 | 462 | if (!state.handle) | |
| 441 | 463 | return; | |
| 442 | - | ||
| 464 | + if (!ex && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) { | ||
| 465 | + ex = new ERR_IP_BLOCKED(ip); | ||
| 466 | + } | ||
| 443 | 467 | if (!ex) { | |
| 444 | 468 | const err = state.handle.connect(ip, port); | |
| 445 | 469 | if (err) { | |
@@ -703,6 +727,13 @@ function doSend(ex, self, ip, list, address, port, callback) { | |||
| 703 | 727 | return; | |
| 704 | 728 | } | |
| 705 | 729 | ||
| 730 | + if (ip && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) { | ||
| 731 | + if (callback) { | ||
| 732 | + process.nextTick(callback, new ERR_IP_BLOCKED(ip)); | ||
| 733 | + } | ||
| 734 | + return; | ||
| 735 | + } | ||
| 736 | + | ||
| 706 | 737 | const req = new SendWrap(); | |
| 707 | 738 | req.list = list; // Keep reference alive. | |
| 708 | 739 | req.address = address; | |
@@ -951,6 +982,10 @@ function onMessage(nread, handle, buf, rinfo) { | |||
| 951 | 982 | if (nread < 0) { | |
| 952 | 983 | return self.emit('error', new ErrnoException(nread, 'recvmsg')); | |
| 953 | 984 | } | |
| 985 | + if (self[kStateSymbol]?.receiveBlockList?.check(rinfo.address, | ||
| 986 | + rinfo.family?.toLocaleLowerCase())) { | ||
| 987 | + return; | ||
| 988 | + } | ||
| 954 | 989 | rinfo.size = buf.length; // compatibility | |
| 955 | 990 | self.emit('message', buf, rinfo); | |
| 956 | 991 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,49 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const dgram = require('dgram'); | ||
| 5 | + const net = require('net'); | ||
| 6 | + | ||
| 7 | + { | ||
| 8 | + const blockList = new net.BlockList(); | ||
| 9 | + blockList.addAddress(common.localhostIPv4); | ||
| 10 | + | ||
| 11 | + const connectSocket = dgram.createSocket({ type: 'udp4', sendBlockList: blockList }); | ||
| 12 | + connectSocket.connect(9999, common.localhostIPv4, common.mustCall((err) => { | ||
| 13 | + assert.ok(err.code === 'ERR_IP_BLOCKED', err); | ||
| 14 | + connectSocket.close(); | ||
| 15 | + })); | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + { | ||
| 19 | + const blockList = new net.BlockList(); | ||
| 20 | + blockList.addAddress(common.localhostIPv4); | ||
| 21 | + const sendSocket = dgram.createSocket({ type: 'udp4', sendBlockList: blockList }); | ||
| 22 | + sendSocket.send('hello', 9999, common.localhostIPv4, common.mustCall((err) => { | ||
| 23 | + assert.ok(err.code === 'ERR_IP_BLOCKED', err); | ||
| 24 | + sendSocket.close(); | ||
| 25 | + })); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + { | ||
| 29 | + const blockList = new net.BlockList(); | ||
| 30 | + blockList.addAddress(common.localhostIPv4); | ||
| 31 | + const receiveSocket = dgram.createSocket({ type: 'udp4', receiveBlockList: blockList }); | ||
| 32 | + // Hack to close the socket | ||
| 33 | + const check = blockList.check; | ||
| 34 | + blockList.check = function() { | ||
| 35 | + process.nextTick(() => { | ||
| 36 | + receiveSocket.close(); | ||
| 37 | + }); | ||
| 38 | + return check.apply(this, arguments); | ||
| 39 | + }; | ||
| 40 | + receiveSocket.on('message', common.mustNotCall()); | ||
| 41 | + receiveSocket.bind(0, common.localhostIPv4, common.mustCall(() => { | ||
| 42 | + const addressInfo = receiveSocket.address(); | ||
| 43 | + const client = dgram.createSocket('udp4'); | ||
| 44 | + client.send('hello', addressInfo.port, addressInfo.address, common.mustCall((err) => { | ||
| 45 | + assert.ok(!err); | ||
| 46 | + client.close(); | ||
| 47 | + })); | ||
| 48 | + })); | ||
| 49 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments