@abtnode/router-provider 1.16.49-beta-20250827-025603-2bb1a7ee → 1.16.49-beta-20250828-131156-98768a61
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/includes/daemon/ssl +3 -0
- package/lib/nginx/index.js +90 -7
- package/lib/util.js +1 -0
- package/package.json +7 -7
package/lib/nginx/index.js
CHANGED
|
@@ -26,6 +26,10 @@ const {
|
|
|
26
26
|
GATEWAY_RATE_LIMIT_GLOBAL,
|
|
27
27
|
GATEWAY_RATE_LIMIT,
|
|
28
28
|
DOMAIN_FOR_IP_SITE_REGEXP,
|
|
29
|
+
CSP_OFFICIAL_SOURCES,
|
|
30
|
+
CSP_SYSTEM_SOURCES,
|
|
31
|
+
CSP_THIRD_PARTY_SOURCES,
|
|
32
|
+
CSP_ICONIFY_SOURCES,
|
|
29
33
|
} = require('@abtnode/constant');
|
|
30
34
|
const { toHex } = require('@ocap/util');
|
|
31
35
|
const promiseRetry = require('promise-retry');
|
|
@@ -164,6 +168,7 @@ class NginxProvider extends BaseProvider {
|
|
|
164
168
|
|
|
165
169
|
this._copyConfigFiles();
|
|
166
170
|
this._ensureDhparam();
|
|
171
|
+
this._ensureDaemonSecurityHeaders();
|
|
167
172
|
this.updateProxyPolicy({ enabled: false });
|
|
168
173
|
this.initialize();
|
|
169
174
|
}
|
|
@@ -303,6 +308,7 @@ class NginxProvider extends BaseProvider {
|
|
|
303
308
|
// if match certificate, then add https server
|
|
304
309
|
this._addHttpsServer({
|
|
305
310
|
conf,
|
|
311
|
+
serviceType: site.serviceType,
|
|
306
312
|
locations: rules,
|
|
307
313
|
certificateFileName: certificate.domain,
|
|
308
314
|
serverName: parsedServerName,
|
|
@@ -314,6 +320,7 @@ class NginxProvider extends BaseProvider {
|
|
|
314
320
|
} else {
|
|
315
321
|
this._addHttpServer({
|
|
316
322
|
conf,
|
|
323
|
+
serviceType: site.serviceType,
|
|
317
324
|
locations: rules,
|
|
318
325
|
serverName: parsedServerName,
|
|
319
326
|
corsAllowedOrigins,
|
|
@@ -581,6 +588,16 @@ class NginxProvider extends BaseProvider {
|
|
|
581
588
|
}
|
|
582
589
|
}
|
|
583
590
|
|
|
591
|
+
_addSecurityHeaders(location, serviceType) {
|
|
592
|
+
if (serviceType === 'daemon') {
|
|
593
|
+
if (fs.existsSync(path.join(this.includesDir, 'daemon', 'security'))) {
|
|
594
|
+
location._add('include', 'includes/daemon/security');
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
location._add('include', 'includes/daemon/ssl');
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
584
601
|
/**
|
|
585
602
|
* Returns:
|
|
586
603
|
* server /flash/ {
|
|
@@ -605,6 +622,7 @@ class NginxProvider extends BaseProvider {
|
|
|
605
622
|
commonHeaders,
|
|
606
623
|
cacheGroup,
|
|
607
624
|
pageGroup,
|
|
625
|
+
serviceType,
|
|
608
626
|
}) {
|
|
609
627
|
server._add('location', concatPath(prefix, suffix, root));
|
|
610
628
|
|
|
@@ -637,6 +655,8 @@ class NginxProvider extends BaseProvider {
|
|
|
637
655
|
location._add('include', 'includes/cache');
|
|
638
656
|
}
|
|
639
657
|
|
|
658
|
+
this._addSecurityHeaders(location, serviceType);
|
|
659
|
+
|
|
640
660
|
// Redirect blocklet traffic
|
|
641
661
|
if (type === ROUTING_RULE_TYPES.BLOCKLET) {
|
|
642
662
|
// FIXME: logic related to server gateway should not in provider
|
|
@@ -680,7 +700,7 @@ class NginxProvider extends BaseProvider {
|
|
|
680
700
|
location._add('proxy_pass', `http://${getUpstreamName(port)}`);
|
|
681
701
|
}
|
|
682
702
|
|
|
683
|
-
_addRedirectTypeLocation({ server, url, redirectCode, prefix, suffix }) {
|
|
703
|
+
_addRedirectTypeLocation({ server, url, redirectCode, prefix, suffix, serviceType }) {
|
|
684
704
|
const cleanUrl = trimEndSlash(url);
|
|
685
705
|
server._add('location', `${concatPath(prefix, suffix)}`);
|
|
686
706
|
const location = this._getLastLocation(server);
|
|
@@ -694,6 +714,8 @@ class NginxProvider extends BaseProvider {
|
|
|
694
714
|
// always allow cors here since we are doing a redirect
|
|
695
715
|
location._add('include', 'includes/cors');
|
|
696
716
|
|
|
717
|
+
this._addSecurityHeaders(location, serviceType);
|
|
718
|
+
|
|
697
719
|
// 如果 prefix 是根路径,则不需要重写,直接将当前的请求附加到设置的重定向地址后面
|
|
698
720
|
if (prefix === '/') {
|
|
699
721
|
location._add('return', `${redirectCode} ${cleanUrl}$request_uri`);
|
|
@@ -704,24 +726,28 @@ class NginxProvider extends BaseProvider {
|
|
|
704
726
|
}
|
|
705
727
|
}
|
|
706
728
|
|
|
707
|
-
_addRewriteTypeLocation({ server, url, prefix, suffix }) {
|
|
729
|
+
_addRewriteTypeLocation({ server, url, prefix, suffix, serviceType }) {
|
|
708
730
|
server._add('location', concatPath(prefix, suffix));
|
|
709
731
|
const location = this._getLastLocation(server);
|
|
732
|
+
|
|
733
|
+
this._addSecurityHeaders(location, serviceType);
|
|
710
734
|
location._add('rewrite', `^${prefix}(.*) ${url}$1 last`);
|
|
711
735
|
}
|
|
712
736
|
|
|
713
|
-
_addNotFoundLocation({ server, prefix, suffix }) {
|
|
737
|
+
_addNotFoundLocation({ server, prefix, suffix, serviceType }) {
|
|
714
738
|
server._add('location', concatPath(prefix, suffix));
|
|
715
739
|
const location = this._getLastLocation(server);
|
|
716
|
-
this._addTailSlashRedirection(location, prefix);
|
|
717
740
|
|
|
741
|
+
this._addSecurityHeaders(location, serviceType);
|
|
742
|
+
this._addTailSlashRedirection(location, prefix);
|
|
718
743
|
location._add('try_files', '$uri /404.html break');
|
|
719
744
|
}
|
|
720
745
|
|
|
721
|
-
_addGeneralProxyLocation({ server, port, prefix, suffix, blockletDid, targetPrefix }) {
|
|
746
|
+
_addGeneralProxyLocation({ server, port, prefix, suffix, blockletDid, targetPrefix, serviceType }) {
|
|
722
747
|
server._add('location', concatPath(prefix, suffix));
|
|
723
748
|
const location = this._getLastLocation(server);
|
|
724
749
|
this._addCommonHeader(location);
|
|
750
|
+
this._addSecurityHeaders(location, serviceType);
|
|
725
751
|
location._add('include', 'includes/proxy');
|
|
726
752
|
if (blockletDid) {
|
|
727
753
|
location._add('proxy_set_header', `X-Blocklet-Did ${blockletDid}`);
|
|
@@ -867,6 +893,61 @@ class NginxProvider extends BaseProvider {
|
|
|
867
893
|
}
|
|
868
894
|
}
|
|
869
895
|
|
|
896
|
+
_ensureDaemonSecurityHeaders() {
|
|
897
|
+
const securityFilePath = path.join(this.includesDir, 'daemon', 'security');
|
|
898
|
+
const cspSources = [
|
|
899
|
+
...CSP_OFFICIAL_SOURCES,
|
|
900
|
+
...CSP_SYSTEM_SOURCES,
|
|
901
|
+
...CSP_THIRD_PARTY_SOURCES,
|
|
902
|
+
...CSP_ICONIFY_SOURCES,
|
|
903
|
+
'data:',
|
|
904
|
+
'blob:',
|
|
905
|
+
'*/__blocklet__.js',
|
|
906
|
+
'*/.well-known/ping',
|
|
907
|
+
];
|
|
908
|
+
const cspPolicy = `default-src 'self'; frame-ancestors 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' ${cspSources.join(' ')}; font-src 'self' data:; connect-src 'self' ${cspSources.join(' ')} */.well-known/ping; base-uri 'self'; object-src 'none'`;
|
|
909
|
+
const cspLine = `add_header Content-Security-Policy "${cspPolicy}" always;`;
|
|
910
|
+
|
|
911
|
+
try {
|
|
912
|
+
if (fs.existsSync(securityFilePath)) {
|
|
913
|
+
logger.info('security include file already exists', { path: securityFilePath });
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
const baseContent = [
|
|
918
|
+
'## Global HTTP security headers (safe baseline)',
|
|
919
|
+
'',
|
|
920
|
+
'# MIME sniffing protection',
|
|
921
|
+
'add_header X-Content-Type-Options "nosniff" always;',
|
|
922
|
+
'# --- Secure Headers Baseline ---',
|
|
923
|
+
'# Hide headers from upstream (in case the upstream app sets them).',
|
|
924
|
+
'# This prevents duplicate values which may cause overly strict policies.',
|
|
925
|
+
'proxy_hide_header Content-Security-Policy;',
|
|
926
|
+
'proxy_hide_header Referrer-Policy;',
|
|
927
|
+
'proxy_hide_header Permissions-Policy;',
|
|
928
|
+
'# Referrer-Policy:',
|
|
929
|
+
'# Controls how much referrer information is included with requests.',
|
|
930
|
+
'# "strict-origin-when-cross-origin" is a balanced choice: full referrer',
|
|
931
|
+
'# for same-origin, origin only for cross-origin, nothing on downgrade.',
|
|
932
|
+
'# Use "no-referrer" if you want the strictest setting.',
|
|
933
|
+
'add_header Referrer-Policy "strict-origin-when-cross-origin" always;',
|
|
934
|
+
'add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=(), bluetooth=(), fullscreen=(), xr-spatial-tracking=(), magnetometer=(), gyroscope=(), accelerometer=(), browsing-topics=()" always;',
|
|
935
|
+
'add_header X-Frame-Options "DENY" always;',
|
|
936
|
+
'# Content-Security-Policy (CSP):',
|
|
937
|
+
'# Mitigates XSS by restricting resource loading.',
|
|
938
|
+
'# This baseline only allows self-hosted resources, blocks framing,',
|
|
939
|
+
'# disallows <base> tag overrides, and disables legacy plugins.',
|
|
940
|
+
'# Adjust sources (script-src, style-src, img-src, etc.) if you need CDNs.',
|
|
941
|
+
cspLine,
|
|
942
|
+
].join('\n');
|
|
943
|
+
|
|
944
|
+
fs.writeFileSync(securityFilePath, baseContent);
|
|
945
|
+
logger.info('security include file updated', { path: securityFilePath });
|
|
946
|
+
} catch (error) {
|
|
947
|
+
logger.error('Failed to update security include file', { error, path: securityFilePath });
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
870
951
|
_addCommonResHeaders(block, headers) {
|
|
871
952
|
if (!headers || Object.prototype.toString.call(headers) !== '[object Object]') {
|
|
872
953
|
return;
|
|
@@ -1019,11 +1100,12 @@ class NginxProvider extends BaseProvider {
|
|
|
1019
1100
|
daemonPort,
|
|
1020
1101
|
commonHeaders,
|
|
1021
1102
|
blockletDid,
|
|
1103
|
+
serviceType,
|
|
1022
1104
|
}) {
|
|
1023
1105
|
const httpServerUnit = this._addHttpServerUnit({ conf, serverName, port });
|
|
1024
1106
|
this._addDefaultLocations({ server: httpServerUnit, daemonPort, serverName });
|
|
1025
1107
|
// eslint-disable-next-line max-len
|
|
1026
|
-
locations.forEach((x) => this._addReverseProxy({ server: httpServerUnit, ...x, serverName, corsAllowedOrigins, commonHeaders, blockletDid })); // prettier-ignore
|
|
1108
|
+
locations.forEach((x) => this._addReverseProxy({ server: httpServerUnit, ...x, serverName, corsAllowedOrigins, commonHeaders, blockletDid, serviceType })); // prettier-ignore
|
|
1027
1109
|
}
|
|
1028
1110
|
|
|
1029
1111
|
_addHttpsServer({
|
|
@@ -1031,6 +1113,7 @@ class NginxProvider extends BaseProvider {
|
|
|
1031
1113
|
locations,
|
|
1032
1114
|
certificateFileName,
|
|
1033
1115
|
serverName,
|
|
1116
|
+
serviceType,
|
|
1034
1117
|
corsAllowedOrigins,
|
|
1035
1118
|
daemonPort,
|
|
1036
1119
|
commonHeaders,
|
|
@@ -1043,7 +1126,7 @@ class NginxProvider extends BaseProvider {
|
|
|
1043
1126
|
|
|
1044
1127
|
this._addDefaultLocations({ server: httpsServerUnit, daemonPort, serverName });
|
|
1045
1128
|
// eslint-disable-next-line max-len
|
|
1046
|
-
locations.forEach((x) => this._addReverseProxy({ server: httpsServerUnit, ...x, serverName, corsAllowedOrigins, commonHeaders, blockletDid })); // prettier-ignore
|
|
1129
|
+
locations.forEach((x) => this._addReverseProxy({ server: httpsServerUnit, ...x, serverName, corsAllowedOrigins, commonHeaders, blockletDid, serviceType })); // prettier-ignore
|
|
1047
1130
|
}
|
|
1048
1131
|
|
|
1049
1132
|
_addHttpServerUnit({ conf, serverName, port = '' }) {
|
package/lib/util.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/router-provider",
|
|
3
|
-
"version": "1.16.49-beta-
|
|
3
|
+
"version": "1.16.49-beta-20250828-131156-98768a61",
|
|
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,11 +32,11 @@
|
|
|
32
32
|
"url": "https://github.com/ArcBlock/blocklet-server/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@abtnode/constant": "1.16.49-beta-
|
|
36
|
-
"@abtnode/db-cache": "1.16.49-beta-
|
|
37
|
-
"@abtnode/logger": "1.16.49-beta-
|
|
38
|
-
"@abtnode/router-templates": "1.16.49-beta-
|
|
39
|
-
"@abtnode/util": "1.16.49-beta-
|
|
35
|
+
"@abtnode/constant": "1.16.49-beta-20250828-131156-98768a61",
|
|
36
|
+
"@abtnode/db-cache": "1.16.49-beta-20250828-131156-98768a61",
|
|
37
|
+
"@abtnode/logger": "1.16.49-beta-20250828-131156-98768a61",
|
|
38
|
+
"@abtnode/router-templates": "1.16.49-beta-20250828-131156-98768a61",
|
|
39
|
+
"@abtnode/util": "1.16.49-beta-20250828-131156-98768a61",
|
|
40
40
|
"@arcblock/http-proxy": "^1.19.1",
|
|
41
41
|
"@arcblock/is-valid-domain": "^1.0.5",
|
|
42
42
|
"@ocap/util": "^1.23.1",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"bluebird": "^3.7.2",
|
|
63
63
|
"fs-extra": "^11.2.0"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "2d2312333cf9dd50034609c678f2fd777e0ba25a"
|
|
66
66
|
}
|