davechri 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.

Potentially problematic release.


This version of davechri might be problematic. Click here for more details.

Files changed (113) hide show
  1. package/README.md +277 -0
  2. package/bin/proxyall +5 -0
  3. package/build/app.js +89 -0
  4. package/build/app.js.map +1 -0
  5. package/build/common/Message.js +34 -0
  6. package/build/common/Message.js.map +1 -0
  7. package/build/common/ProxyConfig.js +27 -0
  8. package/build/common/ProxyConfig.js.map +1 -0
  9. package/build/node-http-mitm-proxy/.gitattributes +2 -0
  10. package/build/node-http-mitm-proxy/.travis.yml +10 -0
  11. package/build/node-http-mitm-proxy/README.md +539 -0
  12. package/build/node-http-mitm-proxy/bin/mitm-proxy.js +36 -0
  13. package/build/node-http-mitm-proxy/examples/forwardHttps.js +62 -0
  14. package/build/node-http-mitm-proxy/examples/modifyGoogle.js +44 -0
  15. package/build/node-http-mitm-proxy/examples/onCertificateMissing.js +30 -0
  16. package/build/node-http-mitm-proxy/examples/onCertificateRequired.js +23 -0
  17. package/build/node-http-mitm-proxy/examples/preventRequest.js +20 -0
  18. package/build/node-http-mitm-proxy/examples/processFullResponseBody.js +36 -0
  19. package/build/node-http-mitm-proxy/examples/removeProxyToServerContentLength.js +17 -0
  20. package/build/node-http-mitm-proxy/examples/websocket.js +31 -0
  21. package/build/node-http-mitm-proxy/examples/wildcard.js +17 -0
  22. package/build/node-http-mitm-proxy/index.d.ts +233 -0
  23. package/build/node-http-mitm-proxy/index.js +3 -0
  24. package/build/node-http-mitm-proxy/lib/ca.js +245 -0
  25. package/build/node-http-mitm-proxy/lib/middleware/gunzip.js +19 -0
  26. package/build/node-http-mitm-proxy/lib/middleware/wildcard.js +22 -0
  27. package/build/node-http-mitm-proxy/lib/proxy.js +1137 -0
  28. package/build/node-http-mitm-proxy/package-lock.json +1406 -0
  29. package/build/node-http-mitm-proxy/package.json +45 -0
  30. package/build/node-http-mitm-proxy/test/01_proxy.js +449 -0
  31. package/build/node-http-mitm-proxy/test/www/1024.bin +64 -0
  32. package/build/node-http-mitm-proxy/test/wwwA/1024.bin +64 -0
  33. package/build/node-http-mitm-proxy/test/wwwA/example.com.html +8 -0
  34. package/build/node-http-mitm-proxy/test/wwwA/index.html +0 -0
  35. package/build/node-http-mitm-proxy/test/wwwB/1024.bin +64 -0
  36. package/build/node-http-mitm-proxy/test/wwwB/index.html +0 -0
  37. package/build/private/keys/README.md +2 -0
  38. package/build/private/keys/server.crt +20 -0
  39. package/build/private/keys/server.key +28 -0
  40. package/build/private/keys/ssl.conf +25 -0
  41. package/build/server/src/Global.js +38 -0
  42. package/build/server/src/Global.js.map +1 -0
  43. package/build/server/src/Http2Proxy.js +197 -0
  44. package/build/server/src/Http2Proxy.js.map +1 -0
  45. package/build/server/src/HttpMessage.js +99 -0
  46. package/build/server/src/HttpMessage.js.map +1 -0
  47. package/build/server/src/HttpProxy.js +196 -0
  48. package/build/server/src/HttpProxy.js.map +1 -0
  49. package/build/server/src/HttpsProxy.js +110 -0
  50. package/build/server/src/HttpsProxy.js.map +1 -0
  51. package/build/server/src/LogProxy.js +115 -0
  52. package/build/server/src/LogProxy.js.map +1 -0
  53. package/build/server/src/Paths.js +28 -0
  54. package/build/server/src/Paths.js.map +1 -0
  55. package/build/server/src/Ping.js +21 -0
  56. package/build/server/src/Ping.js.map +1 -0
  57. package/build/server/src/ProxyAllApp.js +70 -0
  58. package/build/server/src/ProxyAllApp.js.map +1 -0
  59. package/build/server/src/Resend.js +89 -0
  60. package/build/server/src/Resend.js.map +1 -0
  61. package/build/server/src/SocketIoManager.js +312 -0
  62. package/build/server/src/SocketIoManager.js.map +1 -0
  63. package/build/server/src/SocketMessage.js +68 -0
  64. package/build/server/src/SocketMessage.js.map +1 -0
  65. package/build/server/src/TcpProxy.js +202 -0
  66. package/build/server/src/TcpProxy.js.map +1 -0
  67. package/build/server/src/formatters/HexFormatter.js +33 -0
  68. package/build/server/src/formatters/HexFormatter.js.map +1 -0
  69. package/build/server/src/formatters/MongoFormatter.js +97 -0
  70. package/build/server/src/formatters/MongoFormatter.js.map +1 -0
  71. package/build/server/src/formatters/MongoOpCode.js +51 -0
  72. package/build/server/src/formatters/MongoOpCode.js.map +1 -0
  73. package/build/server/src/formatters/RedisFormatter.js +25 -0
  74. package/build/server/src/formatters/RedisFormatter.js.map +1 -0
  75. package/build/server/src/formatters/SqlCommand.js +111 -0
  76. package/build/server/src/formatters/SqlCommand.js.map +1 -0
  77. package/build/server/src/formatters/SqlFormatter.js +150 -0
  78. package/build/server/src/formatters/SqlFormatter.js.map +1 -0
  79. package/client/README.md +46 -0
  80. package/client/build/asset-manifest.json +26 -0
  81. package/client/build/favicon.ico +0 -0
  82. package/client/build/index.html +1 -0
  83. package/client/build/manifest.json +8 -0
  84. package/client/build/robots.txt +3 -0
  85. package/client/build/static/css/2.bbde182e.chunk.css +12 -0
  86. package/client/build/static/css/2.bbde182e.chunk.css.map +1 -0
  87. package/client/build/static/css/main.5bf489b2.chunk.css +2 -0
  88. package/client/build/static/css/main.5bf489b2.chunk.css.map +1 -0
  89. package/client/build/static/js/2.ba308ba1.chunk.js +3 -0
  90. package/client/build/static/js/2.ba308ba1.chunk.js.LICENSE.txt +100 -0
  91. package/client/build/static/js/2.ba308ba1.chunk.js.map +1 -0
  92. package/client/build/static/js/3.7073b0d8.chunk.js +2 -0
  93. package/client/build/static/js/3.7073b0d8.chunk.js.map +1 -0
  94. package/client/build/static/js/main.494a7501.chunk.js +2 -0
  95. package/client/build/static/js/main.494a7501.chunk.js.map +1 -0
  96. package/client/build/static/js/runtime-main.00264969.js +2 -0
  97. package/client/build/static/js/runtime-main.00264969.js.map +1 -0
  98. package/client/build/static/media/fa-brands-400.2285773e.woff +0 -0
  99. package/client/build/static/media/fa-brands-400.23f19bb0.eot +0 -0
  100. package/client/build/static/media/fa-brands-400.2f517e09.svg +3717 -0
  101. package/client/build/static/media/fa-brands-400.527940b1.ttf +0 -0
  102. package/client/build/static/media/fa-brands-400.d878b0a6.woff2 +0 -0
  103. package/client/build/static/media/fa-regular-400.4689f52c.svg +801 -0
  104. package/client/build/static/media/fa-regular-400.491974d1.ttf +0 -0
  105. package/client/build/static/media/fa-regular-400.77206a6b.eot +0 -0
  106. package/client/build/static/media/fa-regular-400.7a333762.woff2 +0 -0
  107. package/client/build/static/media/fa-regular-400.bb58e57c.woff +0 -0
  108. package/client/build/static/media/fa-solid-900.1551f4f6.woff2 +0 -0
  109. package/client/build/static/media/fa-solid-900.7a8b4f13.svg +5034 -0
  110. package/client/build/static/media/fa-solid-900.9bbb245e.eot +0 -0
  111. package/client/build/static/media/fa-solid-900.be9ee23c.ttf +0 -0
  112. package/client/build/static/media/fa-solid-900.eeccf4f6.woff +0 -0
  113. package/package.json +80 -0
