node-mitmproxy-pro 1.0.0 → 1.1.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/README.md +0 -2
- package/lib/bin/index.js +34 -0
- package/lib/common/ProxyHttpAgent.js +37 -0
- package/lib/common/ProxyHttpsAgent.js +37 -0
- package/lib/common/config.js +26 -0
- package/lib/common/util.js +143 -0
- package/lib/index.js +4 -0
- package/lib/middleware/FilterMiddleware.js +1 -0
- package/lib/middleware/HtmlMiddleware.js +107 -0
- package/lib/middleware/MapLocalMiddleware.js +1 -0
- package/lib/middleware/MapRemoteMiddleware.js +1 -0
- package/lib/mitmproxy/createConnectHandler.js +40 -0
- package/lib/mitmproxy/createFakeServerCenter.js +39 -0
- package/lib/mitmproxy/createRequestHandler.js +187 -0
- package/lib/mitmproxy/createUpgradeHandler.js +59 -0
- package/lib/mitmproxy/index.js +100 -0
- package/lib/mitmproxy/middlewareHandler.js +20 -0
- package/lib/tls/CertAndKeyContainer.js +119 -0
- package/lib/tls/FakeServersCenter.js +173 -0
- package/lib/tls/tlsUtils.js +262 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -44,7 +44,6 @@ module.exports = {
|
|
|
44
44
|
效果图:
|
|
45
45
|
<img width=500 src="./doc/img/hello_node-mitmproxy.jpg" />
|
|
46
46
|
|
|
47
|
-
[详细配置说明](https://github.com/CyrilGuoCODE/node-mitmproxy-pro#4配置详细说明)
|
|
48
47
|
[更多例子](./example/config/)
|
|
49
48
|
#### 启动方式
|
|
50
49
|
```
|
|
@@ -61,7 +60,6 @@ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keyc
|
|
|
61
60
|
```
|
|
62
61
|
###### windows
|
|
63
62
|
注: 证书需要安装到 ** 受信任的根证书目录 ** 下
|
|
64
|
-
参考 [issues#3](https://github.com/CyrilGuoCODE/node-mitmproxy-pro/issues/3)
|
|
65
63
|
```
|
|
66
64
|
start %HOMEPATH%/node-mitmproxy-pro/node-mitmproxy-pro.ca.crt
|
|
67
65
|
```
|
package/lib/bin/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
5
|
+
|
|
6
|
+
require('babel-polyfill');
|
|
7
|
+
var mitmproxy = require('../mitmproxy/index');
|
|
8
|
+
var program = require('commander');
|
|
9
|
+
var packageJson = require('../../package.json');
|
|
10
|
+
var tlsUtils = require('../tls/tlsUtils');
|
|
11
|
+
var fs = require('fs');
|
|
12
|
+
var path = require('path');
|
|
13
|
+
var colors = require('colors');
|
|
14
|
+
|
|
15
|
+
fs.existsSync = fs.existsSync || path.existsSync;
|
|
16
|
+
|
|
17
|
+
program.version(packageJson.version).option('-c, --config [value]', 'config file path').parse(process.argv);
|
|
18
|
+
|
|
19
|
+
console.log(program.config);
|
|
20
|
+
|
|
21
|
+
var configPath = path.resolve(program.config);
|
|
22
|
+
|
|
23
|
+
if (fs.existsSync(configPath)) {
|
|
24
|
+
|
|
25
|
+
var configObject = require(configPath);
|
|
26
|
+
|
|
27
|
+
if ((typeof configObject === 'undefined' ? 'undefined' : _typeof(configObject)) !== 'object') {
|
|
28
|
+
console.error(colors.red('Config Error in ' + configPath));
|
|
29
|
+
} else {
|
|
30
|
+
mitmproxy.createProxy(configObject);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
console.error(colors.red('Can not find `config file` file: ' + configPath));
|
|
34
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
4
|
+
|
|
5
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
6
|
+
|
|
7
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
8
|
+
|
|
9
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
10
|
+
|
|
11
|
+
var AgentOrigin = require('agentkeepalive');
|
|
12
|
+
|
|
13
|
+
module.exports = function (_AgentOrigin) {
|
|
14
|
+
_inherits(Agent, _AgentOrigin);
|
|
15
|
+
|
|
16
|
+
function Agent() {
|
|
17
|
+
_classCallCheck(this, Agent);
|
|
18
|
+
|
|
19
|
+
return _possibleConstructorReturn(this, (Agent.__proto__ || Object.getPrototypeOf(Agent)).apply(this, arguments));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_createClass(Agent, [{
|
|
23
|
+
key: 'getName',
|
|
24
|
+
|
|
25
|
+
// Hacky
|
|
26
|
+
value: function getName(option) {
|
|
27
|
+
var name = AgentOrigin.prototype.getName.call(this, option);
|
|
28
|
+
name += ':';
|
|
29
|
+
if (option.customSocketId) {
|
|
30
|
+
name += option.customSocketId;
|
|
31
|
+
}
|
|
32
|
+
return name;
|
|
33
|
+
}
|
|
34
|
+
}]);
|
|
35
|
+
|
|
36
|
+
return Agent;
|
|
37
|
+
}(AgentOrigin);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
4
|
+
|
|
5
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
6
|
+
|
|
7
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
8
|
+
|
|
9
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
10
|
+
|
|
11
|
+
var HttpsAgentOrigin = require('agentkeepalive').HttpsAgent;
|
|
12
|
+
|
|
13
|
+
module.exports = function (_HttpsAgentOrigin) {
|
|
14
|
+
_inherits(HttpsAgent, _HttpsAgentOrigin);
|
|
15
|
+
|
|
16
|
+
function HttpsAgent() {
|
|
17
|
+
_classCallCheck(this, HttpsAgent);
|
|
18
|
+
|
|
19
|
+
return _possibleConstructorReturn(this, (HttpsAgent.__proto__ || Object.getPrototypeOf(HttpsAgent)).apply(this, arguments));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_createClass(HttpsAgent, [{
|
|
23
|
+
key: 'getName',
|
|
24
|
+
|
|
25
|
+
// Hacky
|
|
26
|
+
value: function getName(option) {
|
|
27
|
+
var name = HttpsAgentOrigin.prototype.getName.call(this, option);
|
|
28
|
+
name += ':';
|
|
29
|
+
if (option.customSocketId) {
|
|
30
|
+
name += option.customSocketId;
|
|
31
|
+
}
|
|
32
|
+
return name;
|
|
33
|
+
}
|
|
34
|
+
}]);
|
|
35
|
+
|
|
36
|
+
return HttpsAgent;
|
|
37
|
+
}(HttpsAgentOrigin);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('path');
|
|
4
|
+
|
|
5
|
+
var config = exports;
|
|
6
|
+
|
|
7
|
+
config.caCertFileName = 'node-mitmproxy.ca.crt';
|
|
8
|
+
|
|
9
|
+
config.caKeyFileName = 'node-mitmproxy.ca.key.pem';
|
|
10
|
+
|
|
11
|
+
config.defaultPort = 6789;
|
|
12
|
+
|
|
13
|
+
config.caName = 'node-mitmproxy CA';
|
|
14
|
+
|
|
15
|
+
config.getDefaultCABasePath = function () {
|
|
16
|
+
var userHome = process.env.HOME || process.env.USERPROFILE;
|
|
17
|
+
return path.resolve(userHome, './node-mitmproxy');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
config.getDefaultCACertPath = function () {
|
|
21
|
+
return path.resolve(config.getDefaultCABasePath(), config.caCertFileName);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
config.getDefaultCACertPath = function () {
|
|
25
|
+
return path.resolve(config.getDefaultCABasePath(), config.caKeyFileName);
|
|
26
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var url = require('url');
|
|
4
|
+
var Agent = require('./ProxyHttpAgent');
|
|
5
|
+
var HttpsAgent = require('./ProxyHttpsAgent');
|
|
6
|
+
var tunnelAgent = require('tunnel-agent');
|
|
7
|
+
|
|
8
|
+
var util = exports;
|
|
9
|
+
var httpsAgent = new HttpsAgent({
|
|
10
|
+
keepAlive: true,
|
|
11
|
+
timeout: 60000,
|
|
12
|
+
keepAliveTimeout: 30000, // free socket keepalive for 30 seconds
|
|
13
|
+
rejectUnauthorized: false
|
|
14
|
+
});
|
|
15
|
+
var httpAgent = new Agent({
|
|
16
|
+
keepAlive: true,
|
|
17
|
+
timeout: 60000,
|
|
18
|
+
keepAliveTimeout: 30000 // free socket keepalive for 30 seconds
|
|
19
|
+
});
|
|
20
|
+
var socketId = 0;
|
|
21
|
+
|
|
22
|
+
var httpOverHttpAgent, httpsOverHttpAgent, httpOverHttpsAgent, httpsOverHttpsAgent;
|
|
23
|
+
|
|
24
|
+
util.getOptionsFormRequest = function (req, ssl) {
|
|
25
|
+
var externalProxy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
26
|
+
|
|
27
|
+
var urlObject = url.parse(req.url);
|
|
28
|
+
var defaultPort = ssl ? 443 : 80;
|
|
29
|
+
var protocol = ssl ? 'https:' : 'http:';
|
|
30
|
+
var headers = Object.assign({}, req.headers);
|
|
31
|
+
var externalProxyUrl = null;
|
|
32
|
+
|
|
33
|
+
if (externalProxy) {
|
|
34
|
+
if (typeof externalProxy === 'string') {
|
|
35
|
+
externalProxyUrl = externalProxy;
|
|
36
|
+
} else if (typeof externalProxy === 'function') {
|
|
37
|
+
try {
|
|
38
|
+
externalProxyUrl = externalProxy(req, ssl);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error(e);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
delete headers['proxy-connection'];
|
|
46
|
+
var agent = false;
|
|
47
|
+
if (!externalProxyUrl) {
|
|
48
|
+
// keepAlive
|
|
49
|
+
if (headers.connection !== 'close') {
|
|
50
|
+
if (protocol == 'https:') {
|
|
51
|
+
agent = httpsAgent;
|
|
52
|
+
} else {
|
|
53
|
+
agent = httpAgent;
|
|
54
|
+
}
|
|
55
|
+
headers.connection = 'keep-alive';
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
agent = util.getTunnelAgent(protocol === 'https:', externalProxyUrl);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var options = {
|
|
62
|
+
protocol: protocol,
|
|
63
|
+
hostname: req.headers.host.split(':')[0],
|
|
64
|
+
method: req.method,
|
|
65
|
+
port: req.headers.host.split(':')[1] || defaultPort,
|
|
66
|
+
path: urlObject.path,
|
|
67
|
+
headers: req.headers,
|
|
68
|
+
agent: agent
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (protocol === 'http:' && externalProxyUrl && url.parse(externalProxyUrl).protocol === 'http:') {
|
|
72
|
+
var externalURL = url.parse(externalProxyUrl);
|
|
73
|
+
options.hostname = externalURL.hostname;
|
|
74
|
+
options.port = externalURL.port;
|
|
75
|
+
// support non-transparent proxy
|
|
76
|
+
options.path = 'http://' + urlObject.host + urlObject.path;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// mark a socketId for Agent to bind socket for NTLM
|
|
80
|
+
if (req.socket.customSocketId) {
|
|
81
|
+
options.customSocketId = req.socket.customSocketId;
|
|
82
|
+
} else if (headers['authorization']) {
|
|
83
|
+
options.customSocketId = req.socket.customSocketId = socketId++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return options;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
util.getTunnelAgent = function (requestIsSSL, externalProxyUrl) {
|
|
90
|
+
var urlObject = url.parse(externalProxyUrl);
|
|
91
|
+
var protocol = urlObject.protocol || 'http:';
|
|
92
|
+
var port = urlObject.port;
|
|
93
|
+
if (!port) {
|
|
94
|
+
port = protocol === 'http:' ? 80 : 443;
|
|
95
|
+
}
|
|
96
|
+
var hostname = urlObject.hostname || 'localhost';
|
|
97
|
+
|
|
98
|
+
if (requestIsSSL) {
|
|
99
|
+
if (protocol === 'http:') {
|
|
100
|
+
if (!httpsOverHttpAgent) {
|
|
101
|
+
httpsOverHttpAgent = tunnelAgent.httpsOverHttp({
|
|
102
|
+
proxy: {
|
|
103
|
+
host: hostname,
|
|
104
|
+
port: port
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return httpsOverHttpAgent;
|
|
109
|
+
} else {
|
|
110
|
+
if (!httpsOverHttpsAgent) {
|
|
111
|
+
httpsOverHttpsAgent = tunnelAgent.httpsOverHttps({
|
|
112
|
+
proxy: {
|
|
113
|
+
host: hostname,
|
|
114
|
+
port: port
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return httpsOverHttpsAgent;
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
if (protocol === 'http:') {
|
|
122
|
+
// if (!httpOverHttpAgent) {
|
|
123
|
+
// httpOverHttpAgent = tunnelAgent.httpOverHttp({
|
|
124
|
+
// proxy: {
|
|
125
|
+
// host: hostname,
|
|
126
|
+
// port: port
|
|
127
|
+
// }
|
|
128
|
+
// });
|
|
129
|
+
// }
|
|
130
|
+
return false;
|
|
131
|
+
} else {
|
|
132
|
+
if (!httpOverHttpsAgent) {
|
|
133
|
+
httpOverHttpsAgent = tunnelAgent.httpOverHttps({
|
|
134
|
+
proxy: {
|
|
135
|
+
host: hostname,
|
|
136
|
+
port: port
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return httpOverHttpsAgent;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
4
|
+
|
|
5
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
6
|
+
|
|
7
|
+
var through = require('through2');
|
|
8
|
+
var zlib = require('zlib');
|
|
9
|
+
var url = require('url');
|
|
10
|
+
|
|
11
|
+
var httpUtil = {};
|
|
12
|
+
httpUtil.isGzip = function (res) {
|
|
13
|
+
var contentEncoding = res.headers['content-encoding'];
|
|
14
|
+
return !!(contentEncoding && contentEncoding.toLowerCase() == 'gzip');
|
|
15
|
+
};
|
|
16
|
+
httpUtil.isHtml = function (res) {
|
|
17
|
+
var contentType = res.headers['content-type'];
|
|
18
|
+
return typeof contentType != 'undefined' && /text\/html|application\/xhtml\+xml/.test(contentType);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function injectContentIntoHtmlHead(html, content) {
|
|
22
|
+
html = html.replace(/(<\/head>)/i, function (match) {
|
|
23
|
+
return content + match;
|
|
24
|
+
});
|
|
25
|
+
return html;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function injectContentIntoHtmlBody(html, content) {
|
|
29
|
+
html = html.replace(/(<\/body>)/i, function (match) {
|
|
30
|
+
return content + match;
|
|
31
|
+
});
|
|
32
|
+
return html;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function chunkReplace(_this, chunk, enc, callback, headContent, bodyContent) {
|
|
36
|
+
var chunkString = chunk.toString();
|
|
37
|
+
if (headContent) {
|
|
38
|
+
chunkString = injectScriptIntoHtmlHead(chunkString, headContent);
|
|
39
|
+
}
|
|
40
|
+
if (bodyContent) {
|
|
41
|
+
chunkString = injectContentIntoHtmlBody(chunkString, bodyContent);
|
|
42
|
+
}
|
|
43
|
+
_this.push(new Buffer(chunkString));
|
|
44
|
+
callback();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = function () {
|
|
48
|
+
function InjectHtmlPlugin(_ref) {
|
|
49
|
+
var head = _ref.head,
|
|
50
|
+
body = _ref.body;
|
|
51
|
+
|
|
52
|
+
_classCallCheck(this, InjectHtmlPlugin);
|
|
53
|
+
|
|
54
|
+
this.head = head;
|
|
55
|
+
this.body = body;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_createClass(InjectHtmlPlugin, [{
|
|
59
|
+
key: 'responseInterceptor',
|
|
60
|
+
value: function responseInterceptor(req, res, proxyReq, proxyRes, ssl, next) {
|
|
61
|
+
|
|
62
|
+
if (!this.head && !this.body) {
|
|
63
|
+
next();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var isHtml = httpUtil.isHtml(proxyRes);
|
|
68
|
+
var contentLengthIsZero = function () {
|
|
69
|
+
return proxyRes.headers['content-length'] == 0;
|
|
70
|
+
}();
|
|
71
|
+
if (!isHtml || contentLengthIsZero) {
|
|
72
|
+
next();
|
|
73
|
+
} else {
|
|
74
|
+
Object.keys(proxyRes.headers).forEach(function (key) {
|
|
75
|
+
if (proxyRes.headers[key] != undefined) {
|
|
76
|
+
var newkey = key.replace(/^[a-z]|-[a-z]/g, function (match) {
|
|
77
|
+
return match.toUpperCase();
|
|
78
|
+
});
|
|
79
|
+
var newkey = key;
|
|
80
|
+
if (isHtml && key === 'content-length') {
|
|
81
|
+
// do nothing
|
|
82
|
+
} else {
|
|
83
|
+
res.setHeader(newkey, proxyRes.headers[key]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
res.writeHead(proxyRes.statusCode);
|
|
89
|
+
|
|
90
|
+
var isGzip = httpUtil.isGzip(proxyRes);
|
|
91
|
+
|
|
92
|
+
if (isGzip) {
|
|
93
|
+
proxyRes.pipe(new zlib.Gunzip()).pipe(through(function (chunk, enc, callback) {
|
|
94
|
+
chunkReplace(this, chunk, enc, callback, this.head, this.body);
|
|
95
|
+
})).pipe(new zlib.Gzip()).pipe(res);
|
|
96
|
+
} else {
|
|
97
|
+
proxyRes.pipe(through(function (chunk, enc, callback) {
|
|
98
|
+
chunkReplace(this, chunk, enc, callback, this.head, this.body);
|
|
99
|
+
})).pipe(res);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
next();
|
|
103
|
+
}
|
|
104
|
+
}]);
|
|
105
|
+
|
|
106
|
+
return InjectHtmlPlugin;
|
|
107
|
+
}();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var net = require('net');
|
|
4
|
+
var url = require('url');
|
|
5
|
+
var colors = require('colors');
|
|
6
|
+
|
|
7
|
+
var localIP = '127.0.0.1';
|
|
8
|
+
// create connectHandler function
|
|
9
|
+
module.exports = function createConnectHandler(sslConnectInterceptor, fakeServerCenter) {
|
|
10
|
+
|
|
11
|
+
// return
|
|
12
|
+
return function connectHandler(req, cltSocket, head) {
|
|
13
|
+
|
|
14
|
+
var srvUrl = url.parse('https://' + req.url);
|
|
15
|
+
|
|
16
|
+
if (typeof sslConnectInterceptor === 'function' && sslConnectInterceptor.call(null, req, cltSocket, head)) {
|
|
17
|
+
fakeServerCenter.getServerPromise(srvUrl.hostname, srvUrl.port).then(function (serverObj) {
|
|
18
|
+
connect(req, cltSocket, head, localIP, serverObj.port);
|
|
19
|
+
}, function (e) {
|
|
20
|
+
console.error(e);
|
|
21
|
+
});
|
|
22
|
+
} else {
|
|
23
|
+
connect(req, cltSocket, head, srvUrl.hostname, srvUrl.port);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function connect(req, cltSocket, head, hostname, port) {
|
|
29
|
+
// tunneling https
|
|
30
|
+
var proxySocket = net.connect(port, hostname, function () {
|
|
31
|
+
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' + 'Proxy-agent: node-mitmproxy\r\n' + '\r\n');
|
|
32
|
+
proxySocket.write(head);
|
|
33
|
+
proxySocket.pipe(cltSocket);
|
|
34
|
+
cltSocket.pipe(proxySocket);
|
|
35
|
+
});
|
|
36
|
+
proxySocket.on('error', function (e) {
|
|
37
|
+
console.log(colors.red(e));
|
|
38
|
+
});
|
|
39
|
+
return proxySocket;
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var config = require('../common/config');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var forge = require('node-forge');
|
|
7
|
+
var FakeServersCenter = require('../tls/FakeServersCenter');
|
|
8
|
+
var colors = require('colors');
|
|
9
|
+
|
|
10
|
+
module.exports = function createFakeServerCenter(_ref) {
|
|
11
|
+
var caCertPath = _ref.caCertPath,
|
|
12
|
+
caKeyPath = _ref.caKeyPath,
|
|
13
|
+
requestHandler = _ref.requestHandler,
|
|
14
|
+
upgradeHandler = _ref.upgradeHandler,
|
|
15
|
+
getCertSocketTimeout = _ref.getCertSocketTimeout;
|
|
16
|
+
|
|
17
|
+
var caCert;
|
|
18
|
+
var caKey;
|
|
19
|
+
try {
|
|
20
|
+
fs.accessSync(caCertPath, fs.F_OK);
|
|
21
|
+
fs.accessSync(caKeyPath, fs.F_OK);
|
|
22
|
+
var caCertPem = fs.readFileSync(caCertPath);
|
|
23
|
+
var caKeyPem = fs.readFileSync(caKeyPath);
|
|
24
|
+
caCert = forge.pki.certificateFromPem(caCertPem);
|
|
25
|
+
caKey = forge.pki.privateKeyFromPem(caKeyPem);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.log(colors.red('Can not find `CA certificate` or `CA key`.'), e);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return new FakeServersCenter({
|
|
32
|
+
caCert: caCert,
|
|
33
|
+
caKey: caKey,
|
|
34
|
+
maxLength: 100,
|
|
35
|
+
requestHandler: requestHandler,
|
|
36
|
+
upgradeHandler: upgradeHandler,
|
|
37
|
+
getCertSocketTimeout: getCertSocketTimeout
|
|
38
|
+
});
|
|
39
|
+
};
|