@abtnode/router-provider 1.16.44-beta-20250527-130401-1b9ae926 → 1.16.44-beta-20250529-004636-15e80e20
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/lib/nginx/index.js +104 -3
- package/package.json +7 -6
package/lib/nginx/index.js
CHANGED
|
@@ -26,8 +26,9 @@ const {
|
|
|
26
26
|
GATEWAY_RATE_LIMIT_GLOBAL,
|
|
27
27
|
GATEWAY_RATE_LIMIT,
|
|
28
28
|
} = require('@abtnode/constant');
|
|
29
|
-
|
|
29
|
+
const { toHex } = require('@ocap/util');
|
|
30
30
|
const promiseRetry = require('promise-retry');
|
|
31
|
+
const difference = require('lodash/difference');
|
|
31
32
|
|
|
32
33
|
const logger = require('@abtnode/logger')('router:nginx:controller');
|
|
33
34
|
|
|
@@ -174,6 +175,7 @@ class NginxProvider extends BaseProvider {
|
|
|
174
175
|
proxyPolicy,
|
|
175
176
|
wafPolicy,
|
|
176
177
|
cacheEnabled,
|
|
178
|
+
wafDisabledBlocklets = [],
|
|
177
179
|
} = {}) {
|
|
178
180
|
if (!Array.isArray(routingTable)) {
|
|
179
181
|
throw new Error('routingTable must be an array');
|
|
@@ -228,7 +230,7 @@ class NginxProvider extends BaseProvider {
|
|
|
228
230
|
|
|
229
231
|
this.ensureUpstreamServers(allRules);
|
|
230
232
|
|
|
231
|
-
this._addModSecurity(conf, wafPolicy);
|
|
233
|
+
this._addModSecurity(conf, wafPolicy, wafDisabledBlocklets);
|
|
232
234
|
|
|
233
235
|
// eslint-disable-next-line no-restricted-syntax
|
|
234
236
|
for (const site of sites) {
|
|
@@ -940,7 +942,7 @@ class NginxProvider extends BaseProvider {
|
|
|
940
942
|
return httpsServerUnit;
|
|
941
943
|
}
|
|
942
944
|
|
|
943
|
-
_addModSecurity(conf, wafPolicy = {}) {
|
|
945
|
+
_addModSecurity(conf, wafPolicy = {}, wafDisabledBlocklets = []) {
|
|
944
946
|
if (!wafPolicy.enabled) {
|
|
945
947
|
return;
|
|
946
948
|
}
|
|
@@ -966,6 +968,8 @@ class NginxProvider extends BaseProvider {
|
|
|
966
968
|
fs.writeFileSync(modSecurityConfPath, getModSecurityConf(variables));
|
|
967
969
|
fs.writeFileSync(coreRuleSetConfPath, getCoreRuleSetConf(variables));
|
|
968
970
|
|
|
971
|
+
this.syncCustomCRSFiles({ wafDisabledBlocklets });
|
|
972
|
+
|
|
969
973
|
conf.nginx.http._add('modsecurity', 'on');
|
|
970
974
|
conf.nginx.http._add('modsecurity_transaction_id', '$request_id');
|
|
971
975
|
conf.nginx.http._add('modsecurity_rules_file', modSecurityConfPath);
|
|
@@ -1076,6 +1080,103 @@ class NginxProvider extends BaseProvider {
|
|
|
1076
1080
|
};
|
|
1077
1081
|
}
|
|
1078
1082
|
|
|
1083
|
+
_didToNumber(did) {
|
|
1084
|
+
return parseInt(toHex(Buffer.from(did)).slice(-8), 16);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
_getBlockletWAFTemplateConf({ domainAliases, wafPolicy, defaultWAF = 'On', did = '' }) {
|
|
1088
|
+
if (!Array.isArray(domainAliases) || domainAliases.length === 0) return '';
|
|
1089
|
+
|
|
1090
|
+
const headerComment = [
|
|
1091
|
+
'# ------------------------------------------------------------------------',
|
|
1092
|
+
'# Blocklet WAF Exclusion Rules',
|
|
1093
|
+
'#',
|
|
1094
|
+
`# This file is generated for Blocklet DID: ${did || '[unknown]'} .`,
|
|
1095
|
+
'#',
|
|
1096
|
+
'# The rules below control ModSecurity WAF behavior for specific domains associated with this DID.',
|
|
1097
|
+
'# Each rule disables or enables the WAF engine for requests matching the Host header.',
|
|
1098
|
+
'#',
|
|
1099
|
+
'# DO NOT EDIT THIS FILE MANUALLY.',
|
|
1100
|
+
'# ------------------------------------------------------------------------',
|
|
1101
|
+
'',
|
|
1102
|
+
].join('\n');
|
|
1103
|
+
|
|
1104
|
+
const baseId = 9000000 + (this._didToNumber(did) % 10000);
|
|
1105
|
+
|
|
1106
|
+
const rules = domainAliases
|
|
1107
|
+
.map((domain, idx) => {
|
|
1108
|
+
let rule;
|
|
1109
|
+
if (domain.includes(SLOT_FOR_IP_DNS_SITE)) {
|
|
1110
|
+
// 只匹配 did- 前缀
|
|
1111
|
+
const didPrefix = `${domain.split('-')[0]}-`;
|
|
1112
|
+
rule = `SecRule REQUEST_HEADERS:Host "@contains ${didPrefix}" \\`;
|
|
1113
|
+
} else {
|
|
1114
|
+
rule = `SecRule REQUEST_HEADERS:Host "@streq ${domain}" \\`;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
return `${rule}
|
|
1118
|
+
"id:${baseId + idx},\\
|
|
1119
|
+
phase:1,\\
|
|
1120
|
+
pass,\\
|
|
1121
|
+
nolog,\\
|
|
1122
|
+
tag:'SERVER_WAF',\\
|
|
1123
|
+
tag:'did:${did}',\\
|
|
1124
|
+
ctl:ruleEngine=${wafPolicy?.enabled ? defaultWAF : 'Off'}"`;
|
|
1125
|
+
})
|
|
1126
|
+
.join('\n\n');
|
|
1127
|
+
return `${headerComment}${rules}`;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
addCustomWAFConf({ did, domainAliases, wafPolicy, defaultWAF }) {
|
|
1131
|
+
if (!Array.isArray(domainAliases) || domainAliases.length === 0) return;
|
|
1132
|
+
|
|
1133
|
+
const customDIDConfigPath = path.join(this.includesDir, `security/crs4/rules/REQUEST-900-CUSTOM-RULES-${did}.conf`);
|
|
1134
|
+
|
|
1135
|
+
const confContent = this._getBlockletWAFTemplateConf({
|
|
1136
|
+
domainAliases: domainAliases.map((x) => x.value),
|
|
1137
|
+
defaultWAF,
|
|
1138
|
+
wafPolicy,
|
|
1139
|
+
did,
|
|
1140
|
+
});
|
|
1141
|
+
fs.writeFileSync(customDIDConfigPath, confContent);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
syncCustomCRSFiles({ wafDisabledBlocklets = [] }) {
|
|
1145
|
+
const wafDisabledBlockletsDIDs = wafDisabledBlocklets.map((x) => x.did);
|
|
1146
|
+
const rulesDir = path.join(this.includesDir, 'security/crs4/rules');
|
|
1147
|
+
const prefix = 'REQUEST-900-CUSTOM-RULES-';
|
|
1148
|
+
const files = fs.readdirSync(rulesDir).filter((f) => f.startsWith(prefix));
|
|
1149
|
+
const localWafBlockletsDIDs = files.map((x) => x.replace(prefix, '').replace('.conf', ''));
|
|
1150
|
+
|
|
1151
|
+
const removeList = difference(localWafBlockletsDIDs, wafDisabledBlockletsDIDs);
|
|
1152
|
+
const addList = difference(wafDisabledBlockletsDIDs, localWafBlockletsDIDs);
|
|
1153
|
+
|
|
1154
|
+
logger.info('syncCustomCRSFiles', { removeList, addList });
|
|
1155
|
+
|
|
1156
|
+
if (removeList.length) {
|
|
1157
|
+
const removeFiles = removeList.map((x) => path.join(rulesDir, `${prefix}${x}.conf`));
|
|
1158
|
+
for (const file of removeFiles) {
|
|
1159
|
+
try {
|
|
1160
|
+
fs.rmSync(file, { recursive: true, force: true });
|
|
1161
|
+
} catch (err) {
|
|
1162
|
+
logger.error('Failed to remove custom CRS file', { file, error: err });
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
if (addList.length) {
|
|
1168
|
+
for (const did of addList) {
|
|
1169
|
+
try {
|
|
1170
|
+
const blocklet = wafDisabledBlocklets.find((x) => x.did === did);
|
|
1171
|
+
const domainAliases = blocklet?.site?.domainAliases || [];
|
|
1172
|
+
this.addCustomWAFConf({ did, domainAliases, wafPolicy: { enabled: false }, defaultWAF: 'On' });
|
|
1173
|
+
} catch (error) {
|
|
1174
|
+
logger.error('Failed to add custom CRS file', { did, error });
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1079
1180
|
getLogDir() {
|
|
1080
1181
|
return this.logDir;
|
|
1081
1182
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/router-provider",
|
|
3
|
-
"version": "1.16.44-beta-
|
|
3
|
+
"version": "1.16.44-beta-20250529-004636-15e80e20",
|
|
4
4
|
"description": "Routing engine implementations for abt node",
|
|
5
5
|
"author": "polunzh <polunzh@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ArcBlock/blocklet-server#readme",
|
|
@@ -32,12 +32,13 @@
|
|
|
32
32
|
"url": "https://github.com/ArcBlock/blocklet-server/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@abtnode/constant": "1.16.44-beta-
|
|
36
|
-
"@abtnode/logger": "1.16.44-beta-
|
|
37
|
-
"@abtnode/router-templates": "1.16.44-beta-
|
|
38
|
-
"@abtnode/util": "1.16.44-beta-
|
|
35
|
+
"@abtnode/constant": "1.16.44-beta-20250529-004636-15e80e20",
|
|
36
|
+
"@abtnode/logger": "1.16.44-beta-20250529-004636-15e80e20",
|
|
37
|
+
"@abtnode/router-templates": "1.16.44-beta-20250529-004636-15e80e20",
|
|
38
|
+
"@abtnode/util": "1.16.44-beta-20250529-004636-15e80e20",
|
|
39
39
|
"@arcblock/http-proxy": "^1.19.1",
|
|
40
40
|
"@arcblock/is-valid-domain": "^1.0.5",
|
|
41
|
+
"@ocap/util": "^1.20.11",
|
|
41
42
|
"axios": "^1.7.9",
|
|
42
43
|
"debug": "^4.3.7",
|
|
43
44
|
"fast-glob": "^3.3.2",
|
|
@@ -61,5 +62,5 @@
|
|
|
61
62
|
"bluebird": "^3.7.2",
|
|
62
63
|
"fs-extra": "^11.2.0"
|
|
63
64
|
},
|
|
64
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "93f38f56824d2dd2afcd6950b73a67510d9cd18c"
|
|
65
66
|
}
|