@jonathanleelx/meddle 0.4.5-beta.1 → 0.4.5-beta.2
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.
|
@@ -6,7 +6,7 @@ export interface RemoteAccessConfig {
|
|
|
6
6
|
}
|
|
7
7
|
export interface ProxyAccessDecision {
|
|
8
8
|
allowed: boolean;
|
|
9
|
-
statusCode?: 403 | 407;
|
|
9
|
+
statusCode?: 401 | 403 | 407;
|
|
10
10
|
message?: string;
|
|
11
11
|
}
|
|
12
12
|
export interface RemoteAccessSetupTarget {
|
|
@@ -28,6 +28,13 @@ export declare function normalizeIpAddress(address: string | undefined | null):
|
|
|
28
28
|
export declare function isLoopbackAddress(address: string | undefined | null): boolean;
|
|
29
29
|
export declare function isPrivateNetworkAddress(address: string | undefined | null): boolean;
|
|
30
30
|
export declare function authorizeProxyClient(remoteAddress: string | undefined | null, headers: Record<string, string | string[] | undefined>, config: RemoteAccessConfig): ProxyAccessDecision;
|
|
31
|
+
/**
|
|
32
|
+
* Authorize a request to the management interface (Web UI / REST API / WebSocket).
|
|
33
|
+
* Loopback is always allowed; remote clients require remote mode, a private
|
|
34
|
+
* network address, and (when a token is configured) a valid `Authorization`
|
|
35
|
+
* header (Bearer or Basic with username `meddle`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function authorizeManagementRequest(remoteAddress: string | undefined | null, headers: Record<string, string | string[] | undefined>, config: RemoteAccessConfig): ProxyAccessDecision;
|
|
31
38
|
export declare function stripProxyHeaders<T>(headers: Record<string, T>): Record<string, T>;
|
|
32
39
|
export declare function getLanIPv4Addresses(): string[];
|
|
33
40
|
export declare function createRemoteAccessInfo(config: RemoteAccessConfig, addresses: string[], port: number | null): RemoteAccessInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-access.d.ts","sourceRoot":"","sources":["../../core/remote-access.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"remote-access.d.ts","sourceRoot":"","sources":["../../core/remote-access.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,sBAAsB,EAAE,OAAO,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,uBAAuB,EAAE,CAAC;CACtC;AAmBD,wBAAgB,uBAAuB,CACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,MAAM,EAA0B,GACvC,kBAAkB,CAgBpB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAI7E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAK7E;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAsBnF;AA8BD,wBAAgB,oBAAoB,CAChC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,MAAM,EAAE,kBAAkB,GAC3B,mBAAmB,CAYrB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACtC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,MAAM,EAAE,kBAAkB,GAC3B,mBAAmB,CAYrB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CASnB;AAED,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAS9C;AAED,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,MAAM,GAAG,IAAI,GACpB,gBAAgB,CAkBlB;AAcD,wBAAgB,WAAW,CACvB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EAAE,GACvB,OAAO,CAaT;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI9F;AAWD,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,OAAO,EACvB,YAAY,EAAE,OAAO,GACtB,MAAM,CAoCR"}
|
|
@@ -38,6 +38,7 @@ exports.normalizeIpAddress = normalizeIpAddress;
|
|
|
38
38
|
exports.isLoopbackAddress = isLoopbackAddress;
|
|
39
39
|
exports.isPrivateNetworkAddress = isPrivateNetworkAddress;
|
|
40
40
|
exports.authorizeProxyClient = authorizeProxyClient;
|
|
41
|
+
exports.authorizeManagementRequest = authorizeManagementRequest;
|
|
41
42
|
exports.stripProxyHeaders = stripProxyHeaders;
|
|
42
43
|
exports.getLanIPv4Addresses = getLanIPv4Addresses;
|
|
43
44
|
exports.createRemoteAccessInfo = createRemoteAccessInfo;
|
|
@@ -161,6 +162,26 @@ function authorizeProxyClient(remoteAddress, headers, config) {
|
|
|
161
162
|
}
|
|
162
163
|
return { allowed: true };
|
|
163
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Authorize a request to the management interface (Web UI / REST API / WebSocket).
|
|
167
|
+
* Loopback is always allowed; remote clients require remote mode, a private
|
|
168
|
+
* network address, and (when a token is configured) a valid `Authorization`
|
|
169
|
+
* header (Bearer or Basic with username `meddle`).
|
|
170
|
+
*/
|
|
171
|
+
function authorizeManagementRequest(remoteAddress, headers, config) {
|
|
172
|
+
if (isLoopbackAddress(remoteAddress))
|
|
173
|
+
return { allowed: true };
|
|
174
|
+
if (!config.enabled) {
|
|
175
|
+
return { allowed: false, statusCode: 403, message: 'Remote management is disabled' };
|
|
176
|
+
}
|
|
177
|
+
if (!isPrivateNetworkAddress(remoteAddress)) {
|
|
178
|
+
return { allowed: false, statusCode: 403, message: 'Only private network clients are allowed' };
|
|
179
|
+
}
|
|
180
|
+
if (config.token && !hasValidProxyAuthorization(headers['authorization'], config.token)) {
|
|
181
|
+
return { allowed: false, statusCode: 401, message: 'Management authentication required' };
|
|
182
|
+
}
|
|
183
|
+
return { allowed: true };
|
|
184
|
+
}
|
|
164
185
|
function stripProxyHeaders(headers) {
|
|
165
186
|
const result = {};
|
|
166
187
|
for (const [key, value] of Object.entries(headers)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-access.js","sourceRoot":"","sources":["../../core/remote-access.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,0DAmBC;AAED,gDAIC;AAED,8CAKC;AAED,0DAsBC;AA8BD,oDAgBC;AAED,8CAWC;AAED,kDASC;AAED,wDAsBC;AAcD,kCAiBC;AAED,sDAIC;AAWD,oDAyCC;
|
|
1
|
+
{"version":3,"file":"remote-access.js","sourceRoot":"","sources":["../../core/remote-access.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,0DAmBC;AAED,gDAIC;AAED,8CAKC;AAED,0DAsBC;AA8BD,oDAgBC;AAQD,gEAgBC;AAED,8CAWC;AAED,kDASC;AAED,wDAsBC;AAcD,kCAiBC;AAED,sDAIC;AAWD,oDAyCC;AAzTD,+CAAgC;AAChC,yCAA0B;AAC1B,uCAAwB;AA+BxB,SAAS,YAAY,CAAC,KAAyB;IAC3C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACzC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IACzE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,KAAK,CAAA;IAC3E,OAAO,SAAS,CAAA;AACpB,CAAC;AAED,SAAS,UAAU,CAAC,IAAc,EAAE,IAAY;IAC5C,MAAM,MAAM,GAAG,GAAG,IAAI,GAAG,CAAA;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IACvD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;IACjE,OAAO,SAAS,CAAA;AACpB,CAAC;AAED,SAAgB,uBAAuB,CACnC,MAAyB,OAAO,CAAC,GAAG,EACpC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IACrF,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACnD,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACnC,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,SAAS,CAAA;IACnB,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAA;IAE3E,OAAO;QACH,OAAO;QACP,QAAQ,EAAE,GAAG,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QACrE,cAAc,EAAE,YAAY,IAAI,YAAY,IAAI,OAAO;QACvD,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI;KAC/B,CAAA;AACL,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAkC;IACjE,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAA;IACvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACzC,OAAO,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAA;AACjF,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAkC;IAChE,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC9C,IAAI,UAAU,KAAK,KAAK;QAAE,OAAO,IAAI,CAAA;IACrC,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAC5C,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAA;AAC7C,CAAC;AAED,SAAgB,uBAAuB,CAAC,OAAkC;IACtE,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC9C,IAAI,iBAAiB,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAA;IAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACnC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAChD,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE;eAChB,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;eACzD,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;eACxC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAA;IACnD,CAAC;IACD,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;QACtC,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;eACtB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;eACtB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;eACvB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;eACvB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;eACvB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAChD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACtC,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;WACxC,MAAM,CAAC,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;AAC1D,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAqC,EAAE,KAAa;IACpF,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACjD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAE7C,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACtE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,SAAS,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;QAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;QAC7C,OAAO,QAAQ,KAAK,QAAQ,IAAI,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IACpE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC;AAED,SAAgB,oBAAoB,CAChC,aAAwC,EACxC,OAAsD,EACtD,MAA0B;IAE1B,IAAI,iBAAiB,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAA;IAC1F,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAA;IACnG,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAA;IACxF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC5B,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0BAA0B,CACtC,aAAwC,EACxC,OAAsD,EACtD,MAA0B;IAE1B,IAAI,iBAAiB,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAA;IACxF,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAA;IACnG,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACtF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAA;IAC7F,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC5B,CAAC;AAED,SAAgB,iBAAiB,CAC7B,OAA0B;IAE1B,MAAM,MAAM,GAAsB,EAAE,CAAA;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;QACpC,IAAI,UAAU,KAAK,qBAAqB,IAAI,UAAU,KAAK,kBAAkB,EAAE,CAAC;YAC5E,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACvB,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,SAAgB,mBAAmB;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACnE,IAAI,qDAAqD,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAQ;QAC9E,KAAK,MAAM,KAAK,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAChF,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AAChC,CAAC;AAED,SAAgB,sBAAsB,CAClC,MAA0B,EAC1B,SAAmB,EACnB,IAAmB;IAEnB,MAAM,OAAO,GAAG,IAAI,KAAK,IAAI;QACzB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACxB,OAAO;YACP,QAAQ,EAAE,UAAU,OAAO,IAAI,IAAI,EAAE;YACrC,QAAQ,EAAE,UAAU,OAAO,IAAI,IAAI,GAAG;YACtC,cAAc,EAAE,UAAU,OAAO,IAAI,IAAI,iBAAiB;SAC7D,CAAC,CAAC,CAAA;IAEP,OAAO;QACH,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,sBAAsB,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;QACtC,SAAS,EAAE,IAAI;QACf,cAAc,EAAE,gBAAgB;QAChC,OAAO;KACV,CAAA;AACL,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB;IACrC,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,SAAS,EAAE,CAAC,CAAA;QAC1C,OAAO;YACH,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE;YAChF,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC3C,CAAA;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,IAAI,CAAA;IACf,CAAC;AACL,CAAC;AAED,SAAgB,WAAW,CACvB,UAA8B,EAC9B,UAAkB,EAClB,YAAsB;IAEtB,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7B,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IAEvD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;QACvB,WAAW;QACX,WAAW;QACX,KAAK;QACL,EAAE,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE;QAC3B,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;KAC5E,CAAC,CAAA;IACF,OAAO,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AAC1C,CAAC;AAED,SAAgB,qBAAqB,CAAC,SAAiB;IACnD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACxC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,GAAG,EAAE,CAAA;AAC9D,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC7B,OAAO,KAAK;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AAC/B,CAAC;AAED,SAAgB,oBAAoB,CAChC,IAAY,EACZ,IAAY,EACZ,cAAuB,EACvB,YAAqB;IAErB,MAAM,YAAY,GAAG,GAAG,IAAI,IAAI,IAAI,EAAE,CAAA;IACtC,MAAM,IAAI,GAAG,YAAY;QACrB,CAAC,CAAC,sDAAsD;QACxD,CAAC,CAAC,6CAA6C,CAAA;IACnD,MAAM,KAAK,GAAG,cAAc;QACxB,CAAC,CAAC,gFAAgF;QAClF,CAAC,CAAC,uDAAuD,CAAA;IAE7D,OAAO;;;;;;;;;;;;;;;;;8CAiBmC,UAAU,CAAC,IAAI,CAAC,sBAAsB,IAAI;QAChF,IAAI;QACJ,KAAK;0CAC6B,IAAI;;;kBAG5B,UAAU,CAAC,YAAY,CAAC;;;QAGlC,CAAA;AACR,CAAC"}
|
package/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const { resolveMeddleHome } = require('./bin/lib/meddle-home')
|
|
|
26
26
|
const { recordCrash, crashFingerprint } = require('./bin/lib/crash-report')
|
|
27
27
|
const {
|
|
28
28
|
authorizeProxyClient,
|
|
29
|
+
authorizeManagementRequest,
|
|
29
30
|
buildRemoteAccessConfig,
|
|
30
31
|
buildRemoteSetupHtml,
|
|
31
32
|
createRemoteAccessInfo,
|
|
@@ -316,6 +317,13 @@ const proxyServer = http.createServer(async (req, res) => {
|
|
|
316
317
|
return
|
|
317
318
|
}
|
|
318
319
|
|
|
320
|
+
// 远程管理界面:需 remote 模式 + 私有网络 + (配置了 token 时)合法 Authorization
|
|
321
|
+
const managementAuth = authorizeManagementRequest(req.socket.remoteAddress, req.headers, remoteAccess)
|
|
322
|
+
if (managementAuth.allowed) {
|
|
323
|
+
handleLocalRequest(req, res, { expressApp, serverContext, ctx })
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
|
|
319
327
|
if (remoteAccess.enabled && requestUrl.pathname === '/') {
|
|
320
328
|
const html = buildRemoteSetupHtml(
|
|
321
329
|
requestUrl.hostname,
|
|
@@ -331,8 +339,11 @@ const proxyServer = http.createServer(async (req, res) => {
|
|
|
331
339
|
return
|
|
332
340
|
}
|
|
333
341
|
|
|
334
|
-
|
|
335
|
-
res.
|
|
342
|
+
const managementStatus = managementAuth.statusCode || 403
|
|
343
|
+
res.writeHead(managementStatus, { 'Content-Type': 'text/plain; charset=utf-8' })
|
|
344
|
+
res.end(managementStatus === 401
|
|
345
|
+
? 'Authentication required for remote management'
|
|
346
|
+
: 'Remote access to the Meddle management interface is forbidden')
|
|
336
347
|
return
|
|
337
348
|
}
|
|
338
349
|
|
|
@@ -937,13 +948,16 @@ proxyServer.on('upgrade', (req, socket, head) => {
|
|
|
937
948
|
if (err.code !== 'ECONNRESET') proxyDebug('[ws] upgrade socket error:', err.message)
|
|
938
949
|
})
|
|
939
950
|
|
|
940
|
-
if (
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
951
|
+
if (req.url === '/ws' || req.url.startsWith('/ws?')) {
|
|
952
|
+
const wsAuth = authorizeManagementRequest(socket.remoteAddress, req.headers, remoteAccess)
|
|
953
|
+
if (wsAuth.allowed) {
|
|
954
|
+
if (socket._epWsUpgradeHandled) return
|
|
955
|
+
socket._epWsUpgradeHandled = true
|
|
956
|
+
localWSServer.handleUpgrade(req, socket, head, (ws) => {
|
|
957
|
+
localWSServer.emit('connection', ws, req)
|
|
958
|
+
})
|
|
959
|
+
return
|
|
960
|
+
}
|
|
947
961
|
}
|
|
948
962
|
|
|
949
963
|
socket.destroy()
|
package/mcp-server.js
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js')
|
|
7
7
|
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js')
|
|
8
|
+
const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js')
|
|
8
9
|
// MCP SDK zod-compat 仅支持 zod/v3 或 zod/v4-mini 的内部结构,使用默认 zod 会报 _zod undefined
|
|
9
10
|
const z = require('zod/v3')
|
|
11
|
+
const crypto = require('crypto')
|
|
10
12
|
const path = require('path')
|
|
11
13
|
const fs = require('fs')
|
|
12
14
|
const { spawn } = require('child_process')
|
|
@@ -790,6 +792,59 @@ mcpServer.registerTool('route_preview', {
|
|
|
790
792
|
})
|
|
791
793
|
|
|
792
794
|
async function main() {
|
|
795
|
+
// HTTP 传输模式: MEDDLE_MCP_HTTP=1(可选 MEDDLE_BIND_HOST / MEDDLE_MCP_TOKEN)
|
|
796
|
+
if (process.env.MEDDLE_MCP_HTTP === '1' || process.env.MEDDLE_MCP_HTTP === 'true') {
|
|
797
|
+
const express = require('express')
|
|
798
|
+
const { createMcpExpressApp } = require('@modelcontextprotocol/sdk/server/express.js')
|
|
799
|
+
const host = process.env.MEDDLE_BIND_HOST || '127.0.0.1'
|
|
800
|
+
const port = parseInt(process.env.MEDDLE_MCP_PORT || '9010', 10)
|
|
801
|
+
const token = (process.env.MEDDLE_MCP_TOKEN || '').trim() || null
|
|
802
|
+
|
|
803
|
+
let transport = null
|
|
804
|
+
|
|
805
|
+
function authOk(req) {
|
|
806
|
+
if (!token) return true
|
|
807
|
+
const header = req.headers['authorization'] || req.headers['x-mcp-token'] || ''
|
|
808
|
+
if (Array.isArray(header)) return false
|
|
809
|
+
if (header.startsWith('Bearer ')) {
|
|
810
|
+
const candidate = header.slice(7)
|
|
811
|
+
return candidate.length === token.length && crypto.timingSafeEqual(
|
|
812
|
+
Buffer.from(candidate), Buffer.from(token),
|
|
813
|
+
)
|
|
814
|
+
}
|
|
815
|
+
return header === token
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const app = createMcpExpressApp({ host })
|
|
819
|
+
// 鉴权中间件:配置了 token 时校验所有 MCP 请求
|
|
820
|
+
app.use((req, res, next) => {
|
|
821
|
+
if (!authOk(req)) {
|
|
822
|
+
res.status(401).json({ error: 'authentication required' })
|
|
823
|
+
return
|
|
824
|
+
}
|
|
825
|
+
next()
|
|
826
|
+
})
|
|
827
|
+
// 单一 transport 处理所有请求;SDK 的 connect 会接管 onmessage/onclose
|
|
828
|
+
transport = new StreamableHTTPServerTransport({
|
|
829
|
+
sessionIdGenerator: undefined,
|
|
830
|
+
enableJsonResponse: true,
|
|
831
|
+
enableSseResponse: true,
|
|
832
|
+
})
|
|
833
|
+
await mcpServer.connect(transport)
|
|
834
|
+
app.all('/', (req, res) => {
|
|
835
|
+
transport.handleRequest(req, res, req.body)
|
|
836
|
+
})
|
|
837
|
+
|
|
838
|
+
const server = app.listen(port, host, () => {
|
|
839
|
+
console.log(`MCP HTTP server listening on http://${host}:${port}${token ? ' (token auth)' : ''}`)
|
|
840
|
+
})
|
|
841
|
+
server.on('error', (err) => {
|
|
842
|
+
console.error('MCP HTTP server error:', err.message)
|
|
843
|
+
process.exit(1)
|
|
844
|
+
})
|
|
845
|
+
return
|
|
846
|
+
}
|
|
847
|
+
|
|
793
848
|
const transport = new StdioServerTransport()
|
|
794
849
|
await mcpServer.connect(transport)
|
|
795
850
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jonathanleelx/meddle",
|
|
3
|
-
"version": "0.4.5-beta.
|
|
3
|
+
"version": "0.4.5-beta.2",
|
|
4
4
|
"description": "A simple development proxy server with custom routing rules, mock responses, HTTPS interception, and a plugin system",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "index.js",
|