quic: add block list support for endpoints · nodejs/node@e493f04 · GitHub
Skip to content

Commit e493f04

Browse files
jasnelladuh95
authored andcommitted
quic: add block list support for endpoints
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode/Opus 4.6 PR-URL: #63483 Backport-PR-URL: #64675 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 6d6cd45 commit e493f04

14 files changed

Lines changed: 299 additions & 31 deletions

doc/api/quic.md

Lines changed: 80 additions & 0 deletions

lib/internal/blocklist.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,5 @@ ObjectSetPrototypeOf(InternalBlockList.prototype, BlockList.prototype);
298298
module.exports = {
299299
BlockList,
300300
InternalBlockList,
301+
kHandle,
301302
};

lib/internal/quic/quic.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ if (!process.features.quic || !getOptionValue('--experimental-quic')) {
3636
}
3737

3838
const { inspect } = require('internal/util/inspect');
39+
const {
40+
BlockList,
41+
kHandle: kBlockListHandle,
42+
} = require('internal/blocklist');
3943

4044
let debug = require('internal/util/debuglog').debuglog('quic', (fn) => {
4145
debug = fn;
@@ -318,6 +322,8 @@ const endpointRegistry = new SafeSet();
318322
* @property {number} [immediateCloseBurst] Burst capacity for immediate close rate limiter
319323
* @property {number} [sessionCreationRate] Per-host rate limit for session creation (per second)
320324
* @property {number} [sessionCreationBurst] Per-host burst capacity for session creation rate limiter
325+
* @property {net.BlockList} [blockList] Block list for filtering incoming packets by source address
326+
* @property {'deny'|'allow'} [blockListPolicy='deny'] How to interpret the block list
321327
* @property {ArrayBufferView} [resetTokenSecret] The reset token secret
322328
* @property {bigint|number} [retryTokenExpiration] The retry token expiration
323329
* @property {number} [rxDiagnosticLoss] The receive diagnostic loss probability (range 0.0-1.0)
@@ -4048,6 +4054,8 @@ class QuicEndpoint {
40484054
immediateCloseBurst,
40494055
sessionCreationRate,
40504056
sessionCreationBurst,
4057+
blockList,
4058+
blockListPolicy = 'deny',
40514059
rxDiagnosticLoss,
40524060
txDiagnosticLoss,
40534061
udpReceiveBufferSize,
@@ -4062,6 +4070,16 @@ class QuicEndpoint {
40624070
tokenSecret,
40634071
} = options;
40644072

4073+
if (blockList !== undefined) {
4074+
if (!BlockList.isBlockList(blockList)) {
4075+
throw new ERR_INVALID_ARG_TYPE('options.blockList',
4076+
'net.BlockList', blockList);
4077+
}
4078+
}
4079+
4080+
validateOneOf(blockListPolicy, 'options.blockListPolicy',
4081+
['deny', 'allow']);
4082+
40654083
// All of the other options will be validated internally by the C++ code
40664084
if (address !== undefined && !SocketAddress.isSocketAddress(address)) {
40674085
if (typeof address === 'string') {
@@ -4093,6 +4111,9 @@ class QuicEndpoint {
40934111
immediateCloseBurst,
40944112
sessionCreationRate,
40954113
sessionCreationBurst,
4114+
// Pass the C++ handle, not the JS BlockList wrapper.
4115+
blockList: blockList?.[kBlockListHandle],
4116+
blockListPolicy,
40964117
rxDiagnosticLoss,
40974118
txDiagnosticLoss,
40984119
udpReceiveBufferSize,

lib/internal/quic/stats.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ const {
6868
IDX_STATS_ENDPOINT_IMMEDIATE_CLOSE_COUNT,
6969
IDX_STATS_ENDPOINT_IMMEDIATE_CLOSE_RATE_LIMITED,
7070
IDX_STATS_ENDPOINT_SESSION_CREATION_RATE_LIMITED,
71+
IDX_STATS_ENDPOINT_PACKETS_BLOCKED,
7172

7273
IDX_STATS_SESSION_CREATED_AT,
7374
IDX_STATS_SESSION_DESTROYED_AT,
@@ -136,6 +137,7 @@ assert(IDX_STATS_ENDPOINT_STATELESS_RESET_RATE_LIMITED !== undefined);
136137
assert(IDX_STATS_ENDPOINT_IMMEDIATE_CLOSE_COUNT !== undefined);
137138
assert(IDX_STATS_ENDPOINT_IMMEDIATE_CLOSE_RATE_LIMITED !== undefined);
138139
assert(IDX_STATS_ENDPOINT_SESSION_CREATION_RATE_LIMITED !== undefined);
140+
assert(IDX_STATS_ENDPOINT_PACKETS_BLOCKED !== undefined);
139141
assert(IDX_STATS_SESSION_CREATED_AT !== undefined);
140142
assert(IDX_STATS_SESSION_DESTROYED_AT !== undefined);
141143
assert(IDX_STATS_SESSION_CLOSING_AT !== undefined);
@@ -338,6 +340,12 @@ class QuicEndpointStats {
338340
return this.#handle[IDX_STATS_ENDPOINT_SESSION_CREATION_RATE_LIMITED];
339341
}
340342

343+
/** @type {bigint} */
344+
get packetsBlocked() {
345+
assertIsQuicEndpointStats(this);
346+
return this.#handle[IDX_STATS_ENDPOINT_PACKETS_BLOCKED];
347+
}
348+
341349
toString() {
342350
return JSONStringify(this.toJSON());
343351
}
@@ -363,6 +371,7 @@ class QuicEndpointStats {
363371
immediateCloseCount,
364372
immediateCloseRateLimited,
365373
sessionCreationRateLimited,
374+
packetsBlocked,
366375
} = this;
367376
return {
368377
__proto__: null,
@@ -387,6 +396,7 @@ class QuicEndpointStats {
387396
immediateCloseCount: `${immediateCloseCount}`,
388397
immediateCloseRateLimited: `${immediateCloseRateLimited}`,
389398
sessionCreationRateLimited: `${sessionCreationRateLimited}`,
399+
packetsBlocked: `${packetsBlocked}`,
390400
};
391401
}
392402

@@ -421,6 +431,7 @@ class QuicEndpointStats {
421431
immediateCloseCount,
422432
immediateCloseRateLimited,
423433
sessionCreationRateLimited,
434+
packetsBlocked,
424435
} = this;
425436

426437
return `QuicEndpointStats ${inspect({
@@ -443,6 +454,7 @@ class QuicEndpointStats {
443454
immediateCloseCount,
444455
immediateCloseRateLimited,
445456
sessionCreationRateLimited,
457+
packetsBlocked,
446458
}, opts)}`;
447459
}
448460

src/node_sockaddr.cc

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,7 @@ void SocketAddressBlockList::AddSocketAddressMask(
434434
rules_.emplace_front(std::move(rule));
435435
}
436436

437-
bool SocketAddressBlockList::Apply(
438-
const std::shared_ptr<SocketAddress>& address) {
437+
bool SocketAddressBlockList::Apply(const SocketAddress& address) {
439438
Mutex::ScopedLock lock(mutex_);
440439
for (const auto& rule : rules_) {
441440
if (rule->Apply(address)) return true;
@@ -457,8 +456,8 @@ SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
457456
: network(network_), prefix(prefix_) {}
458457

459458
bool SocketAddressBlockList::SocketAddressRule::Apply(
460-
const std::shared_ptr<SocketAddress>& address) {
461-
return this->address->is_match(*address.get());
459+
const SocketAddress& address) {
460+
return this->address->is_match(address);
462461
}
463462

464463
std::string SocketAddressBlockList::SocketAddressRule::ToString() {
@@ -470,8 +469,8 @@ std::string SocketAddressBlockList::SocketAddressRule::ToString() {
470469
}
471470

472471
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
473-
const std::shared_ptr<SocketAddress>& address) {
474-
return *address.get() >= *start.get() && *address.get() <= *end.get();
472+
const SocketAddress& address) {
473+
return address >= *start.get() && address <= *end.get();
475474
}
476475

477476
std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
@@ -485,8 +484,8 @@ std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
485484
}
486485

487486
bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
488-
const std::shared_ptr<SocketAddress>& address) {
489-
return address->is_in_network(*network.get(), prefix);
487+
const SocketAddress& address) {
488+
return address.is_in_network(*network.get(), prefix);
490489
}
491490

492491
std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
@@ -656,7 +655,7 @@ void SocketAddressBlockListWrap::Check(
656655
SocketAddressBase* addr;
657656
ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
658657

659-
args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
658+
args.GetReturnValue().Set(wrap->blocklist_->Apply(*addr->address()));
660659
}
661660

662661
void SocketAddressBlockListWrap::GetRules(

src/node_sockaddr.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,14 @@ class SocketAddressBlockList : public MemoryRetainer {
258258
void AddSocketAddressMask(const std::shared_ptr<SocketAddress>& address,
259259
int prefix);
260260

261-
bool Apply(const std::shared_ptr<SocketAddress>& address);
261+
bool Apply(const SocketAddress& address);
262262

263263
size_t size() const { return rules_.size(); }
264264

265265
v8::MaybeLocal<v8::Array> ListRules(Environment* env);
266266

267267
struct Rule : public MemoryRetainer {
268-
virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0;
268+
virtual bool Apply(const SocketAddress& address) = 0;
269269
inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env);
270270
virtual std::string ToString() = 0;
271271
};
@@ -275,7 +275,7 @@ class SocketAddressBlockList : public MemoryRetainer {
275275

276276
explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address);
277277

278-
bool Apply(const std::shared_ptr<SocketAddress>& address) override;
278+
bool Apply(const SocketAddress& address) override;
279279
std::string ToString() override;
280280

281281
void MemoryInfo(node::MemoryTracker* tracker) const override;
@@ -290,7 +290,7 @@ class SocketAddressBlockList : public MemoryRetainer {
290290
SocketAddressRangeRule(const std::shared_ptr<SocketAddress>& start,
291291
const std::shared_ptr<SocketAddress>& end);
292292

293-
bool Apply(const std::shared_ptr<SocketAddress>& address) override;
293+
bool Apply(const SocketAddress& address) override;
294294
std::string ToString() override;
295295

296296
void MemoryInfo(node::MemoryTracker* tracker) const override;
@@ -305,7 +305,7 @@ class SocketAddressBlockList : public MemoryRetainer {
305305
SocketAddressMaskRule(const std::shared_ptr<SocketAddress>& address,
306306
int prefix);
307307

308-
bool Apply(const std::shared_ptr<SocketAddress>& address) override;
308+
bool Apply(const SocketAddress& address) override;
309309
std::string ToString() override;
310310

311311
void MemoryInfo(node::MemoryTracker* tracker) const override;
@@ -353,6 +353,10 @@ class SocketAddressBlockListWrap : public BaseObject {
353353
std::shared_ptr<SocketAddressBlockList> blocklist =
354354
std::make_shared<SocketAddressBlockList>());
355355

356+
inline const std::shared_ptr<SocketAddressBlockList>& blocklist() const {
357+
return blocklist_;
358+
}
359+
356360
void MemoryInfo(node::MemoryTracker* tracker) const override;
357361
SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap)
358362
SET_SELF_SIZE(SocketAddressBlockListWrap)

src/quic/bindingdata.h

Lines changed: 4 additions & 0 deletions

0 commit comments

Comments
 (0)