@prosopo/provider 4.8.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$cjs.log +15 -14
- package/.turbo/turbo-build$colon$tsc.log +24 -24
- package/.turbo/turbo-build.log +16 -15
- package/CHANGELOG.md +30 -0
- package/dist/api/admin/apiAdminRoutesProvider.d.ts.map +1 -1
- package/dist/api/admin/apiAdminRoutesProvider.js +4 -1
- package/dist/api/admin/apiAdminRoutesProvider.js.map +1 -1
- package/dist/api/admin/apiDnsEventEndpoint.d.ts +4 -1
- package/dist/api/admin/apiDnsEventEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiDnsEventEndpoint.js +31 -1
- package/dist/api/admin/apiDnsEventEndpoint.js.map +1 -1
- package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +4 -1
- package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +31 -1
- package/dist/cjs/pairs.cjs +14 -0
- package/dist/cjs/tasks/captchaManager.cjs +9 -2
- package/dist/cjs/tasks/dnsEvent/enrichDnsEvent.cjs +62 -0
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +66 -33
- package/dist/cjs/tasks/powCaptcha/powTasks.cjs +42 -15
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +42 -15
- package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +19 -2
- package/dist/cjs/tasks/tasks.cjs +1 -0
- package/dist/cjs/util/usageCounters.cjs +18 -1
- package/dist/cjs/util.cjs +11 -1
- package/dist/pairs.d.ts +4 -0
- package/dist/pairs.d.ts.map +1 -1
- package/dist/pairs.js +15 -1
- package/dist/pairs.js.map +1 -1
- package/dist/tasks/captchaManager.d.ts +2 -2
- package/dist/tasks/captchaManager.d.ts.map +1 -1
- package/dist/tasks/captchaManager.js +9 -2
- package/dist/tasks/captchaManager.js.map +1 -1
- package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts +8 -0
- package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts.map +1 -0
- package/dist/tasks/dnsEvent/enrichDnsEvent.js +62 -0
- package/dist/tasks/dnsEvent/enrichDnsEvent.js.map +1 -0
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +67 -34
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.js +42 -15
- package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js +42 -15
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.d.ts +1 -1
- package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.js +19 -2
- package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
- package/dist/tasks/tasks.d.ts +1 -0
- package/dist/tasks/tasks.d.ts.map +1 -1
- package/dist/tasks/tasks.js +1 -0
- package/dist/tasks/tasks.js.map +1 -1
- package/dist/tests/unit/pairs.unit.test.js +79 -1
- package/dist/tests/unit/pairs.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/dnsEvent/enrichDnsEvent.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/dnsEvent/enrichDnsEvent.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/dnsEvent/enrichDnsEvent.unit.test.js +94 -0
- package/dist/tests/unit/tasks/dnsEvent/enrichDnsEvent.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js +83 -0
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js.map +1 -1
- package/dist/util/usageCounters.d.ts +1 -1
- package/dist/util/usageCounters.d.ts.map +1 -1
- package/dist/util/usageCounters.js +18 -1
- package/dist/util/usageCounters.js.map +1 -1
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +11 -1
- package/dist/util.js.map +1 -1
- package/package.json +13 -12
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const enrichDnsEvent = async (dnsEvent, ipInfoService, primaryIp) => {
|
|
4
|
+
if (!dnsEvent) {
|
|
5
|
+
return void 0;
|
|
6
|
+
}
|
|
7
|
+
const enriched = {
|
|
8
|
+
peerIp: dnsEvent.peerIp,
|
|
9
|
+
resolverIp: dnsEvent.resolverIp,
|
|
10
|
+
pathValid: dnsEvent.pathValid
|
|
11
|
+
};
|
|
12
|
+
const lookups = [];
|
|
13
|
+
const kinds = [];
|
|
14
|
+
if (dnsEvent.peerIp && dnsEvent.peerIp !== primaryIp) {
|
|
15
|
+
lookups.push(ipInfoService.lookup(dnsEvent.peerIp));
|
|
16
|
+
kinds.push("peer");
|
|
17
|
+
}
|
|
18
|
+
if (dnsEvent.resolverIp && dnsEvent.resolverIp !== primaryIp) {
|
|
19
|
+
lookups.push(ipInfoService.lookup(dnsEvent.resolverIp));
|
|
20
|
+
kinds.push("resolver");
|
|
21
|
+
}
|
|
22
|
+
if (lookups.length === 0) {
|
|
23
|
+
return enriched;
|
|
24
|
+
}
|
|
25
|
+
const results = await Promise.all(lookups);
|
|
26
|
+
kinds.forEach((k, i) => {
|
|
27
|
+
const info = results[i];
|
|
28
|
+
if (!info) return;
|
|
29
|
+
if (k === "peer") enriched.peerIpInfo = info;
|
|
30
|
+
else enriched.resolverIpInfo = info;
|
|
31
|
+
});
|
|
32
|
+
return enriched;
|
|
33
|
+
};
|
|
34
|
+
const getIpInfoAsn = (info) => info?.isValid ? info.asnNumber : void 0;
|
|
35
|
+
const extraIpInfosFromEnrichedDnsEvent = (enriched) => {
|
|
36
|
+
if (!enriched) return [];
|
|
37
|
+
const out = [];
|
|
38
|
+
if (enriched.peerIpInfo) out.push(enriched.peerIpInfo);
|
|
39
|
+
if (enriched.resolverIpInfo) out.push(enriched.resolverIpInfo);
|
|
40
|
+
return out;
|
|
41
|
+
};
|
|
42
|
+
const computeDnsAsymmetry = (enriched, clientIpInfo) => {
|
|
43
|
+
if (!enriched) return 0;
|
|
44
|
+
let score = 0;
|
|
45
|
+
if (enriched.pathValid === false) score += 0.3;
|
|
46
|
+
if (enriched.resolverIpInfo?.isValid) {
|
|
47
|
+
if (enriched.resolverIpInfo.isDatacenter) score += 0.3;
|
|
48
|
+
if (enriched.resolverIpInfo.isAbuser) score += 0.2;
|
|
49
|
+
}
|
|
50
|
+
if (enriched.peerIpInfo?.isValid) {
|
|
51
|
+
if (enriched.peerIpInfo.isDatacenter) score += 0.2;
|
|
52
|
+
if (enriched.peerIpInfo.isAbuser) score += 0.2;
|
|
53
|
+
}
|
|
54
|
+
if (clientIpInfo?.isValid && clientIpInfo.providerType === "isp" && enriched.resolverIpInfo?.isValid && enriched.resolverIpInfo.isDatacenter) {
|
|
55
|
+
score += 0.2;
|
|
56
|
+
}
|
|
57
|
+
return Math.min(score, 1);
|
|
58
|
+
};
|
|
59
|
+
exports.computeDnsAsymmetry = computeDnsAsymmetry;
|
|
60
|
+
exports.enrichDnsEvent = enrichDnsEvent;
|
|
61
|
+
exports.extraIpInfosFromEnrichedDnsEvent = extraIpInfosFromEnrichedDnsEvent;
|
|
62
|
+
exports.getIpInfoAsn = getIpInfoAsn;
|
|
@@ -13,6 +13,7 @@ const util = require("../../util.cjs");
|
|
|
13
13
|
const usageCounters = require("../../util/usageCounters.cjs");
|
|
14
14
|
const captchaManager = require("../captchaManager.cjs");
|
|
15
15
|
const decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
16
|
+
const enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
16
17
|
require("../frictionless/frictionlessTasks.cjs");
|
|
17
18
|
const frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
18
19
|
const evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
@@ -174,8 +175,13 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
174
175
|
);
|
|
175
176
|
if (pendingRequest) {
|
|
176
177
|
const { storedCaptchas, receivedCaptchas, captchaIds } = await this.validateReceivedCaptchasAgainstStoredCaptchas(captchas);
|
|
177
|
-
const
|
|
178
|
-
const
|
|
178
|
+
const rawFlat = receivedCaptchas.map((c) => util$2.extractData(c.salt));
|
|
179
|
+
const { checkbox: checkboxCoordPair, flat } = pairs.peelCheckboxPrefix(
|
|
180
|
+
rawFlat,
|
|
181
|
+
receivedCaptchas.map((c) => c.solution.length)
|
|
182
|
+
);
|
|
183
|
+
const shapePairs = flat.map((list) => pairs.constructPairList(list));
|
|
184
|
+
const pairs$1 = checkboxCoordPair ? [[checkboxCoordPair], ...shapePairs] : shapePairs;
|
|
179
185
|
const { tree, commitmentId } = imgCaptchaTasksUtils.buildTreeAndGetCommitmentId(receivedCaptchas);
|
|
180
186
|
const datasetId = util$2.at(storedCaptchas, 0).datasetId;
|
|
181
187
|
if (!datasetId) {
|
|
@@ -555,17 +561,34 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
555
561
|
failStatus = types.ResultReason.SPAM_EMAIL_RULE;
|
|
556
562
|
}
|
|
557
563
|
}
|
|
564
|
+
const sessionRecord = solution.sessionId ? await this.db.getSessionRecordBySessionId(solution.sessionId) : void 0;
|
|
565
|
+
const enrichedDnsEvent = await enrichDnsEvent.enrichDnsEvent(
|
|
566
|
+
sessionRecord?.dnsEvent,
|
|
567
|
+
env.ipInfoService,
|
|
568
|
+
ip ?? solution.ipInfo?.ip
|
|
569
|
+
);
|
|
558
570
|
if (!failStatus) {
|
|
559
571
|
const check = await this.resolveTrafficFilterCheck(
|
|
560
572
|
env,
|
|
561
573
|
solution.ipInfo,
|
|
562
574
|
trafficFilter,
|
|
563
|
-
ip
|
|
575
|
+
ip,
|
|
576
|
+
enrichedDnsEvent
|
|
564
577
|
);
|
|
565
578
|
if (check.isBlocked) {
|
|
566
579
|
this.logger.info(() => ({
|
|
567
580
|
msg: "Traffic filter rejected request",
|
|
568
|
-
data: {
|
|
581
|
+
data: {
|
|
582
|
+
commitmentId,
|
|
583
|
+
dapp,
|
|
584
|
+
ip,
|
|
585
|
+
reason: check.reason,
|
|
586
|
+
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
587
|
+
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
588
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
589
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
590
|
+
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
591
|
+
}
|
|
569
592
|
}));
|
|
570
593
|
commitmentUpdates.result = {
|
|
571
594
|
status: types.CaptchaStatus.disapproved,
|
|
@@ -588,7 +611,8 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
588
611
|
solutionIpAddress,
|
|
589
612
|
this.logger,
|
|
590
613
|
env.ipInfoService,
|
|
591
|
-
ipValidationRules
|
|
614
|
+
ipValidationRules,
|
|
615
|
+
enrichedDnsEvent?.peerIp
|
|
592
616
|
);
|
|
593
617
|
if (!ipValidation.isValid) {
|
|
594
618
|
this.logger.error(() => ({
|
|
@@ -614,40 +638,48 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
614
638
|
"solved",
|
|
615
639
|
types.CaptchaType.image,
|
|
616
640
|
ipValue,
|
|
617
|
-
solution.userAccount
|
|
641
|
+
solution.userAccount,
|
|
642
|
+
enrichedDnsEvent?.peerIp
|
|
618
643
|
)
|
|
619
644
|
);
|
|
620
645
|
}
|
|
621
646
|
let score;
|
|
622
|
-
if (
|
|
623
|
-
const
|
|
624
|
-
|
|
647
|
+
if (sessionRecord) {
|
|
648
|
+
const dnsAsymmetry = enrichDnsEvent.computeDnsAsymmetry(
|
|
649
|
+
enrichedDnsEvent,
|
|
650
|
+
solution.ipInfo
|
|
625
651
|
);
|
|
626
|
-
if (
|
|
627
|
-
|
|
652
|
+
if (dnsAsymmetry > 0) {
|
|
653
|
+
sessionRecord.scoreComponents = {
|
|
654
|
+
...sessionRecord.scoreComponents,
|
|
655
|
+
dnsAsymmetry
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
score = frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
659
|
+
this.logger.info(() => ({
|
|
660
|
+
data: {
|
|
661
|
+
scoreComponents: sessionRecord?.scoreComponents,
|
|
662
|
+
score,
|
|
663
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
664
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
665
|
+
}
|
|
666
|
+
}));
|
|
667
|
+
if (!failStatus && disallowWebView === true && (sessionRecord.webView === true || (sessionRecord.scoreComponents.webView || 0) > 0)) {
|
|
628
668
|
this.logger.info(() => ({
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
669
|
+
msg: "Disallowing webview access - user not verified"
|
|
670
|
+
}));
|
|
671
|
+
commitmentUpdates.result = {
|
|
672
|
+
status: types.CaptchaStatus.disapproved,
|
|
673
|
+
reason: types.ResultReason.DISALLOWED_WEBVIEW
|
|
674
|
+
};
|
|
675
|
+
failStatus = types.ResultReason.DISALLOWED_WEBVIEW;
|
|
676
|
+
isApproved = false;
|
|
677
|
+
failureStatus = types.ResultReason.DISALLOWED_WEBVIEW;
|
|
678
|
+
}
|
|
679
|
+
if (contextAwareEnabled && sessionRecord.reason === types.FrictionlessReason.CONTEXT_AWARE_VALIDATION_FAILED) {
|
|
680
|
+
this.logger.info(() => ({
|
|
681
|
+
msg: "Context aware validation failed"
|
|
633
682
|
}));
|
|
634
|
-
if (!failStatus && disallowWebView === true && (sessionRecord.webView === true || (sessionRecord.scoreComponents.webView || 0) > 0)) {
|
|
635
|
-
this.logger.info(() => ({
|
|
636
|
-
msg: "Disallowing webview access - user not verified"
|
|
637
|
-
}));
|
|
638
|
-
commitmentUpdates.result = {
|
|
639
|
-
status: types.CaptchaStatus.disapproved,
|
|
640
|
-
reason: types.ResultReason.DISALLOWED_WEBVIEW
|
|
641
|
-
};
|
|
642
|
-
failStatus = types.ResultReason.DISALLOWED_WEBVIEW;
|
|
643
|
-
isApproved = false;
|
|
644
|
-
failureStatus = types.ResultReason.DISALLOWED_WEBVIEW;
|
|
645
|
-
}
|
|
646
|
-
if (contextAwareEnabled && sessionRecord.reason === types.FrictionlessReason.CONTEXT_AWARE_VALIDATION_FAILED) {
|
|
647
|
-
this.logger.info(() => ({
|
|
648
|
-
msg: "Context aware validation failed"
|
|
649
|
-
}));
|
|
650
|
-
}
|
|
651
683
|
}
|
|
652
684
|
}
|
|
653
685
|
if (isApproved) {
|
|
@@ -657,7 +689,8 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
657
689
|
captchaResult: "passed",
|
|
658
690
|
headers: solution.headers,
|
|
659
691
|
captchaType: types.CaptchaType.image,
|
|
660
|
-
countryCode: solution.ipInfo?.isValid ? solution.ipInfo.countryCode : void 0
|
|
692
|
+
countryCode: solution.ipInfo?.isValid ? solution.ipInfo.countryCode : void 0,
|
|
693
|
+
dnsEvent: enrichedDnsEvent
|
|
661
694
|
};
|
|
662
695
|
try {
|
|
663
696
|
const decision = await this.decisionMachineRunner.decide(
|
|
@@ -9,6 +9,7 @@ const util$2 = require("../../util.cjs");
|
|
|
9
9
|
const usageCounters = require("../../util/usageCounters.cjs");
|
|
10
10
|
const captchaManager = require("../captchaManager.cjs");
|
|
11
11
|
const decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
12
|
+
const enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
12
13
|
const frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
13
14
|
const routingMachine = require("../frictionless/routingMachine.cjs");
|
|
14
15
|
const evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
@@ -434,17 +435,34 @@ class PowCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
434
435
|
failReason = "API.SPAM_EMAIL_RULE";
|
|
435
436
|
}
|
|
436
437
|
}
|
|
438
|
+
const sessionRecord = challengeRecord.sessionId ? await this.db.getSessionRecordBySessionId(challengeRecord.sessionId) : void 0;
|
|
439
|
+
const enrichedDnsEvent = await enrichDnsEvent.enrichDnsEvent(
|
|
440
|
+
sessionRecord?.dnsEvent,
|
|
441
|
+
env.ipInfoService,
|
|
442
|
+
ip ?? challengeRecord.ipInfo?.ip
|
|
443
|
+
);
|
|
437
444
|
if (!failResult) {
|
|
438
445
|
const check = await this.resolveTrafficFilterCheck(
|
|
439
446
|
env,
|
|
440
447
|
challengeRecord.ipInfo,
|
|
441
448
|
trafficFilter,
|
|
442
|
-
ip
|
|
449
|
+
ip,
|
|
450
|
+
enrichedDnsEvent
|
|
443
451
|
);
|
|
444
452
|
if (check.isBlocked) {
|
|
445
453
|
this.logger.info(() => ({
|
|
446
454
|
msg: "Traffic filter rejected request in PoW verification",
|
|
447
|
-
data: {
|
|
455
|
+
data: {
|
|
456
|
+
challenge,
|
|
457
|
+
dappAccount,
|
|
458
|
+
ip,
|
|
459
|
+
reason: check.reason,
|
|
460
|
+
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
461
|
+
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
462
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
463
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
464
|
+
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
465
|
+
}
|
|
448
466
|
}));
|
|
449
467
|
failResult = {
|
|
450
468
|
status: types.CaptchaStatus.disapproved,
|
|
@@ -469,7 +487,8 @@ class PowCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
469
487
|
challengeIpAddress,
|
|
470
488
|
this.logger,
|
|
471
489
|
env.ipInfoService,
|
|
472
|
-
ipValidationRules
|
|
490
|
+
ipValidationRules,
|
|
491
|
+
enrichedDnsEvent?.peerIp
|
|
473
492
|
);
|
|
474
493
|
if (!ipValidation.isValid) {
|
|
475
494
|
this.logger.error(() => ({
|
|
@@ -490,19 +509,26 @@ class PowCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
490
509
|
}
|
|
491
510
|
}
|
|
492
511
|
let score;
|
|
493
|
-
if (
|
|
494
|
-
const
|
|
495
|
-
|
|
512
|
+
if (sessionRecord) {
|
|
513
|
+
const dnsAsymmetry = enrichDnsEvent.computeDnsAsymmetry(
|
|
514
|
+
enrichedDnsEvent,
|
|
515
|
+
challengeRecord.ipInfo
|
|
496
516
|
);
|
|
497
|
-
if (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
score
|
|
503
|
-
}
|
|
504
|
-
}));
|
|
517
|
+
if (dnsAsymmetry > 0) {
|
|
518
|
+
sessionRecord.scoreComponents = {
|
|
519
|
+
...sessionRecord.scoreComponents,
|
|
520
|
+
dnsAsymmetry
|
|
521
|
+
};
|
|
505
522
|
}
|
|
523
|
+
score = frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
524
|
+
this.logger.info(() => ({
|
|
525
|
+
data: {
|
|
526
|
+
scoreComponents: { ...sessionRecord?.scoreComponents || {} },
|
|
527
|
+
score,
|
|
528
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
529
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
530
|
+
}
|
|
531
|
+
}));
|
|
506
532
|
}
|
|
507
533
|
if (!failResult) {
|
|
508
534
|
try {
|
|
@@ -514,7 +540,8 @@ class PowCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
514
540
|
captchaType: types.CaptchaType.pow,
|
|
515
541
|
behavioralDataPacked: challengeRecord.behavioralDataPacked,
|
|
516
542
|
deviceCapability: challengeRecord.deviceCapability,
|
|
517
|
-
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0
|
|
543
|
+
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
|
|
544
|
+
dnsEvent: enrichedDnsEvent
|
|
518
545
|
};
|
|
519
546
|
const decision = await this.decisionMachineRunner.decide(
|
|
520
547
|
decisionInput,
|
|
@@ -9,6 +9,7 @@ const util$2 = require("../../util.cjs");
|
|
|
9
9
|
const usageCounters = require("../../util/usageCounters.cjs");
|
|
10
10
|
const captchaManager = require("../captchaManager.cjs");
|
|
11
11
|
const decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
12
|
+
const enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
12
13
|
const frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
13
14
|
const powTasksUtils = require("../powCaptcha/powTasksUtils.cjs");
|
|
14
15
|
const puzzleTasksUtils = require("./puzzleTasksUtils.cjs");
|
|
@@ -365,17 +366,34 @@ class PuzzleCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
365
366
|
}));
|
|
366
367
|
}
|
|
367
368
|
}
|
|
369
|
+
const sessionRecord = challengeRecord.sessionId ? await this.db.getSessionRecordBySessionId(challengeRecord.sessionId) : void 0;
|
|
370
|
+
const enrichedDnsEvent = await enrichDnsEvent.enrichDnsEvent(
|
|
371
|
+
sessionRecord?.dnsEvent,
|
|
372
|
+
env.ipInfoService,
|
|
373
|
+
ip ?? challengeRecord.ipInfo?.ip
|
|
374
|
+
);
|
|
368
375
|
{
|
|
369
376
|
const check = await this.resolveTrafficFilterCheck(
|
|
370
377
|
env,
|
|
371
378
|
challengeRecord.ipInfo,
|
|
372
379
|
trafficFilter,
|
|
373
|
-
ip
|
|
380
|
+
ip,
|
|
381
|
+
enrichedDnsEvent
|
|
374
382
|
);
|
|
375
383
|
if (check.isBlocked) {
|
|
376
384
|
this.logger.info(() => ({
|
|
377
385
|
msg: "Traffic filter rejected request in puzzle verification",
|
|
378
|
-
data: {
|
|
386
|
+
data: {
|
|
387
|
+
challenge,
|
|
388
|
+
dappAccount,
|
|
389
|
+
ip,
|
|
390
|
+
reason: check.reason,
|
|
391
|
+
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
392
|
+
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
393
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
394
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
395
|
+
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
396
|
+
}
|
|
379
397
|
}));
|
|
380
398
|
const blockedResult = {
|
|
381
399
|
status: types.CaptchaStatus.disapproved,
|
|
@@ -413,7 +431,8 @@ class PuzzleCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
413
431
|
challengeIpAddress,
|
|
414
432
|
this.logger,
|
|
415
433
|
env.ipInfoService,
|
|
416
|
-
ipValidationRules
|
|
434
|
+
ipValidationRules,
|
|
435
|
+
enrichedDnsEvent?.peerIp
|
|
417
436
|
);
|
|
418
437
|
if (!ipValidation.isValid) {
|
|
419
438
|
this.logger.error(() => ({
|
|
@@ -443,19 +462,26 @@ class PuzzleCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
443
462
|
}
|
|
444
463
|
}
|
|
445
464
|
let score;
|
|
446
|
-
if (
|
|
447
|
-
const
|
|
448
|
-
|
|
465
|
+
if (sessionRecord) {
|
|
466
|
+
const dnsAsymmetry = enrichDnsEvent.computeDnsAsymmetry(
|
|
467
|
+
enrichedDnsEvent,
|
|
468
|
+
challengeRecord.ipInfo
|
|
449
469
|
);
|
|
450
|
-
if (
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
score
|
|
456
|
-
}
|
|
457
|
-
}));
|
|
470
|
+
if (dnsAsymmetry > 0) {
|
|
471
|
+
sessionRecord.scoreComponents = {
|
|
472
|
+
...sessionRecord.scoreComponents,
|
|
473
|
+
dnsAsymmetry
|
|
474
|
+
};
|
|
458
475
|
}
|
|
476
|
+
score = frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
477
|
+
this.logger.info(() => ({
|
|
478
|
+
data: {
|
|
479
|
+
scoreComponents: { ...sessionRecord?.scoreComponents || {} },
|
|
480
|
+
score,
|
|
481
|
+
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
482
|
+
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
483
|
+
}
|
|
484
|
+
}));
|
|
459
485
|
}
|
|
460
486
|
try {
|
|
461
487
|
const decisionInput = {
|
|
@@ -466,7 +492,8 @@ class PuzzleCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
466
492
|
captchaType: types.CaptchaType.puzzle,
|
|
467
493
|
behavioralDataPacked: challengeRecord.behavioralDataPacked,
|
|
468
494
|
deviceCapability: challengeRecord.deviceCapability,
|
|
469
|
-
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0
|
|
495
|
+
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
|
|
496
|
+
dnsEvent: enrichedDnsEvent
|
|
470
497
|
};
|
|
471
498
|
const decision = await this.decisionMachineRunner.decide(
|
|
472
499
|
decisionInput,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const types = require("@prosopo/types");
|
|
4
|
-
const
|
|
4
|
+
const evaluateIpInfo = (ipInfo, trafficFilter, options) => {
|
|
5
5
|
if (!ipInfo || !ipInfo.isValid) {
|
|
6
6
|
return { isBlocked: false };
|
|
7
7
|
}
|
|
@@ -24,7 +24,7 @@ const checkTrafficFilter = (ipInfo, trafficFilter) => {
|
|
|
24
24
|
return { isBlocked: true, reason: types.ResultReason.ABUSER_BLOCKED };
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
if (trafficFilter.blockDatacenter && ipInfo.isDatacenter) {
|
|
27
|
+
if (trafficFilter.blockDatacenter && ipInfo.isDatacenter && !(options.suppressVpnDatacenterInteraction && ipInfo.isVPN && !trafficFilter.blockVpn)) {
|
|
28
28
|
return { isBlocked: true, reason: types.ResultReason.DATACENTER_BLOCKED };
|
|
29
29
|
}
|
|
30
30
|
if (trafficFilter.blockMobile && ipInfo.isMobile) {
|
|
@@ -38,4 +38,21 @@ const checkTrafficFilter = (ipInfo, trafficFilter) => {
|
|
|
38
38
|
}
|
|
39
39
|
return { isBlocked: false };
|
|
40
40
|
};
|
|
41
|
+
const checkTrafficFilter = (ipInfo, trafficFilter, extraIpInfos) => {
|
|
42
|
+
const primary = evaluateIpInfo(ipInfo, trafficFilter, {
|
|
43
|
+
suppressVpnDatacenterInteraction: true
|
|
44
|
+
});
|
|
45
|
+
if (primary.isBlocked) {
|
|
46
|
+
return primary;
|
|
47
|
+
}
|
|
48
|
+
for (const extra of extraIpInfos ?? []) {
|
|
49
|
+
const result = evaluateIpInfo(extra, trafficFilter, {
|
|
50
|
+
suppressVpnDatacenterInteraction: false
|
|
51
|
+
});
|
|
52
|
+
if (result.isBlocked) {
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { isBlocked: false };
|
|
57
|
+
};
|
|
41
58
|
exports.checkTrafficFilter = checkTrafficFilter;
|
package/dist/cjs/tasks/tasks.cjs
CHANGED
|
@@ -160,7 +160,7 @@ class UsageCounters {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
const buildAllWindowIncrements = (kind, captchaType, ip, userAccount) => {
|
|
163
|
+
const buildAllWindowIncrements = (kind, captchaType, ip, userAccount, peerIp) => {
|
|
164
164
|
const out = [];
|
|
165
165
|
for (const window of [
|
|
166
166
|
"1m",
|
|
@@ -177,6 +177,12 @@ const buildAllWindowIncrements = (kind, captchaType, ip, userAccount) => {
|
|
|
177
177
|
value: userAccount
|
|
178
178
|
}
|
|
179
179
|
);
|
|
180
|
+
if (peerIp && peerIp !== ip) {
|
|
181
|
+
out.push({
|
|
182
|
+
spec: { kind, captchaType, dimension: "peerIp", window },
|
|
183
|
+
value: peerIp
|
|
184
|
+
});
|
|
185
|
+
}
|
|
180
186
|
if (captchaType !== "any") {
|
|
181
187
|
out.push(
|
|
182
188
|
{
|
|
@@ -193,6 +199,17 @@ const buildAllWindowIncrements = (kind, captchaType, ip, userAccount) => {
|
|
|
193
199
|
value: userAccount
|
|
194
200
|
}
|
|
195
201
|
);
|
|
202
|
+
if (peerIp && peerIp !== ip) {
|
|
203
|
+
out.push({
|
|
204
|
+
spec: {
|
|
205
|
+
kind,
|
|
206
|
+
captchaType: "any",
|
|
207
|
+
dimension: "peerIp",
|
|
208
|
+
window
|
|
209
|
+
},
|
|
210
|
+
value: peerIp
|
|
211
|
+
});
|
|
212
|
+
}
|
|
196
213
|
}
|
|
197
214
|
}
|
|
198
215
|
return out;
|
package/dist/cjs/util.cjs
CHANGED
|
@@ -224,7 +224,17 @@ const evaluateIpValidationRules = (comparison, rules, logger) => {
|
|
|
224
224
|
shouldFlag
|
|
225
225
|
};
|
|
226
226
|
};
|
|
227
|
-
const deepValidateIpAddress = async (ip, challengeIpAddress, logger, ipInfoService, ipValidationRules) => {
|
|
227
|
+
const deepValidateIpAddress = async (ip, challengeIpAddress, logger, ipInfoService, ipValidationRules, dnsPeerIp) => {
|
|
228
|
+
if (ipValidationRules?.forceConsistentIp === true && dnsPeerIp && dnsPeerIp !== ip) {
|
|
229
|
+
logger.info(() => ({
|
|
230
|
+
msg: "IP validation failed - dnsEvent.peerIp does not match client IP",
|
|
231
|
+
data: { clientIp: ip, dnsPeerIp }
|
|
232
|
+
}));
|
|
233
|
+
return {
|
|
234
|
+
isValid: false,
|
|
235
|
+
errorMessage: `Client IP ${ip} does not match dnsEvent.peerIp ${dnsPeerIp}`
|
|
236
|
+
};
|
|
237
|
+
}
|
|
228
238
|
const standardValidation = validateIpAddress(ip, challengeIpAddress, logger);
|
|
229
239
|
if (!standardValidation.isValid) {
|
|
230
240
|
if (standardValidation.errorMessage?.includes("Invalid IP address")) {
|
package/dist/pairs.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export declare const constructPairList: (list: number[]) => [number, number][];
|
|
2
|
+
export declare const peelCheckboxPrefix: (flat: number[][], solutionLengths: number[]) => {
|
|
3
|
+
checkbox?: [number, number];
|
|
4
|
+
flat: number[][];
|
|
5
|
+
};
|
|
2
6
|
export declare const containsIdenticalPairs: (pairsLists: [number, number][][]) => boolean;
|
|
3
7
|
//# sourceMappingURL=pairs.d.ts.map
|
package/dist/pairs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairs.d.ts","sourceRoot":"","sources":["../src/pairs.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,iBAAiB,SAAU,MAAM,EAAE,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAWlE,CAAC;AAMF,eAAO,MAAM,sBAAsB,eAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,YActE,CAAC"}
|
|
1
|
+
{"version":3,"file":"pairs.d.ts","sourceRoot":"","sources":["../src/pairs.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,iBAAiB,SAAU,MAAM,EAAE,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAWlE,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACxB,MAAM,EAAE,EAAE,mBACC,MAAM,EAAE,KACvB;IAAE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;CAYjD,CAAC;AAMF,eAAO,MAAM,sBAAsB,eAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,YActE,CAAC"}
|
package/dist/pairs.js
CHANGED
|
@@ -9,6 +9,19 @@ const constructPairList = (list) => {
|
|
|
9
9
|
}
|
|
10
10
|
return pairList;
|
|
11
11
|
};
|
|
12
|
+
const peelCheckboxPrefix = (flat, solutionLengths) => {
|
|
13
|
+
const firstFlat = flat[0];
|
|
14
|
+
const firstLen = solutionLengths[0];
|
|
15
|
+
if (firstFlat === void 0 || firstLen === void 0) {
|
|
16
|
+
return { flat };
|
|
17
|
+
}
|
|
18
|
+
if (firstFlat.length === 2 * firstLen + 2) {
|
|
19
|
+
const checkbox = [at(firstFlat, 0), at(firstFlat, 1)];
|
|
20
|
+
const stripped = [firstFlat.slice(2), ...flat.slice(1)];
|
|
21
|
+
return { checkbox, flat: stripped };
|
|
22
|
+
}
|
|
23
|
+
return { flat };
|
|
24
|
+
};
|
|
12
25
|
const containsIdenticalPairs = (pairsLists) => {
|
|
13
26
|
const set = /* @__PURE__ */ new Set();
|
|
14
27
|
for (const pairList of pairsLists) {
|
|
@@ -23,5 +36,6 @@ const containsIdenticalPairs = (pairsLists) => {
|
|
|
23
36
|
};
|
|
24
37
|
export {
|
|
25
38
|
constructPairList,
|
|
26
|
-
containsIdenticalPairs
|
|
39
|
+
containsIdenticalPairs,
|
|
40
|
+
peelCheckboxPrefix
|
|
27
41
|
};
|
package/dist/pairs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairs.js","sourceRoot":"","sources":["../src/pairs.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAKnC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAc,EAAsB,EAAE;IAEvE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAMF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,UAAgC,EAAE,EAAE;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9B,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtB,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IAGD,OAAO,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACzD,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"pairs.js","sourceRoot":"","sources":["../src/pairs.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAKnC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAc,EAAsB,EAAE;IAEvE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,IAAgB,EAChB,eAAyB,EAC2B,EAAE;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,EAAE,IAAI,EAAE,CAAC;IACjB,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC;AACjB,CAAC,CAAC;AAMF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,UAAgC,EAAE,EAAE;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9B,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtB,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IAGD,OAAO,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACzD,CAAC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RedisWriteQueue } from "@prosopo/database";
|
|
2
2
|
import type { TranslationKey } from "@prosopo/locale";
|
|
3
3
|
import { type Logger } from "@prosopo/logger";
|
|
4
|
-
import { type CaptchaType, type IPInfoResponse, type ITrafficFilter, type KeyringPair, type ProsopoConfigOutput, type RequestHeaders, type Session, type SimdReadingsStage, Tier, type UserCommitment } from "@prosopo/types";
|
|
4
|
+
import { type CaptchaType, type EnrichedDnsEvent, type IPInfoResponse, type ITrafficFilter, type KeyringPair, type ProsopoConfigOutput, type RequestHeaders, type Session, type SimdReadingsStage, Tier, type UserCommitment } from "@prosopo/types";
|
|
5
5
|
import type { ClientRecord, IProviderDatabase, IUserDataSlim, PoWCaptchaRecord, PuzzleCaptchaRecord } from "@prosopo/types-database";
|
|
6
6
|
import type { ProviderEnvironment } from "@prosopo/types-env";
|
|
7
7
|
import { type AccessPolicy, type AccessRulesStorage, type UserScope, type UserScopeRecord } from "@prosopo/user-access-policy";
|
|
@@ -46,7 +46,7 @@ export declare class CaptchaManager {
|
|
|
46
46
|
decryptBehavioralData(encryptedData: string, decryptKeys: (string | undefined)[]): Promise<BehavioralDataResult | null>;
|
|
47
47
|
checkForHardBlock(userAccessRulesStorage: AccessRulesStorage, challengeRecord: PoWCaptchaRecord | PuzzleCaptchaRecord | UserCommitment, userAccount: string, headers: RequestHeaders, coords?: [number, number][][], countryCode?: string, asn?: number): Promise<AccessPolicy | undefined>;
|
|
48
48
|
checkSpamEmail(email: string): Promise<boolean>;
|
|
49
|
-
resolveTrafficFilterCheck(env: ProviderEnvironment, recordIpInfo: IPInfoResponse | undefined, trafficFilter: Partial<ITrafficFilter> | undefined, currentIp?: string): Promise<TrafficCheckResult>;
|
|
49
|
+
resolveTrafficFilterCheck(env: ProviderEnvironment, recordIpInfo: IPInfoResponse | undefined, trafficFilter: Partial<ITrafficFilter> | undefined, currentIp?: string, enrichedDnsEvent?: EnrichedDnsEvent): Promise<TrafficCheckResult>;
|
|
50
50
|
static canClientSeeScore(tier: Tier, score?: number): boolean | 0 | undefined;
|
|
51
51
|
}
|
|
52
52
|
//# sourceMappingURL=captchaManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captchaManager.d.ts","sourceRoot":"","sources":["../../src/tasks/captchaManager.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAEN,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EAEnB,KAAK,OAAO,EACZ,KAAK,iBAAiB,EACtB,IAAI,EACJ,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACN,KAAK,YAAY,EAEjB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,MAAM,6BAA6B,CAAC;AAMrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"captchaManager.d.ts","sourceRoot":"","sources":["../../src/tasks/captchaManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { ResultReason, Tier, ApiParams } from "@prosopo/types";
|
|
|
3
3
|
import { AccessPolicyType } from "@prosopo/user-access-policy";
|
|
4
4
|
import { getPrioritisedAccessRule, getRequestUserScope } from "../api/blacklistRequestInspector.js";
|
|
5
5
|
import { getIpAddressFromComposite } from "../compositeIpAddress.js";
|
|
6
|
+
import { extraIpInfosFromEnrichedDnsEvent } from "./dnsEvent/enrichDnsEvent.js";
|
|
6
7
|
import { checkSpamEmail } from "./spam/checkSpamEmail.js";
|
|
7
8
|
import { checkTrafficFilter } from "./spam/checkTrafficFilter.js";
|
|
8
9
|
const findHardBlockPolicy = (accessPolicies) => {
|
|
@@ -397,6 +398,8 @@ class CaptchaManager {
|
|
|
397
398
|
* - If the dapp's server passed up the end user's current IP via the
|
|
398
399
|
* verify call, look that up fresh — it's the "now" IP for filtering
|
|
399
400
|
* and may differ from the IP that originally requested the captcha.
|
|
401
|
+
* - When the session carries a `dnsEvent`, its `peerIp` and `resolverIp`
|
|
402
|
+
* are enriched and passed alongside the primary IP.
|
|
400
403
|
* - `blockAbuser` defaults to true so abusive networks are always
|
|
401
404
|
* blocked even when the site hasn't configured a trafficFilter.
|
|
402
405
|
* - Returns `{ isBlocked: false }` if every filter flag is off, without
|
|
@@ -406,14 +409,18 @@ class CaptchaManager {
|
|
|
406
409
|
* updates record / session state differently); this helper just returns
|
|
407
410
|
* the verdict.
|
|
408
411
|
*/
|
|
409
|
-
async resolveTrafficFilterCheck(env, recordIpInfo, trafficFilter, currentIp) {
|
|
412
|
+
async resolveTrafficFilterCheck(env, recordIpInfo, trafficFilter, currentIp, enrichedDnsEvent) {
|
|
410
413
|
const effective = { blockAbuser: true, ...trafficFilter };
|
|
411
414
|
const hasAny = Object.values(effective).some((v) => v);
|
|
412
415
|
if (!hasAny) {
|
|
413
416
|
return { isBlocked: false };
|
|
414
417
|
}
|
|
415
418
|
const ipInfo = currentIp ? await env.ipInfoService.lookup(currentIp) : recordIpInfo;
|
|
416
|
-
return checkTrafficFilter(
|
|
419
|
+
return checkTrafficFilter(
|
|
420
|
+
ipInfo,
|
|
421
|
+
effective,
|
|
422
|
+
extraIpInfosFromEnrichedDnsEvent(enrichedDnsEvent)
|
|
423
|
+
);
|
|
417
424
|
}
|
|
418
425
|
static canClientSeeScore(tier, score) {
|
|
419
426
|
return score && tier && tier !== Tier.Free;
|