@requestly/requestly-proxy 1.0.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/LICENSE +201 -0
- package/README.md +5 -0
- package/dist/components/interfaces/logger-service.d.ts +4 -0
- package/dist/components/interfaces/logger-service.js +2 -0
- package/dist/components/interfaces/rules-data-source.d.ts +6 -0
- package/dist/components/interfaces/rules-data-source.js +2 -0
- package/dist/components/proxy-middleware/constants.d.ts +11 -0
- package/dist/components/proxy-middleware/constants.js +21 -0
- package/dist/components/proxy-middleware/helpers/ctx_rq_namespace.d.ts +35 -0
- package/dist/components/proxy-middleware/helpers/ctx_rq_namespace.js +96 -0
- package/dist/components/proxy-middleware/helpers/harObectCreator.d.ts +140 -0
- package/dist/components/proxy-middleware/helpers/harObectCreator.js +158 -0
- package/dist/components/proxy-middleware/helpers/http_helpers.d.ts +2 -0
- package/dist/components/proxy-middleware/helpers/http_helpers.js +47 -0
- package/dist/components/proxy-middleware/helpers/proxy_ctx_helper.d.ts +14 -0
- package/dist/components/proxy-middleware/helpers/proxy_ctx_helper.js +86 -0
- package/dist/components/proxy-middleware/helpers/response_helper.d.ts +3 -0
- package/dist/components/proxy-middleware/helpers/response_helper.js +17 -0
- package/dist/components/proxy-middleware/helpers/rule_processor_helper.d.ts +17 -0
- package/dist/components/proxy-middleware/helpers/rule_processor_helper.js +192 -0
- package/dist/components/proxy-middleware/index.d.ts +25 -0
- package/dist/components/proxy-middleware/index.js +257 -0
- package/dist/components/proxy-middleware/middlewares/amiusing_middleware.d.ts +6 -0
- package/dist/components/proxy-middleware/middlewares/amiusing_middleware.js +25 -0
- package/dist/components/proxy-middleware/middlewares/logger_middleware.d.ts +66 -0
- package/dist/components/proxy-middleware/middlewares/logger_middleware.js +89 -0
- package/dist/components/proxy-middleware/middlewares/rules_middleware.d.ts +40 -0
- package/dist/components/proxy-middleware/middlewares/rules_middleware.js +117 -0
- package/dist/components/proxy-middleware/middlewares/ssl_cert_middleware.d.ts +7 -0
- package/dist/components/proxy-middleware/middlewares/ssl_cert_middleware.js +33 -0
- package/dist/components/proxy-middleware/rule_action_processor/handle_mixed_response.d.ts +14 -0
- package/dist/components/proxy-middleware/rule_action_processor/handle_mixed_response.js +78 -0
- package/dist/components/proxy-middleware/rule_action_processor/index.d.ts +13 -0
- package/dist/components/proxy-middleware/rule_action_processor/index.js +101 -0
- package/dist/components/proxy-middleware/rule_action_processor/modified_requests_pool.d.ts +7 -0
- package/dist/components/proxy-middleware/rule_action_processor/modified_requests_pool.js +34 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/block_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/block_processor.js +21 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/delay_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/delay_processor.js +29 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/insert_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/insert_processor.js +154 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_header_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_header_processor.js +69 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_request_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_request_processor.js +89 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_response_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_response_processor.js +109 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_user_agent_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/modify_user_agent_processor.js +25 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/redirect_processor.d.ts +6 -0
- package/dist/components/proxy-middleware/rule_action_processor/processors/redirect_processor.js +58 -0
- package/dist/components/proxy-middleware/rule_action_processor/utils.d.ts +11 -0
- package/dist/components/proxy-middleware/rule_action_processor/utils.js +33 -0
- package/dist/components/ssl-proxying/ssl-proxying-manager.d.ts +3 -0
- package/dist/components/ssl-proxying/ssl-proxying-manager.js +6 -0
- package/dist/constants/cert.d.ts +7 -0
- package/dist/constants/cert.js +13 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -0
- package/dist/lib/proxy/bin/mitm-proxy.d.ts +2 -0
- package/dist/lib/proxy/bin/mitm-proxy.js +30 -0
- package/dist/lib/proxy/custom/utils/checkInvalidHeaderChar.d.ts +8 -0
- package/dist/lib/proxy/custom/utils/checkInvalidHeaderChar.js +14 -0
- package/dist/lib/proxy/index.d.ts +2 -0
- package/dist/lib/proxy/index.js +2 -0
- package/dist/lib/proxy/lib/ca.d.ts +8 -0
- package/dist/lib/proxy/lib/ca.js +277 -0
- package/dist/lib/proxy/lib/middleware/gunzip.d.ts +2 -0
- package/dist/lib/proxy/lib/middleware/gunzip.js +17 -0
- package/dist/lib/proxy/lib/middleware/wildcard.d.ts +1 -0
- package/dist/lib/proxy/lib/middleware/wildcard.js +20 -0
- package/dist/lib/proxy/lib/proxy.d.ts +36 -0
- package/dist/lib/proxy/lib/proxy.js +1217 -0
- package/dist/rq-proxy-provider.d.ts +10 -0
- package/dist/rq-proxy-provider.js +20 -0
- package/dist/rq-proxy.d.ts +15 -0
- package/dist/rq-proxy.js +53 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +111 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/circularQueue.d.ts +2 -0
- package/dist/utils/circularQueue.js +31 -0
- package/dist/utils/helpers/rules-helper.d.ts +11 -0
- package/dist/utils/helpers/rules-helper.js +59 -0
- package/dist/utils/index.d.ts +0 -0
- package/dist/utils/index.js +0 -0
- package/package.json +43 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const proxy_1 = require("../../../../lib/proxy");
|
|
16
|
+
const requestly_core_1 = require("@requestly/requestly-core");
|
|
17
|
+
const proxy_ctx_helper_1 = require("../../helpers/proxy_ctx_helper");
|
|
18
|
+
const utils_1 = require("../utils");
|
|
19
|
+
const fs_1 = __importDefault(require("fs"));
|
|
20
|
+
const { types } = require("util");
|
|
21
|
+
const process_modify_response_action = (action, ctx) => {
|
|
22
|
+
const allowed_handlers = [proxy_1.PROXY_HANDLER_TYPE.ON_RESPONSE_END];
|
|
23
|
+
if (!allowed_handlers.includes(ctx.currentHandler)) {
|
|
24
|
+
return (0, utils_1.build_action_processor_response)(action, false);
|
|
25
|
+
}
|
|
26
|
+
if (action.responseType &&
|
|
27
|
+
action.responseType === requestly_core_1.CONSTANTS.RESPONSE_BODY_TYPES.CODE) {
|
|
28
|
+
modify_response_using_code(action, ctx);
|
|
29
|
+
return (0, utils_1.build_action_processor_response)(action, true);
|
|
30
|
+
}
|
|
31
|
+
else if (action.responseType === requestly_core_1.CONSTANTS.RESPONSE_BODY_TYPES.LOCAL_FILE) {
|
|
32
|
+
modify_response_using_local(action, ctx);
|
|
33
|
+
return (0, utils_1.build_action_processor_response)(action, true);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
modify_response(ctx, action.response, action.statusCode);
|
|
37
|
+
return (0, utils_1.build_action_processor_response)(action, true);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const modify_response = (ctx, new_resp, status_code) => {
|
|
41
|
+
ctx.rq_response_body = new_resp;
|
|
42
|
+
ctx.rq_response_status_code = status_code;
|
|
43
|
+
};
|
|
44
|
+
const modify_response_using_local = (action, ctx) => {
|
|
45
|
+
let data;
|
|
46
|
+
try {
|
|
47
|
+
data = fs_1.default.readFileSync(action.response, "utf-8");
|
|
48
|
+
modify_response(ctx, data, action.statusCode);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.log("Some Error while reading file");
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const modify_response_using_code = (action, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
let userFunction = null;
|
|
56
|
+
try {
|
|
57
|
+
userFunction = requestly_core_1.UTILS.GET_FUNCTION_FROM_STRING(action.response);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// User has provided an invalid function
|
|
61
|
+
return modify_response(ctx, "Can't parse Requestly function. Please recheck. Error Code 7201. Actual Error: " +
|
|
62
|
+
error.message);
|
|
63
|
+
}
|
|
64
|
+
if (!userFunction || typeof userFunction !== "function") {
|
|
65
|
+
// User has provided an invalid function
|
|
66
|
+
return modify_response(ctx, "Can't parse Requestly function. Please recheck. Error Code 944.");
|
|
67
|
+
}
|
|
68
|
+
// Everything good so far. Now try to execute user's function
|
|
69
|
+
let finalResponse = null;
|
|
70
|
+
try {
|
|
71
|
+
const args = {
|
|
72
|
+
method: ctx.clientToProxyRequest
|
|
73
|
+
? ctx.clientToProxyRequest.method
|
|
74
|
+
? ctx.clientToProxyRequest.method
|
|
75
|
+
: null
|
|
76
|
+
: null,
|
|
77
|
+
response: ctx.rq_response_body,
|
|
78
|
+
url: (0, proxy_ctx_helper_1.get_request_url)(ctx),
|
|
79
|
+
responseType: ctx.serverToProxyResponse.headers["content-type"],
|
|
80
|
+
requestHeaders: ctx.clientToProxyRequest.headers,
|
|
81
|
+
requestData: null,
|
|
82
|
+
};
|
|
83
|
+
try {
|
|
84
|
+
args.responseJSON = JSON.parse(args.response);
|
|
85
|
+
}
|
|
86
|
+
catch (_a) {
|
|
87
|
+
/*Do nothing -- could not parse body as JSON */
|
|
88
|
+
}
|
|
89
|
+
finalResponse = userFunction(args);
|
|
90
|
+
if (types.isPromise(finalResponse)) {
|
|
91
|
+
finalResponse = yield finalResponse;
|
|
92
|
+
}
|
|
93
|
+
const isResponseJSON = args.responseType && args.responseType.includes("application/json");
|
|
94
|
+
if (typeof finalResponse === "object" && isResponseJSON) {
|
|
95
|
+
finalResponse = JSON.stringify(finalResponse);
|
|
96
|
+
}
|
|
97
|
+
if (finalResponse && typeof finalResponse === "string") {
|
|
98
|
+
return modify_response(ctx, finalResponse, action.statusCode);
|
|
99
|
+
}
|
|
100
|
+
else
|
|
101
|
+
throw new Error("Returned value is not a string");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
// Function parsed but failed to execute
|
|
105
|
+
return modify_response(ctx, "Can't execute Requestly function. Please recheck. Error Code 187. Actual Error: " +
|
|
106
|
+
error.message);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
exports.default = process_modify_response_action;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const proxy_1 = require("../../../../lib/proxy");
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const process_modify_user_agent_action = (action, ctx) => {
|
|
6
|
+
const allowed_handlers = [proxy_1.PROXY_HANDLER_TYPE.ON_REQUEST];
|
|
7
|
+
if (!allowed_handlers.includes(ctx.currentHandler)) {
|
|
8
|
+
return (0, utils_1.build_action_processor_response)(action, false);
|
|
9
|
+
}
|
|
10
|
+
if (ctx.currentHandler == proxy_1.PROXY_HANDLER_TYPE.ON_REQUEST) {
|
|
11
|
+
modify_request_headers(action, ctx);
|
|
12
|
+
return (0, utils_1.build_action_processor_response)(action, true);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const modify_request_headers = (action, ctx) => {
|
|
16
|
+
const newRequestHeaders = action.newRequestHeaders;
|
|
17
|
+
for (var headerName in ctx.proxyToServerRequestOptions.headers) {
|
|
18
|
+
if (ctx.proxyToServerRequestOptions.headers.hasOwnProperty(headerName)) {
|
|
19
|
+
delete ctx.proxyToServerRequestOptions.headers[headerName];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Set Request Headers
|
|
23
|
+
newRequestHeaders.forEach((pair) => (ctx.proxyToServerRequestOptions.headers[pair.name] = pair.value));
|
|
24
|
+
};
|
|
25
|
+
exports.default = process_modify_user_agent_action;
|
package/dist/components/proxy-middleware/rule_action_processor/processors/redirect_processor.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const proxy_1 = require("../../../../lib/proxy");
|
|
16
|
+
const proxy_ctx_helper_1 = require("../../helpers/proxy_ctx_helper");
|
|
17
|
+
const modified_requests_pool_1 = __importDefault(require("../modified_requests_pool"));
|
|
18
|
+
const handle_mixed_response_1 = __importDefault(require("../handle_mixed_response"));
|
|
19
|
+
const utils_1 = require("../utils");
|
|
20
|
+
const { URL } = require("url");
|
|
21
|
+
// adding util to get origin header for handling cors
|
|
22
|
+
const getRequestOrigin = (ctx) => {
|
|
23
|
+
const originalRequestHeaders = ctx.rq.original_request.headers || {};
|
|
24
|
+
return (originalRequestHeaders["Origin"] ||
|
|
25
|
+
originalRequestHeaders["origin"] ||
|
|
26
|
+
originalRequestHeaders["ORIGIN"]);
|
|
27
|
+
};
|
|
28
|
+
const process_redirect_action = (action, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
const allowed_handlers = [proxy_1.PROXY_HANDLER_TYPE.ON_REQUEST];
|
|
30
|
+
if (!allowed_handlers.includes(ctx.currentHandler)) {
|
|
31
|
+
return (0, utils_1.build_action_processor_response)(action, false);
|
|
32
|
+
}
|
|
33
|
+
const current_url = (0, proxy_ctx_helper_1.get_request_url)(ctx);
|
|
34
|
+
const new_url = action.url;
|
|
35
|
+
const request_url = current_url.replace(/www\./g, "");
|
|
36
|
+
// Skip if already redirected
|
|
37
|
+
if (modified_requests_pool_1.default.isURLModified(request_url)) {
|
|
38
|
+
// Do nothing
|
|
39
|
+
return (0, utils_1.build_action_processor_response)(action, false);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
modified_requests_pool_1.default.add(new_url);
|
|
43
|
+
}
|
|
44
|
+
const { status: isMixedResponse, response_data } = yield (0, handle_mixed_response_1.default)(ctx, new_url);
|
|
45
|
+
if (isMixedResponse) {
|
|
46
|
+
return (0, utils_1.build_action_processor_response)(action, true, (0, utils_1.build_post_process_data)(response_data.status_code, response_data.headers, response_data.body));
|
|
47
|
+
}
|
|
48
|
+
// If this is a pre-flight request, don't redirect it
|
|
49
|
+
if ((0, proxy_ctx_helper_1.is_request_preflight)(ctx))
|
|
50
|
+
return true;
|
|
51
|
+
return (0, utils_1.build_action_processor_response)(action, true, (0, utils_1.build_post_process_data)(307, {
|
|
52
|
+
"Cache-Control": "no-cache",
|
|
53
|
+
"Access-Control-Allow-Origin": getRequestOrigin(ctx) || "*",
|
|
54
|
+
"Access-Control-Allow-Credentials": "true",
|
|
55
|
+
Location: new_url,
|
|
56
|
+
}, null));
|
|
57
|
+
});
|
|
58
|
+
exports.default = process_redirect_action;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function build_action_processor_response(action: any, success?: boolean, post_process_data?: any): {
|
|
2
|
+
action: any;
|
|
3
|
+
success: boolean;
|
|
4
|
+
post_process_data: any;
|
|
5
|
+
};
|
|
6
|
+
export function build_post_process_data(status_code: any, headers: any, body: any): {
|
|
7
|
+
status_code: any;
|
|
8
|
+
headers: any;
|
|
9
|
+
body: any;
|
|
10
|
+
};
|
|
11
|
+
export function get_success_actions_from_action_results(action_result_objs?: any[]): any[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.get_success_actions_from_action_results = exports.build_post_process_data = exports.build_action_processor_response = void 0;
|
|
4
|
+
const build_action_processor_response = (action, success = false, post_process_data = null) => {
|
|
5
|
+
let resp = {
|
|
6
|
+
action: action,
|
|
7
|
+
success: success,
|
|
8
|
+
post_process_data: post_process_data,
|
|
9
|
+
};
|
|
10
|
+
return resp;
|
|
11
|
+
};
|
|
12
|
+
exports.build_action_processor_response = build_action_processor_response;
|
|
13
|
+
const build_post_process_data = (status_code, headers, body) => {
|
|
14
|
+
if (!status_code && !headers && !body) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
let data = {
|
|
18
|
+
status_code,
|
|
19
|
+
headers,
|
|
20
|
+
body,
|
|
21
|
+
};
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
exports.build_post_process_data = build_post_process_data;
|
|
25
|
+
const get_success_actions_from_action_results = (action_result_objs = []) => {
|
|
26
|
+
if (!action_result_objs) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
// BY default success is false
|
|
30
|
+
const success_action_results_objs = action_result_objs.filter((obj) => obj && obj && obj.success === true);
|
|
31
|
+
return success_action_results_objs.map((obj) => obj.action);
|
|
32
|
+
};
|
|
33
|
+
exports.get_success_actions_from_action_results = get_success_actions_from_action_results;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.certConfig = void 0;
|
|
4
|
+
exports.certConfig = {
|
|
5
|
+
CERT_NAME: "RQProxyCA",
|
|
6
|
+
CERT_VALIDITY: {
|
|
7
|
+
// Number of days - before the current date - Keep minimum 1 to avoid 12am date change issues
|
|
8
|
+
START_BEFORE: 1,
|
|
9
|
+
// Number of days - after the current date - Keep minimum 1 to avoid 12am date change issues
|
|
10
|
+
// CAUTION : Increasing this count might affect current app users
|
|
11
|
+
END_AFTER: 365,
|
|
12
|
+
},
|
|
13
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RQProxyProvider = exports.RQProxy = void 0;
|
|
7
|
+
const rq_proxy_1 = __importDefault(require("./rq-proxy"));
|
|
8
|
+
exports.RQProxy = rq_proxy_1.default;
|
|
9
|
+
const rq_proxy_provider_1 = __importDefault(require("./rq-proxy-provider"));
|
|
10
|
+
exports.RQProxyProvider = rq_proxy_provider_1.default;
|
|
11
|
+
exports.default = rq_proxy_1.default;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var yargs = require("yargs");
|
|
4
|
+
var debug = require("debug")("http-mitm-proxy:bin");
|
|
5
|
+
var args = yargs
|
|
6
|
+
.alias("h", "help")
|
|
7
|
+
.alias("h", "?")
|
|
8
|
+
.options("port", {
|
|
9
|
+
default: 80,
|
|
10
|
+
describe: "HTTP Port.",
|
|
11
|
+
})
|
|
12
|
+
.alias("p", "port")
|
|
13
|
+
.options("host", {
|
|
14
|
+
describe: "HTTP Listen Interface.",
|
|
15
|
+
}).argv;
|
|
16
|
+
if (args.help) {
|
|
17
|
+
yargs.showHelp();
|
|
18
|
+
process.exit(-1);
|
|
19
|
+
}
|
|
20
|
+
var proxy = require("../lib/proxy")();
|
|
21
|
+
proxy.onError(function (ctx, err, errorKind) {
|
|
22
|
+
debug(errorKind, err);
|
|
23
|
+
});
|
|
24
|
+
proxy.listen(args, function (err) {
|
|
25
|
+
if (err) {
|
|
26
|
+
debug("Failed to start listening on port " + args.port, err);
|
|
27
|
+
return process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
debug("proxy listening on " + args.port);
|
|
30
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export = checkInvalidHeaderChar;
|
|
2
|
+
/**
|
|
3
|
+
* True if val contains an invalid field-vchar
|
|
4
|
+
* field-value = *( field-content / obs-fold )
|
|
5
|
+
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
|
6
|
+
* field-vchar = VCHAR / obs-text
|
|
7
|
+
*/
|
|
8
|
+
declare function checkInvalidHeaderChar(val: any): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sagar - Polyfill for _http_common.js
|
|
3
|
+
*/
|
|
4
|
+
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
|
|
5
|
+
/**
|
|
6
|
+
* True if val contains an invalid field-vchar
|
|
7
|
+
* field-value = *( field-content / obs-fold )
|
|
8
|
+
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
|
9
|
+
* field-vchar = VCHAR / obs-text
|
|
10
|
+
*/
|
|
11
|
+
function checkInvalidHeaderChar(val) {
|
|
12
|
+
return headerCharRegex.test(val);
|
|
13
|
+
}
|
|
14
|
+
module.exports = checkInvalidHeaderChar;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Sentry
|
|
3
|
+
var Sentry = require("@sentry/browser");
|
|
4
|
+
// Config
|
|
5
|
+
const staticConfig = require("../../../constants/cert").certConfig;
|
|
6
|
+
var FS = require("fs");
|
|
7
|
+
var path = require("path");
|
|
8
|
+
var Forge = require("node-forge");
|
|
9
|
+
var pki = Forge.pki;
|
|
10
|
+
var mkdirp = require("mkdirp");
|
|
11
|
+
var async = require("async");
|
|
12
|
+
var CAattrs = [
|
|
13
|
+
{
|
|
14
|
+
name: "commonName",
|
|
15
|
+
value: staticConfig.CERT_NAME,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "countryName",
|
|
19
|
+
value: "Internet",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
shortName: "ST",
|
|
23
|
+
value: "Internet",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "localityName",
|
|
27
|
+
value: "Internet",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "organizationName",
|
|
31
|
+
value: staticConfig.CERT_NAME,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
shortName: "OU",
|
|
35
|
+
value: "CA",
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
var CAextensions = [
|
|
39
|
+
{
|
|
40
|
+
name: "basicConstraints",
|
|
41
|
+
cA: true,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "keyUsage",
|
|
45
|
+
keyCertSign: true,
|
|
46
|
+
digitalSignature: true,
|
|
47
|
+
nonRepudiation: true,
|
|
48
|
+
keyEncipherment: true,
|
|
49
|
+
dataEncipherment: true,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "extKeyUsage",
|
|
53
|
+
serverAuth: true,
|
|
54
|
+
clientAuth: true,
|
|
55
|
+
codeSigning: true,
|
|
56
|
+
emailProtection: true,
|
|
57
|
+
timeStamping: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "nsCertType",
|
|
61
|
+
client: true,
|
|
62
|
+
server: true,
|
|
63
|
+
email: true,
|
|
64
|
+
objsign: true,
|
|
65
|
+
sslCA: true,
|
|
66
|
+
emailCA: true,
|
|
67
|
+
objCA: true,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "subjectKeyIdentifier",
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
var ServerAttrs = [
|
|
74
|
+
{
|
|
75
|
+
name: "countryName",
|
|
76
|
+
value: "Internet",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
shortName: "ST",
|
|
80
|
+
value: "Internet",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "localityName",
|
|
84
|
+
value: "Internet",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "organizationName",
|
|
88
|
+
value: staticConfig.CERT_NAME,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
shortName: "OU",
|
|
92
|
+
value: staticConfig.CERT_NAME,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
var ServerExtensions = [
|
|
96
|
+
{
|
|
97
|
+
name: "basicConstraints",
|
|
98
|
+
cA: false,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "keyUsage",
|
|
102
|
+
keyCertSign: false,
|
|
103
|
+
digitalSignature: true,
|
|
104
|
+
nonRepudiation: false,
|
|
105
|
+
keyEncipherment: true,
|
|
106
|
+
dataEncipherment: true,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "extKeyUsage",
|
|
110
|
+
serverAuth: true,
|
|
111
|
+
clientAuth: true,
|
|
112
|
+
codeSigning: false,
|
|
113
|
+
emailProtection: false,
|
|
114
|
+
timeStamping: false,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "nsCertType",
|
|
118
|
+
client: true,
|
|
119
|
+
server: true,
|
|
120
|
+
email: false,
|
|
121
|
+
objsign: false,
|
|
122
|
+
sslCA: false,
|
|
123
|
+
emailCA: false,
|
|
124
|
+
objCA: false,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "subjectKeyIdentifier",
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
var CA = function () { };
|
|
131
|
+
CA.create = function (caFolder, callback) {
|
|
132
|
+
var ca = new CA();
|
|
133
|
+
ca.baseCAFolder = caFolder;
|
|
134
|
+
ca.certsFolder = path.join(ca.baseCAFolder, "certs");
|
|
135
|
+
ca.keysFolder = path.join(ca.baseCAFolder, "keys");
|
|
136
|
+
async.series([
|
|
137
|
+
mkdirp.bind(null, ca.baseCAFolder),
|
|
138
|
+
mkdirp.bind(null, ca.certsFolder),
|
|
139
|
+
mkdirp.bind(null, ca.keysFolder),
|
|
140
|
+
function (callback) {
|
|
141
|
+
FS.exists(path.join(ca.certsFolder, "ca.pem"), function (exists) {
|
|
142
|
+
if (exists) {
|
|
143
|
+
ca.loadCA(callback);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
ca.generateCA(callback);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
], function (err) {
|
|
151
|
+
if (err) {
|
|
152
|
+
return callback(err);
|
|
153
|
+
}
|
|
154
|
+
return callback(null, ca);
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
CA.prototype.randomSerialNumber = function () {
|
|
158
|
+
// generate random 16 bytes hex string
|
|
159
|
+
var sn = "";
|
|
160
|
+
for (var i = 0; i < 4; i++) {
|
|
161
|
+
sn += ("00000000" + Math.floor(Math.random() * Math.pow(256, 4)).toString(16)).slice(-8);
|
|
162
|
+
}
|
|
163
|
+
return sn;
|
|
164
|
+
};
|
|
165
|
+
CA.prototype.generateCA = function (callback) {
|
|
166
|
+
var self = this;
|
|
167
|
+
pki.rsa.generateKeyPair({ bits: 2048 }, function (err, keys) {
|
|
168
|
+
if (err) {
|
|
169
|
+
return callback(err);
|
|
170
|
+
}
|
|
171
|
+
var cert = pki.createCertificate();
|
|
172
|
+
cert.publicKey = keys.publicKey;
|
|
173
|
+
cert.serialNumber = self.randomSerialNumber();
|
|
174
|
+
cert.validity.notBefore = new Date();
|
|
175
|
+
cert.validity.notBefore.setDate(cert.validity.notBefore.getDate() -
|
|
176
|
+
staticConfig.CERT_VALIDITY.START_BEFORE);
|
|
177
|
+
cert.validity.notAfter = new Date();
|
|
178
|
+
cert.validity.notAfter.setDate(cert.validity.notBefore.getDate() + staticConfig.CERT_VALIDITY.END_AFTER);
|
|
179
|
+
cert.setSubject(CAattrs);
|
|
180
|
+
cert.setIssuer(CAattrs);
|
|
181
|
+
cert.setExtensions(CAextensions);
|
|
182
|
+
cert.sign(keys.privateKey, Forge.md.sha256.create());
|
|
183
|
+
self.CAcert = cert;
|
|
184
|
+
self.CAkeys = keys;
|
|
185
|
+
async.parallel([
|
|
186
|
+
FS.writeFile.bind(null, path.join(self.certsFolder, "ca.pem"), pki.certificateToPem(cert)),
|
|
187
|
+
FS.writeFile.bind(null, path.join(self.keysFolder, "ca.private.key"), pki.privateKeyToPem(keys.privateKey)),
|
|
188
|
+
FS.writeFile.bind(null, path.join(self.keysFolder, "ca.public.key"), pki.publicKeyToPem(keys.publicKey)),
|
|
189
|
+
], callback);
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
CA.prototype.loadCA = function (callback) {
|
|
193
|
+
var self = this;
|
|
194
|
+
async.auto({
|
|
195
|
+
certPEM: function (callback) {
|
|
196
|
+
FS.readFile(path.join(self.certsFolder, "ca.pem"), "utf-8", callback);
|
|
197
|
+
},
|
|
198
|
+
keyPrivatePEM: function (callback) {
|
|
199
|
+
FS.readFile(path.join(self.keysFolder, "ca.private.key"), "utf-8", callback);
|
|
200
|
+
},
|
|
201
|
+
keyPublicPEM: function (callback) {
|
|
202
|
+
FS.readFile(path.join(self.keysFolder, "ca.public.key"), "utf-8", callback);
|
|
203
|
+
},
|
|
204
|
+
}, function (err, results) {
|
|
205
|
+
if (err) {
|
|
206
|
+
return callback(err);
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
self.CAcert = pki.certificateFromPem(results.certPEM);
|
|
210
|
+
self.CAkeys = {
|
|
211
|
+
privateKey: pki.privateKeyFromPem(results.keyPrivatePEM),
|
|
212
|
+
publicKey: pki.publicKeyFromPem(results.keyPublicPEM),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
Sentry.captureException(err);
|
|
217
|
+
return callback(err);
|
|
218
|
+
}
|
|
219
|
+
return callback();
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
CA.prototype.generateServerCertificateKeys = function (hosts, cb) {
|
|
223
|
+
var self = this;
|
|
224
|
+
if (typeof hosts === "string")
|
|
225
|
+
hosts = [hosts];
|
|
226
|
+
var mainHost = hosts[0];
|
|
227
|
+
var keysServer = pki.rsa.generateKeyPair(2048);
|
|
228
|
+
var certServer = pki.createCertificate();
|
|
229
|
+
certServer.publicKey = keysServer.publicKey;
|
|
230
|
+
certServer.serialNumber = this.randomSerialNumber();
|
|
231
|
+
certServer.validity.notBefore = new Date();
|
|
232
|
+
certServer.validity.notBefore.setDate(certServer.validity.notBefore.getDate() -
|
|
233
|
+
staticConfig.CERT_VALIDITY.START_BEFORE);
|
|
234
|
+
certServer.validity.notAfter = new Date();
|
|
235
|
+
certServer.validity.notAfter.setDate(certServer.validity.notBefore.getDate() +
|
|
236
|
+
staticConfig.CERT_VALIDITY.END_AFTER);
|
|
237
|
+
var attrsServer = ServerAttrs.slice(0);
|
|
238
|
+
attrsServer.unshift({
|
|
239
|
+
name: "commonName",
|
|
240
|
+
value: mainHost,
|
|
241
|
+
});
|
|
242
|
+
certServer.setSubject(attrsServer);
|
|
243
|
+
certServer.setIssuer(this.CAcert.issuer.attributes);
|
|
244
|
+
certServer.setExtensions(ServerExtensions.concat([
|
|
245
|
+
{
|
|
246
|
+
name: "subjectAltName",
|
|
247
|
+
altNames: hosts.map(function (host) {
|
|
248
|
+
if (host.match(/^[\d\.]+$/)) {
|
|
249
|
+
return { type: 7, ip: host };
|
|
250
|
+
}
|
|
251
|
+
return { type: 2, value: host };
|
|
252
|
+
}),
|
|
253
|
+
},
|
|
254
|
+
]));
|
|
255
|
+
certServer.sign(this.CAkeys.privateKey, Forge.md.sha256.create());
|
|
256
|
+
var certPem = pki.certificateToPem(certServer);
|
|
257
|
+
var keyPrivatePem = pki.privateKeyToPem(keysServer.privateKey);
|
|
258
|
+
var keyPublicPem = pki.publicKeyToPem(keysServer.publicKey);
|
|
259
|
+
FS.writeFile(this.certsFolder + "/" + mainHost.replace(/\*/g, "_") + ".pem", certPem, function (error) {
|
|
260
|
+
if (error)
|
|
261
|
+
console.error("Failed to save certificate to disk in " + self.certsFolder, error);
|
|
262
|
+
});
|
|
263
|
+
FS.writeFile(this.keysFolder + "/" + mainHost.replace(/\*/g, "_") + ".key", keyPrivatePem, function (error) {
|
|
264
|
+
if (error)
|
|
265
|
+
console.error("Failed to save private key to disk in " + self.keysFolder, error);
|
|
266
|
+
});
|
|
267
|
+
FS.writeFile(this.keysFolder + "/" + mainHost.replace(/\*/g, "_") + ".public.key", keyPublicPem, function (error) {
|
|
268
|
+
if (error)
|
|
269
|
+
console.error("Failed to save public key to disk in " + self.keysFolder, error);
|
|
270
|
+
});
|
|
271
|
+
// returns synchronously even before files get written to disk
|
|
272
|
+
cb(certPem, keyPrivatePem);
|
|
273
|
+
};
|
|
274
|
+
CA.prototype.getCACertPath = function () {
|
|
275
|
+
return this.certsFolder + "/ca.pem";
|
|
276
|
+
};
|
|
277
|
+
module.exports = CA;
|