green-tunnel 2.0.1 → 3.0.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.
- package/dist/core/config.d.ts +13 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +87 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/dns/decode.d.ts +12 -0
- package/dist/core/dns/decode.d.ts.map +1 -0
- package/dist/core/dns/decode.js +23 -0
- package/dist/core/dns/decode.js.map +1 -0
- package/dist/core/dns/doh.d.ts +19 -0
- package/dist/core/dns/doh.d.ts.map +1 -0
- package/dist/core/dns/doh.js +54 -0
- package/dist/core/dns/doh.js.map +1 -0
- package/dist/core/dns/dot.d.ts +13 -0
- package/dist/core/dns/dot.d.ts.map +1 -0
- package/dist/core/dns/dot.js +79 -0
- package/dist/core/dns/dot.js.map +1 -0
- package/dist/core/dns/index.d.ts +8 -0
- package/dist/core/dns/index.d.ts.map +1 -0
- package/dist/core/dns/index.js +18 -0
- package/dist/core/dns/index.js.map +1 -0
- package/dist/core/dns/plain.d.ts +17 -0
- package/dist/core/dns/plain.d.ts.map +1 -0
- package/dist/core/dns/plain.js +45 -0
- package/dist/core/dns/plain.js.map +1 -0
- package/dist/core/dns/resolver.d.ts +27 -0
- package/dist/core/dns/resolver.d.ts.map +1 -0
- package/dist/core/dns/resolver.js +81 -0
- package/dist/core/dns/resolver.js.map +1 -0
- package/dist/core/errors.d.ts +32 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +37 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/http/head.d.ts +40 -0
- package/dist/core/http/head.d.ts.map +1 -0
- package/dist/core/http/head.js +122 -0
- package/dist/core/http/head.js.map +1 -0
- package/dist/core/http/rewriter.d.ts +20 -0
- package/dist/core/http/rewriter.d.ts.map +1 -0
- package/dist/core/http/rewriter.js +184 -0
- package/dist/core/http/rewriter.js.map +1 -0
- package/dist/core/index.d.ts +28 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +27 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +38 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +92 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/net/socket.d.ts +30 -0
- package/dist/core/net/socket.d.ts.map +1 -0
- package/dist/core/net/socket.js +98 -0
- package/dist/core/net/socket.js.map +1 -0
- package/dist/core/proxy/connect-tunnel.d.ts +14 -0
- package/dist/core/proxy/connect-tunnel.d.ts.map +1 -0
- package/dist/core/proxy/connect-tunnel.js +44 -0
- package/dist/core/proxy/connect-tunnel.js.map +1 -0
- package/dist/core/proxy/connection.d.ts +12 -0
- package/dist/core/proxy/connection.d.ts.map +1 -0
- package/dist/core/proxy/connection.js +88 -0
- package/dist/core/proxy/connection.js.map +1 -0
- package/dist/core/proxy/context.d.ts +15 -0
- package/dist/core/proxy/context.d.ts.map +1 -0
- package/dist/core/proxy/context.js +2 -0
- package/dist/core/proxy/context.js.map +1 -0
- package/dist/core/proxy/index.d.ts +33 -0
- package/dist/core/proxy/index.d.ts.map +1 -0
- package/dist/core/proxy/index.js +162 -0
- package/dist/core/proxy/index.js.map +1 -0
- package/dist/core/proxy/pipe.d.ts +12 -0
- package/dist/core/proxy/pipe.d.ts.map +1 -0
- package/dist/core/proxy/pipe.js +42 -0
- package/dist/core/proxy/pipe.js.map +1 -0
- package/dist/core/proxy/plain-tunnel.d.ts +12 -0
- package/dist/core/proxy/plain-tunnel.d.ts.map +1 -0
- package/dist/core/proxy/plain-tunnel.js +29 -0
- package/dist/core/proxy/plain-tunnel.js.map +1 -0
- package/dist/core/system-proxy/darwin.d.ts +32 -0
- package/dist/core/system-proxy/darwin.d.ts.map +1 -0
- package/dist/core/system-proxy/darwin.js +146 -0
- package/dist/core/system-proxy/darwin.js.map +1 -0
- package/dist/core/system-proxy/driver.d.ts +21 -0
- package/dist/core/system-proxy/driver.d.ts.map +1 -0
- package/dist/core/system-proxy/driver.js +2 -0
- package/dist/core/system-proxy/driver.js.map +1 -0
- package/dist/core/system-proxy/exec.d.ts +21 -0
- package/dist/core/system-proxy/exec.d.ts.map +1 -0
- package/dist/core/system-proxy/exec.js +62 -0
- package/dist/core/system-proxy/exec.js.map +1 -0
- package/dist/core/system-proxy/index.d.ts +45 -0
- package/dist/core/system-proxy/index.d.ts.map +1 -0
- package/dist/core/system-proxy/index.js +151 -0
- package/dist/core/system-proxy/index.js.map +1 -0
- package/dist/core/system-proxy/linux.d.ts +18 -0
- package/dist/core/system-proxy/linux.d.ts.map +1 -0
- package/dist/core/system-proxy/linux.js +100 -0
- package/dist/core/system-proxy/linux.js.map +1 -0
- package/dist/core/system-proxy/recovery.d.ts +23 -0
- package/dist/core/system-proxy/recovery.d.ts.map +1 -0
- package/dist/core/system-proxy/recovery.js +147 -0
- package/dist/core/system-proxy/recovery.js.map +1 -0
- package/dist/core/system-proxy/windows.d.ts +15 -0
- package/dist/core/system-proxy/windows.d.ts.map +1 -0
- package/dist/core/system-proxy/windows.js +96 -0
- package/dist/core/system-proxy/windows.js.map +1 -0
- package/dist/core/tls/fragment.d.ts +28 -0
- package/dist/core/tls/fragment.d.ts.map +1 -0
- package/dist/core/tls/fragment.js +81 -0
- package/dist/core/tls/fragment.js.map +1 -0
- package/dist/core/types.d.ts +138 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +7 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +155 -0
- package/dist/main.js.map +1 -0
- package/dist/options.d.ts +25 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +144 -0
- package/dist/options.js.map +1 -0
- package/dist/ui.d.ts +17 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +89 -0
- package/dist/ui.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/package.json +31 -30
- package/LICENSE +0 -21
- package/README.md +0 -168
- package/bin/gt.js +0 -170
- package/src/config.js +0 -15
- package/src/dns/base.js +0 -47
- package/src/dns/https.js +0 -30
- package/src/dns/tls.js +0 -15
- package/src/dns/unencrypted.js +0 -25
- package/src/handlers/http.js +0 -65
- package/src/handlers/https.js +0 -78
- package/src/handlers/request.js +0 -32
- package/src/http/request.js +0 -45
- package/src/http/response.js +0 -45
- package/src/http/utils.js +0 -86
- package/src/index.cjs +0 -7
- package/src/index.js +0 -4
- package/src/logger.js +0 -11
- package/src/proxy.js +0 -74
- package/src/scripts/windows/wininet-reset-settings.ps1 +0 -14
- package/src/utils/analytics.js +0 -59
- package/src/utils/buffer.js +0 -35
- package/src/utils/socket.js +0 -32
- package/src/utils/system-proxy.js +0 -153
package/src/dns/tls.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import dnstls from 'dns-over-tls';
|
|
2
|
-
import BaseDNS from './base.js';
|
|
3
|
-
|
|
4
|
-
export default class DNSOverTLS extends BaseDNS {
|
|
5
|
-
async _lookup(hostname) {
|
|
6
|
-
const {answers} = await dnstls.query(hostname);
|
|
7
|
-
|
|
8
|
-
const answer = answers.find(answer => answer.type === 'A' && answer.class === 'IN');
|
|
9
|
-
|
|
10
|
-
if (answer) {
|
|
11
|
-
return answer.data;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
package/src/dns/unencrypted.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import dnsSocket from 'dns-socket';
|
|
2
|
-
import BaseDNS from './base.js';
|
|
3
|
-
|
|
4
|
-
const socket = dnsSocket()
|
|
5
|
-
|
|
6
|
-
export default class DNSUnencrypted extends BaseDNS {
|
|
7
|
-
constructor(dnsIp, dnsPort) {
|
|
8
|
-
super();
|
|
9
|
-
this.dnsIp = dnsIp;
|
|
10
|
-
this.dnsPort = dnsPort;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
_lookup(hostname) {
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
socket.query({
|
|
16
|
-
questions: [{
|
|
17
|
-
type: 'A',
|
|
18
|
-
name: hostname
|
|
19
|
-
}]
|
|
20
|
-
}, this.dnsPort, this.dnsIp, (err, res, query) => {
|
|
21
|
-
resolve(res.answers[0].data);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
package/src/handlers/http.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import {URL} from 'url';
|
|
2
|
-
import {isStartOfHTTPRequest} from '../http/utils.js';
|
|
3
|
-
import {createConnection, closeSocket, tryWrite} from '../utils/socket.js';
|
|
4
|
-
import HTTPRequest from '../http/request.js';
|
|
5
|
-
import getLogger from '../logger.js';
|
|
6
|
-
|
|
7
|
-
const logger = getLogger('https-handler');
|
|
8
|
-
|
|
9
|
-
export default async function handleHTTP(clientSocket, firstChunk, proxy) {
|
|
10
|
-
const firstLine = firstChunk.toString().split('\r\n')[0];
|
|
11
|
-
const url = new URL(firstLine.split(/\s+/)[1]);
|
|
12
|
-
|
|
13
|
-
const host = url.hostname;
|
|
14
|
-
const port = url.port || 80;
|
|
15
|
-
|
|
16
|
-
logger.debug(`[HTTP REQUEST] ${url.host}`);
|
|
17
|
-
|
|
18
|
-
// -- ServerSocket --
|
|
19
|
-
|
|
20
|
-
const serverSocket = await createConnection({host, port}, proxy.dns);
|
|
21
|
-
|
|
22
|
-
const close = () => {
|
|
23
|
-
closeSocket(clientSocket);
|
|
24
|
-
closeSocket(serverSocket);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
tryWrite(serverSocket, interceptRequest(firstChunk), close);
|
|
28
|
-
|
|
29
|
-
serverSocket.on('data', data => {
|
|
30
|
-
tryWrite(clientSocket, data, close);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
serverSocket.on('error', error => {
|
|
34
|
-
close(error);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
serverSocket.on('end', () => {
|
|
38
|
-
close();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// -- clientSocket --
|
|
42
|
-
|
|
43
|
-
clientSocket.on('data', data => {
|
|
44
|
-
tryWrite(serverSocket, interceptRequest(data), close);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
clientSocket.on('end', () => {
|
|
48
|
-
close();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
clientSocket.resume();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function interceptRequest(data) {
|
|
55
|
-
const strData = data.toString();
|
|
56
|
-
|
|
57
|
-
if (isStartOfHTTPRequest(strData)) {
|
|
58
|
-
const request = new HTTPRequest(strData);
|
|
59
|
-
request.path = new URL(request.path).pathname;
|
|
60
|
-
delete request.headers['Proxy-Connection'];
|
|
61
|
-
return request.toString();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return data;
|
|
65
|
-
}
|
package/src/handlers/https.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import {URL} from 'url';
|
|
2
|
-
import {bufferToChunks} from '../utils/buffer.js';
|
|
3
|
-
import {createConnection, closeSocket, tryWrite} from '../utils/socket.js';
|
|
4
|
-
import HTTPResponse from '../http/response.js';
|
|
5
|
-
import getLogger from '../logger.js';
|
|
6
|
-
|
|
7
|
-
const logger = getLogger('https-handler');
|
|
8
|
-
|
|
9
|
-
export default async function handleHTTPS(clientSocket, firstChunk, proxy) {
|
|
10
|
-
const firstLine = firstChunk.toString().split('\r\n')[0];
|
|
11
|
-
const requestUrl = `https://${firstLine.split(/\s+/)[1]}`;
|
|
12
|
-
const url = new URL(requestUrl);
|
|
13
|
-
|
|
14
|
-
const host = url.hostname;
|
|
15
|
-
const port = url.port || 443;
|
|
16
|
-
|
|
17
|
-
logger.debug(`[HTTPS REQUEST] ${url.host}`);
|
|
18
|
-
|
|
19
|
-
// -- ServerSocket --
|
|
20
|
-
|
|
21
|
-
const serverSocket = await createConnection({host, port}, proxy.dns);
|
|
22
|
-
|
|
23
|
-
const close = () => {
|
|
24
|
-
closeSocket(clientSocket);
|
|
25
|
-
closeSocket(serverSocket);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
serverSocket.on('data', data => {
|
|
29
|
-
logger.debug(`[HTTPS] receive from ${url.host} (length: ${data.length})`);
|
|
30
|
-
tryWrite(clientSocket, data, close);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
serverSocket.on('end', () => {
|
|
34
|
-
logger.debug(`[HTTPS END] server ended ${url.host}`);
|
|
35
|
-
close();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
serverSocket.on('error', error => {
|
|
39
|
-
logger.debug(`[HTTPS ERROR] server error ${error}`);
|
|
40
|
-
close(error);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// -- clientSocket --
|
|
44
|
-
|
|
45
|
-
clientSocket.once('data', clientHello => {
|
|
46
|
-
const chunks = bufferToChunks(clientHello, proxy.config.clientHelloMTU, proxy.config.tlsRecordFragmentation);
|
|
47
|
-
for (const chunk of chunks) {
|
|
48
|
-
logger.debug(`[HTTPS HELLO] ${url.host} (length: ${chunk.length})`);
|
|
49
|
-
tryWrite(serverSocket, chunk, close);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
clientSocket.on('data', data => {
|
|
53
|
-
logger.debug(`[HTTPS] send to ${url.host} (length: ${data.length})`);
|
|
54
|
-
tryWrite(serverSocket, data, close);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
clientSocket.on('end', () => {
|
|
59
|
-
logger.debug(`[HTTPS END] client ended ${url.host}`);
|
|
60
|
-
close();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
clientSocket.on('error', error => {
|
|
64
|
-
logger.debug(`[HTTPS ERROR] client error ${error}`);
|
|
65
|
-
close(error);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
tryWrite(clientSocket, getConnectionEstablishedPacket(), close);
|
|
69
|
-
clientSocket.resume();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function getConnectionEstablishedPacket() {
|
|
73
|
-
const packet = new HTTPResponse();
|
|
74
|
-
packet.statusCode = 200;
|
|
75
|
-
packet.statusMessgae = 'Connection Established';
|
|
76
|
-
return packet.toString();
|
|
77
|
-
}
|
|
78
|
-
|
package/src/handlers/request.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {isStartOfHTTPRequest, isConnectMethod} from '../http/utils.js';
|
|
2
|
-
import handleHTTP from './http.js';
|
|
3
|
-
import handleHTTPS from './https.js';
|
|
4
|
-
|
|
5
|
-
export default async function handleRequest(clientSocket, proxy) {
|
|
6
|
-
clientSocket.resume();
|
|
7
|
-
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
clientSocket.once('data', async data => {
|
|
10
|
-
try {
|
|
11
|
-
clientSocket.pause();
|
|
12
|
-
const strData = data.toString();
|
|
13
|
-
|
|
14
|
-
if (isStartOfHTTPRequest(strData)) {
|
|
15
|
-
if (isConnectMethod(strData)) {
|
|
16
|
-
await handleHTTPS(clientSocket, data, proxy);
|
|
17
|
-
} else if (proxy.config.httpsOnly) {
|
|
18
|
-
throw new Error('Insecure request blocked: ', strData);
|
|
19
|
-
} else {
|
|
20
|
-
await handleHTTP(clientSocket, data, proxy);
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
throw new Error('Unsupported request: ', strData);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
resolve();
|
|
27
|
-
} catch (error) {
|
|
28
|
-
reject(error);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
}
|
package/src/http/request.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {parseRequest} from './utils.js';
|
|
2
|
-
|
|
3
|
-
export default class HTTPRequest {
|
|
4
|
-
constructor(rawReq) {
|
|
5
|
-
if (rawReq) {
|
|
6
|
-
const packet = this._parseRequest(rawReq);
|
|
7
|
-
this.method = packet.method;
|
|
8
|
-
this.path = packet.path;
|
|
9
|
-
this.httpVersion = packet.httpVersion;
|
|
10
|
-
this.headers = packet.headers;
|
|
11
|
-
this.payload = packet.payload;
|
|
12
|
-
} else {
|
|
13
|
-
this.method = 'GET';
|
|
14
|
-
this.path = '/';
|
|
15
|
-
this.httpVersion = 'HTTP/1.1';
|
|
16
|
-
this.headers = {};
|
|
17
|
-
this.payload = '';
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
_parseRequest(rawReq) {
|
|
22
|
-
const {firstLineParts, ...request} = parseRequest(rawReq);
|
|
23
|
-
|
|
24
|
-
request.method = firstLineParts[0];
|
|
25
|
-
request.path = firstLineParts[1];
|
|
26
|
-
request.httpVersion = firstLineParts[2];
|
|
27
|
-
|
|
28
|
-
return request;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
toString() {
|
|
32
|
-
let result = '';
|
|
33
|
-
|
|
34
|
-
result += `${this.method} ${this.path} ${this.httpVersion}\r\n`;
|
|
35
|
-
|
|
36
|
-
for (const header in this.headers) {
|
|
37
|
-
result += `${header}: ${this.headers[header]}\r\n`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
result += '\r\n';
|
|
41
|
-
result += this.payload;
|
|
42
|
-
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/http/response.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {parseRequest} from './utils.js';
|
|
2
|
-
|
|
3
|
-
export default class HTTPResponse {
|
|
4
|
-
constructor(rawReq) {
|
|
5
|
-
if (rawReq) {
|
|
6
|
-
const packet = this._parseRequest(rawReq);
|
|
7
|
-
this.httpVersion = packet.httpVersion;
|
|
8
|
-
this.statusCode = packet.statusCode;
|
|
9
|
-
this.statusMessgae = packet.statusMessgae;
|
|
10
|
-
this.headers = packet.headers;
|
|
11
|
-
this.payload = packet.payload;
|
|
12
|
-
} else {
|
|
13
|
-
this.httpVersion = 'HTTP/1.1';
|
|
14
|
-
this.statusCode = 200;
|
|
15
|
-
this.statusMessgae = 'OK';
|
|
16
|
-
this.headers = {};
|
|
17
|
-
this.payload = '';
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
_parseResponse(rawRes) {
|
|
22
|
-
const {firstLineParts, ...request} = parseRequest(rawRes);
|
|
23
|
-
|
|
24
|
-
request.httpVersion = firstLineParts[0];
|
|
25
|
-
request.statusCode = firstLineParts[1];
|
|
26
|
-
request.statusMessgae = firstLineParts[2];
|
|
27
|
-
|
|
28
|
-
return request;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
toString() {
|
|
32
|
-
let result = '';
|
|
33
|
-
|
|
34
|
-
result += `${this.httpVersion} ${this.statusCode} ${this.statusMessgae}\r\n`;
|
|
35
|
-
|
|
36
|
-
for (const header in this.headers) {
|
|
37
|
-
result += `${header}: ${this.headers[header]}\r\n`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
result += '\r\n';
|
|
41
|
-
result += this.payload;
|
|
42
|
-
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/http/utils.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
export function parseRequest(rawRequest) {
|
|
2
|
-
const mainParts = rawRequest.split('\r\n\r\n');
|
|
3
|
-
const headersPart = mainParts[0];
|
|
4
|
-
const payload = mainParts[1];
|
|
5
|
-
|
|
6
|
-
const headerLines = headersPart.split('\r\n');
|
|
7
|
-
const firsLine = headerLines.shift();
|
|
8
|
-
|
|
9
|
-
const firstLineParts = firsLine.split(/\s+/);
|
|
10
|
-
const headers = parseHeaders(headerLines);
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
firstLineParts,
|
|
14
|
-
headers,
|
|
15
|
-
payload
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function parseHeaders(headerLines) {
|
|
20
|
-
const headers = {};
|
|
21
|
-
|
|
22
|
-
for (const line of headerLines) {
|
|
23
|
-
const [name, value] = line.split(/ *: */);
|
|
24
|
-
headers[name] = value;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return headers;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function isConnectMethod(rawInput) {
|
|
31
|
-
const firstWord = rawInput.split(/\s+/)[0];
|
|
32
|
-
return firstWord.toUpperCase() === 'CONNECT';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function isStartOfHTTPRequest(rawRequest) {
|
|
36
|
-
// Valid methods (for http request)
|
|
37
|
-
const firstWord = rawRequest.split(/\s+/)[0];
|
|
38
|
-
if (validMethods.includes(firstWord.toUpperCase())) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Like HTTP/1.1 (For http response)
|
|
43
|
-
const httpWord = firstWord.split('/')[0];
|
|
44
|
-
if (httpWord.toLowerCase() === 'http') {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const validMethods = [
|
|
52
|
-
'DELETE',
|
|
53
|
-
'GET',
|
|
54
|
-
'HEAD',
|
|
55
|
-
'POST',
|
|
56
|
-
'PUT',
|
|
57
|
-
'CONNECT',
|
|
58
|
-
'OPTIONS',
|
|
59
|
-
'TRACE',
|
|
60
|
-
'COPY',
|
|
61
|
-
'LOCK',
|
|
62
|
-
'MKCOL',
|
|
63
|
-
'MOVE',
|
|
64
|
-
'PROPFIND',
|
|
65
|
-
'PROPPATCH',
|
|
66
|
-
'SEARCH',
|
|
67
|
-
'UNLOCK',
|
|
68
|
-
'BIND',
|
|
69
|
-
'REBIND',
|
|
70
|
-
'UNBIND',
|
|
71
|
-
'ACL',
|
|
72
|
-
'REPORT',
|
|
73
|
-
'MKACTIVITY',
|
|
74
|
-
'CHECKOUT',
|
|
75
|
-
'MERGE',
|
|
76
|
-
'M-SEARCH',
|
|
77
|
-
'NOTIFY',
|
|
78
|
-
'SUBSCRIBE',
|
|
79
|
-
'UNSUBSCRIBE',
|
|
80
|
-
'PATCH',
|
|
81
|
-
'PURGE',
|
|
82
|
-
'MKCALENDAR',
|
|
83
|
-
'LINK',
|
|
84
|
-
'UNLINK'
|
|
85
|
-
];
|
|
86
|
-
|
package/src/index.cjs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
// CJS interop shim — green-tunnel is now an ES module.
|
|
3
|
-
// CommonJS callers must use dynamic import:
|
|
4
|
-
// const gt = await import('green-tunnel');
|
|
5
|
-
throw new Error(
|
|
6
|
-
'green-tunnel is an ES module. Use `import` (or dynamic `await import(\'green-tunnel\')`) instead of `require()`.'
|
|
7
|
-
);
|
package/src/index.js
DELETED
package/src/logger.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import debug from 'debug';
|
|
2
|
-
|
|
3
|
-
export default function getLogger(name) {
|
|
4
|
-
return {
|
|
5
|
-
debug: debug(`green-tunnel:${name}`),
|
|
6
|
-
success: debug(`green-tunnel:${name}:success`),
|
|
7
|
-
error: debug(`green-tunnel:${name}:error`),
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
debug.enable('green-tunnel:proxy:error');
|
package/src/proxy.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import net from 'net';
|
|
2
|
-
import { setProxy, unsetProxy } from './utils/system-proxy.js';
|
|
3
|
-
import handleRequest from './handlers/request.js';
|
|
4
|
-
import DNSOverTLS from './dns/tls.js';
|
|
5
|
-
import DNSOverHTTPS from './dns/https.js';
|
|
6
|
-
import DNSUnencrypted from './dns/unencrypted.js';
|
|
7
|
-
import config from './config.js';
|
|
8
|
-
import getLogger from './logger.js';
|
|
9
|
-
import { appInit } from './utils/analytics.js';
|
|
10
|
-
|
|
11
|
-
const logger = getLogger('proxy');
|
|
12
|
-
|
|
13
|
-
export default class Proxy {
|
|
14
|
-
constructor(customConfig) {
|
|
15
|
-
this.config = { ...config, ...customConfig };
|
|
16
|
-
this.server = undefined;
|
|
17
|
-
this.isSystemProxySet = false;
|
|
18
|
-
this.initDNS();
|
|
19
|
-
appInit(customConfig.source);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
initDNS() {
|
|
23
|
-
if (this.config.dns.type === 'https') {
|
|
24
|
-
this.dns = new DNSOverHTTPS(this.config.dns.server);
|
|
25
|
-
} else if (this.config.dns.type === 'tls') {
|
|
26
|
-
this.dns = new DNSOverTLS(this.config.dns.server);
|
|
27
|
-
} else {
|
|
28
|
-
this.dns = new DNSUnencrypted(this.config.dns.ip, this.config.dns.port);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async start(options = {}) {
|
|
33
|
-
options.setProxy = options.setProxy === undefined ? false : options.setProxy;
|
|
34
|
-
|
|
35
|
-
this.server = net.createServer({ pauseOnConnect: true }, clientSocket => {
|
|
36
|
-
handleRequest(clientSocket, this).catch(err => {
|
|
37
|
-
logger.debug(String(err));
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
this.server.on('error', err => {
|
|
42
|
-
logger.error(err.toString());
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
this.server.on('close', () => {
|
|
46
|
-
logger.debug('server closed');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
await new Promise(resolve => {
|
|
50
|
-
this.server.listen(this.config.port, this.config.ip, () => resolve());
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const { address, port } = this.server.address();
|
|
54
|
-
logger.debug(`server listen on ${address} port ${port}`);
|
|
55
|
-
|
|
56
|
-
if (options.setProxy) {
|
|
57
|
-
await setProxy(address, port);
|
|
58
|
-
this.isSystemProxySet = true;
|
|
59
|
-
logger.debug('system proxy set');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async stop() {
|
|
64
|
-
if (this.server) {
|
|
65
|
-
this.server.close();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (this.isSystemProxySet) {
|
|
69
|
-
await unsetProxy();
|
|
70
|
-
this.isSystemProxySet = false;
|
|
71
|
-
logger.debug('system proxy unset');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
$signature = @'
|
|
2
|
-
[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)]
|
|
3
|
-
public static extern bool InternetSetOption(IntPtr hInternet, int
|
|
4
|
-
dwOption, IntPtr lpBuffer, int dwBufferLength);
|
|
5
|
-
'@
|
|
6
|
-
|
|
7
|
-
$interopHelper = Add-Type -MemberDefinition $signature -Name MyInteropHelper -PassThru
|
|
8
|
-
$INTERNET_OPTION_SETTINGS_CHANGED = 39
|
|
9
|
-
$INTERNET_OPTION_REFRESH = 37
|
|
10
|
-
|
|
11
|
-
$result1 = $interopHelper::InternetSetOption(0, $INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
|
|
12
|
-
$result2 = $interopHelper::InternetSetOption(0, $INTERNET_OPTION_REFRESH, 0, 0)
|
|
13
|
-
|
|
14
|
-
$result1 -and $result2
|
package/src/utils/analytics.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { homedir } from 'os';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
|
-
import { randomUUID } from 'crypto';
|
|
5
|
-
import packageJson from '../../package.json' with { type: 'json' };
|
|
6
|
-
|
|
7
|
-
const MEASUREMENT_ID = 'G-D1R7M2YZ8Q';
|
|
8
|
-
|
|
9
|
-
// Get this from: GA4 Admin → Data Streams → select stream → Measurement Protocol API secrets → Create
|
|
10
|
-
const API_SECRET = 'Y_lvWjBxSG2-k5UYBJQQ7Q';
|
|
11
|
-
|
|
12
|
-
const CONFIG_DIR = join(homedir(), '.config', 'greentunnel');
|
|
13
|
-
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
14
|
-
|
|
15
|
-
function getClientId() {
|
|
16
|
-
try {
|
|
17
|
-
mkdirSync(CONFIG_DIR, {recursive: true});
|
|
18
|
-
let config = {};
|
|
19
|
-
if (existsSync(CONFIG_FILE)) {
|
|
20
|
-
config = JSON.parse(readFileSync(CONFIG_FILE, 'utf8'));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!config.clientId) {
|
|
24
|
-
config.clientId = randomUUID();
|
|
25
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(config));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return config.clientId;
|
|
29
|
-
} catch {
|
|
30
|
-
return randomUUID();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function sendEvent(name, params = {}) {
|
|
35
|
-
if (!API_SECRET) return;
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
await fetch(
|
|
39
|
-
`https://www.google-analytics.com/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
|
|
40
|
-
{
|
|
41
|
-
method: 'POST',
|
|
42
|
-
body: JSON.stringify({
|
|
43
|
-
client_id: getClientId(),
|
|
44
|
-
events: [{name, params}],
|
|
45
|
-
}),
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
} catch {
|
|
49
|
-
// Analytics failures must never crash the app
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function appInit(source = 'OTHER') {
|
|
54
|
-
sendEvent('app_init', {
|
|
55
|
-
source,
|
|
56
|
-
version: packageJson.version,
|
|
57
|
-
platform: process.platform,
|
|
58
|
-
});
|
|
59
|
-
}
|
package/src/utils/buffer.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export function bufferToChunks(buffer, chunkSize, recordFragmentation) {
|
|
2
|
-
if(recordFragmentation) buffer=tlsRecordFragmentation(buffer, chunkSize)
|
|
3
|
-
const result = [];
|
|
4
|
-
const len = buffer.length;
|
|
5
|
-
let i = 0;
|
|
6
|
-
|
|
7
|
-
while (i < len) {
|
|
8
|
-
result.push(buffer.slice(i, i += chunkSize));
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return result;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* @param {Buffer} buffer
|
|
15
|
-
* @param {number} chunkSize
|
|
16
|
-
*/
|
|
17
|
-
function tlsRecordFragmentation(buffer, chunkSize) {
|
|
18
|
-
const list = []
|
|
19
|
-
const header = buffer.subarray(0,3)
|
|
20
|
-
const fullRecord = buffer.subarray(5)
|
|
21
|
-
const len = fullRecord.length
|
|
22
|
-
let i = 0
|
|
23
|
-
|
|
24
|
-
while (i < len) {
|
|
25
|
-
const record = fullRecord.subarray(i, i+chunkSize)
|
|
26
|
-
const recordLength = record.length
|
|
27
|
-
const buf = Buffer.alloc(recordLength+5)
|
|
28
|
-
header.copy(buf)
|
|
29
|
-
buf.writeUInt16BE(recordLength,3)
|
|
30
|
-
record.copy(buf,5)
|
|
31
|
-
list.push(buf)
|
|
32
|
-
i+=chunkSize
|
|
33
|
-
}
|
|
34
|
-
return Buffer.concat(list)
|
|
35
|
-
}
|
package/src/utils/socket.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import net from 'net';
|
|
2
|
-
import getLogger from '../logger.js';
|
|
3
|
-
|
|
4
|
-
const logger = getLogger('socket');
|
|
5
|
-
|
|
6
|
-
export async function createConnection(opts, dns) {
|
|
7
|
-
const ip = await dns.lookup(opts.host);
|
|
8
|
-
|
|
9
|
-
const t = new Date();
|
|
10
|
-
return new Promise(resolve => {
|
|
11
|
-
const socket = net.createConnection({...opts, host: ip}, () => {
|
|
12
|
-
logger.debug(`[Socket] connected to ${opts.host} (${ip}) (${new Date() - t} ms)`);
|
|
13
|
-
resolve(socket);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function tryWrite(socket, data, onError) {
|
|
19
|
-
try {
|
|
20
|
-
socket.write(data);
|
|
21
|
-
} catch (error) {
|
|
22
|
-
if (onError) {
|
|
23
|
-
onError(error);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function closeSocket(socket) {
|
|
29
|
-
socket.removeAllListeners('data');
|
|
30
|
-
socket.removeAllListeners('error');
|
|
31
|
-
socket.end();
|
|
32
|
-
}
|