|
1 | 1 | import { MockConfig, RecordConfig, RequestInfo, SniffConfig } from './types'; |
2 | 2 | import { Proxy as HttpProxy, IContext, IProxyOptions } from 'http-mitm-proxy'; |
| 3 | +import * as net from 'net'; |
3 | 4 | import { ProxyAgent } from 'proxy-agent'; |
4 | 5 | import { v4 as uuid } from 'uuid'; |
5 | 6 | import { |
@@ -30,6 +31,8 @@ export interface ProxyOptions { |
30 | 31 | port: number; |
31 | 32 | ip: string; |
32 | 33 | previousConfig?: ProxyOptions; |
| 34 | + whitelistedDomains?: string[]; |
| 35 | + blacklistedDomains?: string[]; |
33 | 36 | } |
34 | 37 |
|
35 | 38 | export class Proxy { |
@@ -103,6 +106,56 @@ export class Proxy { |
103 | 106 | log.info('Routing traffic via proxy-chain upstream agent'); |
104 | 107 | } |
105 | 108 |
|
| 109 | + this.httpProxy.onConnect((req, clientToProxySocket, head, callback) => { |
| 110 | + const [hostname, port] = req.url!.split(':'); |
| 111 | + const whitelistedDomains = this.options.whitelistedDomains ?? []; |
| 112 | + const blacklistedDomains = this.options.blacklistedDomains ?? []; |
| 113 | + |
| 114 | + let shouldIntercept = true; |
| 115 | + if (whitelistedDomains.length > 0) { |
| 116 | + shouldIntercept = whitelistedDomains.some((domain) => doesUrlMatch(domain, hostname)); |
| 117 | + } else if (blacklistedDomains.length > 0) { |
| 118 | + shouldIntercept = !blacklistedDomains.some((domain) => doesUrlMatch(domain, hostname)); |
| 119 | + } |
| 120 | + if (shouldIntercept) { |
| 121 | + return callback(); |
| 122 | + } else { |
| 123 | + clientToProxySocket.on('error', (err) => { |
| 124 | + log.error(`Client socket error for ${hostname}: ${err.message}`); |
| 125 | + }); |
| 126 | + |
| 127 | + const proxyToServerSocket = net.connect( |
| 128 | + { |
| 129 | + host: hostname, |
| 130 | + port: Number(port || 80), |
| 131 | + }, |
| 132 | + () => { |
| 133 | + clientToProxySocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); |
| 134 | + if (head && head.length > 0) { |
| 135 | + proxyToServerSocket.write(head); |
| 136 | + } |
| 137 | + proxyToServerSocket.pipe(clientToProxySocket); |
| 138 | + clientToProxySocket.pipe(proxyToServerSocket); |
| 139 | + } |
| 140 | + ); |
| 141 | + |
| 142 | + proxyToServerSocket.on('close', () => { |
| 143 | + clientToProxySocket.end(); |
| 144 | + }); |
| 145 | + |
| 146 | + clientToProxySocket.on('close', () => { |
| 147 | + proxyToServerSocket.end(); |
| 148 | + }); |
| 149 | + |
| 150 | + proxyToServerSocket.on('error', (err) => { |
| 151 | + log.error(`[Tunnel] Server socket error for ${hostname}: ${err.message}`); |
| 152 | + clientToProxySocket.end(); |
| 153 | + }); |
| 154 | + |
| 155 | + return; |
| 156 | + } |
| 157 | + }); |
| 158 | + |
106 | 159 | this.httpProxy.onRequest( |
107 | 160 | RequestInterceptor((requestData: any) => { |
108 | 161 | for (const sniffer of this.sniffers.values()) { |
|
0 commit comments