@@ -0,0 +1,539 @@
1
+ # HTTP MITM Proxy
2
+
3
+ HTTP Man In The Middle (MITM) Proxy written in node.js. Supports capturing and modifying the request and response data.
4
+
5
+ [![](https://david-dm.org/joeferner/node-http-mitm-proxy.svg)](https://david-dm.org/joeferner/node-http-mitm-proxy)
6
+ [![Build Status](https://travis-ci.org/joeferner/node-http-mitm-proxy.svg?branch=master)](https://travis-ci.org/joeferner/node-http-mitm-proxy)
7
+
8
+
9
+ # Install
10
+
11
+ `npm install --save http-mitm-proxy`
12
+
13
+ ## Typescript
14
+ type definitions are now included in this project, no extra steps required.
15
+
16
+ # Example
17
+
18
+ This example will modify any search results coming from google and replace all the result titles with "Pwned!".
19
+
20
+ ```javascript
21
+ var Proxy = require('http-mitm-proxy');
22
+ var proxy = Proxy();
23
+
24
+ proxy.onError(function(ctx, err) {
25
+ console.error('proxy error:', err);
26
+ });
27
+
28
+ proxy.onRequest(function(ctx, callback) {
29
+ if (ctx.clientToProxyRequest.headers.host == 'www.google.com'
30
+ && ctx.clientToProxyRequest.url.indexOf('/search') == 0) {
31
+ ctx.use(Proxy.gunzip);
32
+
33
+ ctx.onResponseData(function(ctx, chunk, callback) {
34
+ chunk = new Buffer(chunk.toString().replace(/<h3.*?<\/h3>/g, '<h3>Pwned!</h3>'));
35
+ return callback(null, chunk);
36
+ });
37
+ }
38
+ return callback();
39
+ });
40
+
41
+ proxy.listen({port: 8081});
42
+ ```
43
+
44
+ You can find more examples in the [examples directory](https://github.com/joeferner/node-http-mitm-proxy/tree/master/examples)
45
+
46
+ # SSL
47
+
48
+ Using node-forge allows the automatic generation of SSL certificates within the proxy. After running your app you will find options.sslCaDir + '/certs/ca.pem' which can be imported to your browser, phone, etc.
49
+
50
+ # API
51
+
52
+ ## Proxy
53
+ * [listen(options)](#proxy_listen)
54
+ * [close](#proxy_close)
55
+ * [onError(fn)](#proxy_onError)
56
+ * [onCertificateRequired](#proxy_onCertificateRequired)
57
+ * [onCertificateMissing](#proxy_onCertificateMissing)
58
+ * [onRequest(fn)](#proxy_onRequest)
59
+ * [onRequestData(fn)](#proxy_onRequestData)
60
+ * [onRequestEnd(fn)](#proxy_onRequestEnd)
61
+ * [onResponse(fn)](#proxy_onResponse)
62
+ * [onResponseData(fn)](#proxy_onResponseData)
63
+ * [onResponseEnd(fn)](#proxy_onResponseEnd)
64
+ * [onWebSocketConnection(fn)](#proxy_onWebSocketConnection)
65
+ * [onWebSocketSend(fn)](#proxy_onWebSocketSend)
66
+ * [onWebSocketMessage(fn)](#proxy_onWebSocketMessage)
67
+ * [onWebSocketFrame(fn)](#proxy_onWebSocketFrame)
68
+ * [onWebSocketError(fn)](#proxy_onWebSocketError)
69
+ * [onWebSocketClose(fn)](#proxy_onWebSocketClose)
70
+ * [use(fn)](#proxy_use)
71
+
72
+ ## Context
73
+
74
+ Context functions only effect the current request/response. For example you may only want to gunzip requests
75
+ made to a particular host.
76
+
77
+ * isSSL: boolean,
78
+ * clientToProxyRequest: [IncomingMessage](https://nodejs.org/api/http.html#http_http_incomingmessage),
79
+ * proxyToClientResponse: [ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse),
80
+ * proxyToServerRequest: [ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest),
81
+ * serverToProxyResponse: [IncomingMessage](https://nodejs.org/api/http.html#http_http_incomingmessage),
82
+ * [onError(fn)](#proxy_onError)
83
+ * [onRequest(fn)](#proxy_onRequest)
84
+ * [onRequestData(fn)](#proxy_onRequestData)
85
+ * [onRequestEnd(fn)](#proxy_onRequestEnd)
86
+ * [addRequestFilter(fn)](#context_addRequestFilter)
87
+ * [onResponse(fn)](#proxy_onResponse)
88
+ * [onResponseData(fn)](#proxy_onResponseData)
89
+ * [onResponseEnd(fn)](#proxy_onResponseEnd)
90
+ * [addResponseFilter(fn)](#context_addResponseFilter)
91
+ * [use(mod)](#proxy_use)
92
+
93
+ ## WebSocket Context
94
+
95
+ The context available in websocket handlers is a bit different
96
+
97
+ * isSSL: boolean,
98
+ * clientToProxyWebSocket: [WebSocket](https://github.com/websockets/ws/blob/master/doc/ws.md#class-wswebsocket),
99
+ * proxyToServerWebSocket: [WebSocket](https://github.com/websockets/ws/blob/master/doc/ws.md#class-wswebsocket),
100
+ * [onWebSocketConnection(fn)](#proxy_onWebSocketConnection)
101
+ * [onWebSocketSend(fn)](#proxy_onWebSocketSend)
102
+ * [onWebSocketMessage(fn)](#proxy_onWebSocketMessage)
103
+ * [onWebSocketFrame(fn)](#proxy_onWebSocketFrame)
104
+ * [onWebSocketError(fn)](#proxy_onWebSocketError)
105
+ * [onWebSocketClose(fn)](#proxy_onWebSocketClose)
106
+ * [use(mod)](#proxy_use)
107
+
108
+ <a name="proxy"/>
109
+
110
+ ## Proxy
111
+
112
+ <a name="proxy_listen" />
113
+
114
+ ### proxy.listen
115
+
116
+ Starts the proxy listening on the given port.
117
+
118
+ __Arguments__
119
+
120
+ * options - An object with the following options:
121
+ * port - The port or named socket to listen on (default: 8080).
122
+ * host - The hostname or local address to listen on.
123
+ * sslCaDir - Path to the certificates cache directory (default: process.cwd() + '/.http-mitm-proxy')
124
+ * keepAlive - enable [HTTP persistent connection](https://en.wikipedia.org/wiki/HTTP_persistent_connection)
125
+ * timeout - The number of milliseconds of inactivity before a socket is presumed to have timed out. Defaults to no timeout.
126
+ * httpAgent - The [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) to use when making http requests. Useful for chaining proxys. (default: internal Agent)
127
+ * httpsAgent - The [https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) to use when making https requests. Useful for chaining proxys. (default: internal Agent)
128
+ * forceSNI - force use of [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) by the client. Allow node-http-mitm-proxy to handle all HTTPS requests with a single internal server.
129
+ * httpsPort - The port or named socket for https server to listen on. _(forceSNI must be enabled)_
130
+ * forceChunkedRequest - Setting this option will remove the content-length from the proxy to server request, forcing chunked encoding.
131
+
132
+ __Example__
133
+
134
+ proxy.listen({ port: 80 });
135
+
136
+ <a name="proxy_close" />
137
+
138
+ ### proxy.close
139
+
140
+ Stops the proxy listening.
141
+
142
+ __Example__
143
+
144
+ proxy.close();
145
+
146
+ <a name="proxy_onError" />
147
+
148
+ ### proxy.onError(fn) or ctx.onError(fn)
149
+
150
+ Adds a function to the list of functions to get called if an error occures.
151
+
152
+ __Arguments__
153
+
154
+ * fn(ctx, err, errorKind) - The function to be called on an error.
155
+
156
+ __Example__
157
+
158
+ proxy.onError(function(ctx, err, errorKind) {
159
+ // ctx may be null
160
+ var url = (ctx && ctx.clientToProxyRequest) ? ctx.clientToProxyRequest.url : "";
161
+ console.error(errorKind + ' on ' + url + ':', err);
162
+ });
163
+
164
+ <a name="proxy_onCertificateRequired" />
165
+
166
+ ### proxy.onCertificateRequired = function(hostname, callback)
167
+
168
+ Allows the default certificate name/path computation to be overwritten.
169
+
170
+ The default behavior expects `keys/{hostname}.pem` and `certs/{hostname}.pem` files to be at `self.sslCaDir`.
171
+
172
+ __Arguments__
173
+
174
+ * hostname - Requested hostname.
175
+ * callback - The function to be called when certificate files' path were already computed.
176
+
177
+ __Example 1__
178
+
179
+ proxy.onCertificateRequired = function(hostname, callback) {
180
+ return callback(null, {
181
+ keyFile: path.resolve('/ca/certs/', hostname + '.key'),
182
+ certFile: path.resolve('/ca/certs/', hostname + '.crt')
183
+ });
184
+ };
185
+
186
+ __Example 2: Wilcard certificates__
187
+
188
+ proxy.onCertificateRequired = function(hostname, callback) {
189
+ return callback(null, {
190
+ keyFile: path.resolve('/ca/certs/', hostname + '.key'),
191
+ certFile: path.resolve('/ca/certs/', hostname + '.crt'),
192
+ hosts: ["*.mydomain.com"]
193
+ });
194
+ };
195
+
196
+
197
+ <a name="proxy_onCertificateMissing" />
198
+
199
+ ### proxy.onCertificateMissing = function(ctx, files, callback)
200
+
201
+ Allows you to handle missing certificate files for current request, for example, creating them on the fly.
202
+
203
+ __Arguments__
204
+
205
+ * ctx - Context with the following properties
206
+ * hostname - The hostname which requires certificates
207
+ * data.keyFileExists - Whether key file exists or not
208
+ * data.certFileExists - Whether certificate file exists or not
209
+ * files - missing files names (`files.keyFile`, `files.certFile` and optional `files.hosts`)
210
+ * callback - The function to be called to pass certificate data back (`keyFileData` and `certFileData`)
211
+
212
+ __Example 1__
213
+
214
+ proxy.onCertificateMissing = function(ctx, files, callback) {
215
+ console.log('Looking for "%s" certificates', ctx.hostname);
216
+ console.log('"%s" missing', ctx.files.keyFile);
217
+ console.log('"%s" missing', ctx.files.certFile);
218
+
219
+ // Here you have the last chance to provide certificate files data
220
+ // A tipical use case would be creating them on the fly
221
+ //
222
+ // return callback(null, {
223
+ // keyFileData: keyFileData,
224
+ // certFileData: certFileData
225
+ // });
226
+ };
227
+
228
+ __Example 2: Wilcard certificates__
229
+
230
+ proxy.onCertificateMissing = function(ctx, files, callback) {
231
+ return callback(null, {
232
+ keyFileData: keyFileData,
233
+ certFileData: certFileData,
234
+ hosts: ["*.mydomain.com"]
235
+ });
236
+ };
237
+
238
+
239
+ <a name="proxy_onRequest" />
240
+
241
+ ### proxy.onRequest(fn) or ctx.onRequest(fn)
242
+
243
+ Adds a function to get called at the beginning of a request.
244
+
245
+ __Arguments__
246
+
247
+ * fn(ctx, callback) - The function that gets called on each request.
248
+
249
+ __Example__
250
+
251
+ proxy.onRequest(function(ctx, callback) {
252
+ console.log('REQUEST:', ctx.clientToProxyRequest.url);
253
+ return callback();
254
+ });
255
+
256
+ <a name="proxy_onRequestData" />
257
+
258
+ ### proxy.onRequestData(fn) or ctx.onRequestData(fn)
259
+
260
+ Adds a function to get called for each request data chunk (the body).
261
+
262
+ __Arguments__
263
+
264
+ * fn(ctx, chunk, callback) - The function that gets called for each data chunk.
265
+
266
+ __Example__
267
+
268
+ proxy.onRequestData(function(ctx, chunk, callback) {
269
+ console.log('REQUEST DATA:', chunk.toString());
270
+ return callback(null, chunk);
271
+ });
272
+
273
+ <a name="proxy_onRequestEnd" />
274
+
275
+ ### proxy.onRequestEnd(fn) or ctx.onRequestEnd(fn)
276
+
277
+ Adds a function to get called when all request data (the body) was sent.
278
+
279
+ __Arguments__
280
+
281
+ * fn(ctx, callback) - The function that gets called when all request data (the body) was sent.
282
+
283
+ __Example__
284
+
285
+ var chunks = [];
286
+
287
+ proxy.onRequestData(function(ctx, chunk, callback) {
288
+ chunks.push(chunk);
289
+ return callback(null, chunk);
290
+ });
291
+
292
+ proxy.onRequestEnd(function(ctx, callback) {
293
+ console.log('REQUEST END', (Buffer.concat(chunks)).toString());
294
+ return callback();
295
+ });
296
+
297
+ <a name="proxy_onResponse" />
298
+
299
+ ### proxy.onResponse(fn) or ctx.onResponse(fn)
300
+
301
+ Adds a function to get called at the beginning of the response.
302
+
303
+ __Arguments__
304
+
305
+ * fn(ctx, callback) - The function that gets called on each response.
306
+
307
+ __Example__
308
+
309
+ proxy.onResponse(function(ctx, callback) {
310
+ console.log('BEGIN RESPONSE');
311
+ return callback();
312
+ });
313
+
314
+ <a name="proxy_onResponseData" />
315
+
316
+ ### proxy.onResponseData(fn) or ctx.onResponseData(fn)
317
+
318
+ Adds a function to get called for each response data chunk (the body).
319
+
320
+ __Arguments__
321
+
322
+ * fn(ctx, chunk, callback) - The function that gets called for each data chunk.
323
+
324
+ __Example__
325
+
326
+ proxy.onResponseData(function(ctx, chunk, callback) {
327
+ console.log('RESPONSE DATA:', chunk.toString());
328
+ return callback(null, chunk);
329
+ });
330
+
331
+ <a name="proxy_onResponseEnd" />
332
+
333
+ ### proxy.onResponseEnd(fn) or ctx.onResponseEnd(fn)
334
+
335
+ Adds a function to get called when the proxy request to server has ended.
336
+
337
+ __Arguments__
338
+
339
+ * fn(ctx, callback) - The function that gets called when the proxy request to server as ended.
340
+
341
+ __Example__
342
+
343
+ proxy.onResponseEnd(function(ctx, callback) {
344
+ console.log('RESPONSE END');
345
+ return callback();
346
+ });
347
+
348
+ <a name="proxy_onWebSocketConnection" />
349
+
350
+ ### proxy.onWebSocketConnection(fn) or ctx.onWebSocketConnection(fn)
351
+
352
+ Adds a function to get called at the beginning of websocket connection
353
+
354
+ __Arguments__
355
+
356
+ * fn(ctx, callback) - The function that gets called for each data chunk.
357
+
358
+ __Example__
359
+
360
+ proxy.onWebSocketConnection(function(ctx, callback) {
361
+ console.log('WEBSOCKET CONNECT:', ctx.clientToProxyWebSocket.upgradeReq.url);
362
+ return callback();
363
+ });
364
+
365
+ <a name="proxy_onWebSocketSend" />
366
+
367
+ ### proxy.onWebSocketSend(fn) or ctx.onWebSocketSend(fn)
368
+
369
+ Adds a function to get called for each WebSocket message sent by the client.
370
+
371
+ __Arguments__
372
+
373
+ * fn(ctx, message, flags, callback) - The function that gets called for each WebSocket message sent by the client.
374
+
375
+ __Example__
376
+
377
+ proxy.onWebSocketSend(function(ctx, message, flags, callback) {
378
+ console.log('WEBSOCKET SEND:', ctx.clientToProxyWebSocket.upgradeReq.url, message);
379
+ return callback(null, message, flags);
380
+ });
381
+
382
+ <a name="proxy_onWebSocketMessage" />
383
+
384
+ ### proxy.onWebSocketMessage(fn) or ctx.onWebSocketMessage(fn)
385
+
386
+ Adds a function to get called for each WebSocket message received from the server.
387
+
388
+ __Arguments__
389
+
390
+ * fn(ctx, message, flags, callback) - The function that gets called for each WebSocket message received from the server.
391
+
392
+ __Example__
393
+
394
+ proxy.onWebSocketMessage(function(ctx, message, flags, callback) {
395
+ console.log('WEBSOCKET MESSAGE:', ctx.clientToProxyWebSocket.upgradeReq.url, message);
396
+ return callback(null, message, flags);
397
+ });
398
+
399
+ <a name="proxy_onWebSocketFrame" />
400
+
401
+ ### proxy.onWebSocketFrame(fn) or ctx.onWebSocketFrame(fn)
402
+
403
+ Adds a function to get called for each WebSocket frame exchanged (`message`, `ping` or `pong`).
404
+
405
+ __Arguments__
406
+
407
+ * fn(ctx, type, fromServer, data, flags, callback) - The function that gets called for each WebSocket frame exchanged.
408
+
409
+ __Example__
410
+
411
+ proxy.onWebSocketFrame(function(ctx, type, fromServer, data, flags, callback) {
412
+ console.log('WEBSOCKET FRAME ' + type + ' received from ' + (fromServer ? 'server' : 'client'), ctx.clientToProxyWebSocket.upgradeReq.url, data);
413
+ return callback(null, data, flags);
414
+ });
415
+
416
+ <a name="proxy_onWebSocketError" />
417
+
418
+ ### proxy.onWebSocketError(fn) or ctx.onWebSocketError(fn)
419
+
420
+ Adds a function to the list of functions to get called if an error occures in WebSocket.
421
+
422
+ __Arguments__
423
+
424
+ * fn(ctx, err) - The function to be called on an error in WebSocket.
425
+
426
+ __Example__
427
+
428
+ proxy.onWebSocketError(function(ctx, err) {
429
+ console.log('WEBSOCKET ERROR:', ctx.clientToProxyWebSocket.upgradeReq.url, err);
430
+ });
431
+
432
+ <a name="proxy_onWebSocketClose" />
433
+
434
+ ### proxy.onWebSocketClose(fn) or ctx.onWebSocketClose(fn)
435
+
436
+ Adds a function to get called when a WebSocket connection is closed
437
+
438
+ __Arguments__
439
+
440
+ * fn(ctx, code, message, callback) - The function that gets when a WebSocket is closed.
441
+
442
+ __Example__
443
+
444
+ proxy.onWebSocketClose(function(ctx, code, message, callback) {
445
+ console.log('WEBSOCKET CLOSED BY '+(ctx.closedByServer ? 'SERVER' : 'CLIENT'), ctx.clientToProxyWebSocket.upgradeReq.url, code, message);
446
+ callback(null, code, message);
447
+ });
448
+
449
+ <a name="proxy_use" />
450
+
451
+ ### proxy.use(module) or ctx.use(module)
452
+
453
+ Adds a module into the proxy. Modules encapsulate multiple life cycle processing functions into one object.
454
+
455
+ __Arguments__
456
+
457
+ * module - The module to add. Modules contain a hash of functions to add.
458
+
459
+ __Example__
460
+
461
+ proxy.use({
462
+ onError: function(ctx, err) { },
463
+ onCertificateRequired: function(hostname, callback) { return callback(); },
464
+ onCertificateMissing: function(ctx, files, callback) { return callback(); },
465
+ onRequest: function(ctx, callback) { return callback(); },
466
+ onRequestData: function(ctx, chunk, callback) { return callback(null, chunk); },
467
+ onResponse: function(ctx, callback) { return callback(); },
468
+ onResponseData: function(ctx, chunk, callback) { return callback(null, chunk); },
469
+ onWebSocketConnection: function(ctx, callback) { return callback(); },
470
+ onWebSocketSend: function(ctx, message, flags, callback) { return callback(null, message, flags); },
471
+ onWebSocketMessage: function(ctx, message, flags, callback) { return callback(null, message, flags); },
472
+ onWebSocketError: function(ctx, err) { },
473
+ onWebSocketClose: function(ctx, code, message, callback) { },
474
+ });
475
+
476
+ node-http-mitm-proxy provide some ready to use modules:
477
+ - `Proxy.gunzip` Gunzip response filter (uncompress gzipped content before onResponseData and compress back after)
478
+ - `Proxy.wildcard` Generates wilcard certificates by default (so less certificates are generated)
479
+
480
+ <a name="context"/>
481
+
482
+ ## Context
483
+
484
+ <a name="context_addRequestFilter" />
485
+
486
+ ### ctx.addRequestFilter(stream)
487
+
488
+ Adds a stream into the request body stream.
489
+
490
+ __Arguments__
491
+
492
+ * stream - The read/write stream to add in the request body stream.
493
+
494
+ __Example__
495
+
496
+ ctx.addRequestFilter(zlib.createGunzip());
497
+
498
+ <a name="context_addRequestFilter" />
499
+
500
+ ### ctx.addResponseFilter(stream)
501
+
502
+ Adds a stream into the response body stream.
503
+
504
+ __Arguments__
505
+
506
+ * stream - The read/write stream to add in the response body stream.
507
+
508
+ __Example__
509
+
510
+ ctx.addResponseFilter(zlib.createGunzip());
511
+
512
+ # License
513
+
514
+ ```
515
+ Copyright (c) 2015 Joe Ferner
516
+
517
+ Permission is hereby granted, free of charge, to any person obtaining a copy
518
+ of this software and associated documentation files (the "Software"), to deal
519
+ in the Software without restriction, including without limitation the rights
520
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
521
+ copies of the Software, and to permit persons to whom the Software is
522
+ furnished to do so, subject to the following conditions:
523
+
524
+
525
+
526
+ The above copyright notice and this permission notice shall be included in
527
+ all copies or substantial portions of the Software.
528
+
529
+
530
+
531
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
532
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
533
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
534
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
535
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
536
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
537
+ THE SOFTWARE.
538
+ ```
539
+
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ var yargs = require('yargs');
6
+ var debug = require('debug')('http-mitm-proxy:bin');
7
+
8
+ var args = yargs
9
+ .alias('h', 'help')
10
+ .alias('h', '?')
11
+ .options('port', {
12
+ default: 80,
13
+ describe: 'HTTP Port.'
14
+ })
15
+ .alias('p', 'port')
16
+ .options('host', {
17
+ describe: 'HTTP Listen Interface.'
18
+ })
19
+ .argv;
20
+
21
+ if (args.help) {
22
+ yargs.showHelp();
23
+ return process.exit(-1);
24
+ }
25
+
26
+ var proxy = require('../lib/proxy')();
27
+ proxy.onError(function(ctx, err, errorKind) {
28
+ debug(errorKind, err);
29
+ });
30
+ proxy.listen(args, function(err) {
31
+ if (err) {
32
+ debug('Failed to start listening on port ' + args.port, err);
33
+ return process.exit(1);
34
+ }
35
+ debug('proxy listening on ' + args.port);
36
+ });
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ var port = 8081;
4
+ var net = require('net');
5
+ var assert = require('assert');
6
+ var Proxy = require('../');
7
+ var proxy = Proxy();
8
+
9
+ proxy.onConnect(function(req, socket, head) {
10
+ var host = req.url.split(":")[0];
11
+ var port = req.url.split(":")[1];
12
+
13
+ console.log('Tunnel to', req.url);
14
+ var conn = net.connect({
15
+ port: port,
16
+ host: host,
17
+ allowHalfOpen: true
18
+ }, function(){
19
+ conn.on('finish', () => {
20
+ socket.destroy();
21
+ });
22
+ socket.on('close', () => {
23
+ conn.end();
24
+ });
25
+ socket.write('HTTP/1.1 200 OK\r\n\r\n', 'UTF-8', function(){
26
+ conn.pipe(socket);
27
+ socket.pipe(conn);
28
+ })
29
+ });
30
+
31
+ conn.on('error', function(err) {
32
+ filterSocketConnReset(err, 'PROXY_TO_SERVER_SOCKET');
33
+ });
34
+ socket.on('error', function(err) {
35
+ filterSocketConnReset(err, 'CLIENT_TO_PROXY_SOCKET');
36
+ });
37
+ });
38
+
39
+ // Since node 0.9.9, ECONNRESET on sockets are no longer hidden
40
+ function filterSocketConnReset(err, socketDescription) {
41
+ if (err.errno === 'ECONNRESET') {
42
+ console.log('Got ECONNRESET on ' + socketDescription + ', ignoring.');
43
+ } else {
44
+ console.log('Got unexpected error on ' + socketDescription, err);
45
+ }
46
+ }
47
+
48
+ proxy.listen({ port }, function() {
49
+ console.log('Proxy server listening on ' + port);
50
+
51
+ var cmd = `curl -x http://localhost:${port} https://github.com/ | grep html`;
52
+ console.log('> ' + cmd);
53
+ require('child_process').exec(cmd, function (error, stdout, stderr) {
54
+ if (error) {
55
+ Global.error(`exec error: ${error}`);
56
+ return;
57
+ }
58
+ Global.log(`${stdout}`);
59
+ assert(/DOCTYPE/.test(stdout));
60
+ proxy.close();
61
+ });
62
+ });
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ var port = 8081;
4
+
5
+ var Proxy = require('../');
6
+ var proxy = Proxy();
7
+
8
+ proxy.onError(function(ctx, err, errorKind) {
9
+ // ctx may be null
10
+ var url = (ctx && ctx.clientToProxyRequest) ? ctx.clientToProxyRequest.url : '';
11
+ console.error(errorKind + ' on ' + url + ':', err);
12
+ });
13
+
14
+ proxy.onRequest(function(ctx, callback) {
15
+ //console.log('REQUEST: http://' + ctx.clientToProxyRequest.headers.host + ctx.clientToProxyRequest.url);
16
+ if (ctx.clientToProxyRequest.headers.host == 'www.google.com'
17
+ && ctx.clientToProxyRequest.url.indexOf('/search') == 0) {
18
+ ctx.use(Proxy.gunzip);
19
+
20
+ ctx.onResponseData(function(ctx, chunk, callback) {
21
+ chunk = new Buffer(chunk.toString().replace(/<h3.*?<\/h3>/g, '<h3>Pwned!</h3>'));
22
+ return callback(null, chunk);
23
+ });
24
+ }
25
+ return callback();
26
+ });
27
+
28
+ proxy.onRequestData(function(ctx, chunk, callback) {
29
+ //console.log('request data length: ' + chunk.length);
30
+ return callback(null, chunk);
31
+ });
32
+
33
+ proxy.onResponse(function(ctx, callback) {
34
+ //console.log('RESPONSE: http://' + ctx.clientToProxyRequest.headers.host + ctx.clientToProxyRequest.url);
35
+ return callback(null);
36
+ });
37
+
38
+ proxy.onResponseData(function(ctx, chunk, callback) {
39
+ //console.log('response data length: ' + chunk.length);
40
+ return callback(null, chunk);
41
+ });
42
+
43
+ proxy.listen({ port: port });
44
+ console.log('listening on ' + port);